Fix frontend bugs

This commit is contained in:
Santiago Lo Coco 2023-10-27 16:03:36 -03:00
parent a538c5f74c
commit ed6b3f2447
17 changed files with 49 additions and 249 deletions

View File

@ -1,66 +0,0 @@
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate,
}));
import "../matchMedia.mock";
import { act, renderHook } from "@testing-library/react";
import { useAuthenticateUser } from "./useAuthenticateUser";
describe("UseAuthenticateUser Hook Test", () => {
afterEach(() => {
localStorage.removeItem("token");
});
test("Hook initial state", async () => {
const { result } = renderHook(() => useAuthenticateUser());
expect(result.current.isLoading).toBeFalsy();
expect(result.current.error).toBeNull();
});
test("Hook fetch state - Authenticate function - Promise not resolved", async () => {
const { result } = renderHook(() => useAuthenticateUser());
act(() => {
result.current.authenticate({
email: "martin@gmail.com",
password: "password1234",
});
});
expect(result.current.isLoading).toBeTruthy();
expect(result.current.error).toBeNull();
});
test("Hook fetch state - Authenticate function - Promise success", async () => {
const { result } = renderHook(() => useAuthenticateUser());
await act(async () => {
await result.current.authenticate({
email: "martin@gmail.com",
password: "password1234",
});
});
expect(localStorage.getItem("token")).not.toBeNull();
expect(result.current.isLoading).toBeFalsy();
expect(result.current.error).not.toBeNull();
});
test("Hook fetch state - Authenticate function - Promise failed", async () => {
const { result } = renderHook(() => useAuthenticateUser());
await act(async () => {
await result.current.authenticate({
email: "notExistingUser",
password: "notExistingUser",
});
});
expect(localStorage.getItem("token")).toBe("undefined");
expect(result.current.isLoading).toBeFalsy();
expect(result.current.error).not.toBeNull();
});
});

View File

@ -1,80 +0,0 @@
import React, { useEffect } from "react";
import { useState } from "react";
import { Credentials, User, TokenData } from "../Types";
import { useNavigate } from "react-router-dom";
import { fetchUserById, logIn } from "../Api";
import { tokenStatus } from "../Api";
import jwt_decode from "jwt-decode";
export const useAuthenticateUser = () => {
const [isLoading, setIsLoading] = useState(false);
const [isAirline, setIsAirline] = useState(false);
const [user, setUser] = useState<User | null>(null);
const [error, setError] = useState<string | null>(null);
const [tokenValidated, setTokenValidated] = useState(false);
const navigate = useNavigate();
const authenticate = async (credentials: Credentials): Promise<void> => {
if (!user) {
try {
setIsLoading(true);
setError(null);
const tokens = await logIn(credentials);
localStorage.setItem("token", tokens.access_token);
const airline = (jwt_decode(tokens.access_token) as TokenData).airline;
setIsAirline(airline)
if (tokens.user_id) {
const user = await fetchUserById(tokens.user_id);
setUser(user);
} else {
setError(tokens.message!.split(".")[0] + ".");
setUser(null);
}
} catch (error) {
setError(error as string);
} finally {
setIsLoading(false);
navigate("/home")
}
}
};
const validateToken = async () => {
try {
setIsLoading(true);
const existingToken = localStorage.getItem("token");
if (existingToken && !tokenValidated) {
const response = await tokenStatus(existingToken);
const { message } = response;
if (message) throw new Error("Invalid token");
const airline = (jwt_decode(existingToken) as TokenData).airline;
setIsAirline(airline)
const user = await fetchUserById(response.id);
setUser(user);
}
setTokenValidated(true);
} catch (error) {
logout();
} finally {
setIsLoading(false);
}
return user;
};
const logout = () => {
localStorage.removeItem("token");
setUser(null);
setTokenValidated(false)
navigate("/login");
};
return { user, isLoading, authenticate, validateToken, isAirline, logout, error };
};

View File

@ -37,9 +37,15 @@ import jwt_decode from "jwt-decode";
useEffect(() => {
const existingToken = localStorage.getItem("token");
if (existingToken) {
const airline = (jwt_decode(existingToken) as TokenData).airline;
setIsAirline(airline)
let airline
try {
airline = (jwt_decode(existingToken) as TokenData).airline;
setIsAirline(airline)
} catch (err) {
setLoadingInitial(false);
logout()
return;
}
tokenStatus(existingToken)
.then((res) => fetchUserById(res.id)
@ -47,7 +53,10 @@ import jwt_decode from "jwt-decode";
.catch((_error) => {})
.finally(() => setLoadingInitial(false))
)
.catch((_error) => {})
.catch((_error) => {
setLoadingInitial(false)
logout()
})
// .finally(() => setLoadingInitial(false));
} else {
setLoadingInitial(false)

View File

@ -9,9 +9,6 @@ from src.api.cruds import flight as flight_crud
from src.api.db import get_db
from src.api.schemas.flight import Flight, FlightCreate, FlightStatusUpdate
# from copy import copy
router = APIRouter()

View File

@ -3,4 +3,4 @@ fastapi[all]==0.103.2
pyjwt==2.6.0
gunicorn==20.1.0
requests==2.31.0
aiohttp==3.8.6
asyncreq==0.0.4

View File

@ -1,11 +1,11 @@
from typing import Annotated
from asyncreq import request
from fastapi import APIRouter, Header, HTTPException
from src.api.config import API_AUTH
from src.api.schemas.auth import RefreshToken, Token
from src.api.schemas.user import UserLogin, UserMin, UserRegister
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,11 +1,11 @@
from typing import Annotated, Optional
from asyncreq import request
from fastapi import APIRouter, Header, HTTPException
from src.api.config import API_FLIGHTS, API_MESSAGES
from src.api.routes.auth import status as checkAuth
from src.api.schemas.flight import Flight, FlightCreate, FlightStatusUpdate
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,8 +1,8 @@
from asyncreq import request
from fastapi import APIRouter, HTTPException
from src.api.config import API_NOTIFICATIONS
from src.api.schemas.notification import Update as Message
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,11 +1,11 @@
from typing import Annotated
from asyncreq import request
from fastapi import APIRouter, Header, HTTPException
from src.api.config import API_SUBSCRIPTIONS
from src.api.routes.auth import status as checkAuth
from src.api.schemas.subscriptions import Subscription
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,8 +1,8 @@
from asyncreq import request
from fastapi import APIRouter, HTTPException
from src.api.config import API_USERS
from src.api.schemas.user import User, UserRegister
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,40 +0,0 @@
from typing import Optional
import aiohttp
import async_timeout
from aiohttp import ClientConnectorError, ContentTypeError, JsonPayload
from fastapi import HTTPException, Response
async def make_request(
url: str,
method: str,
headers: dict = None,
query: Optional[dict] = None,
data: str = None,
json: JsonPayload = None,
timeout: int = 60,
):
async with async_timeout.timeout(delay=timeout):
async with aiohttp.ClientSession(headers=headers) as session:
async with session.request(
method=method, url=url, params=query, data=data, json=json
) as response:
if response.status == 204:
response_json = Response(status_code=204)
else:
response_json = await response.json()
decoded_json = response_json
return decoded_json, response.status, response.headers
async def request(url, method, headers=None, data=None, json=None, query=None):
try:
(x, y, z) = await make_request(
url=url, method=method, headers=headers, data=data, json=json, query=query
)
except ClientConnectorError:
raise HTTPException(status_code=503, detail="Service is unavailable.")
except ContentTypeError:
raise HTTPException(status_code=500, detail="Service error.")
return x, y, z

View File

@ -60,7 +60,7 @@ export const addData = <T>(storeName: string, data: T): Promise<T|string|null> =
});
};
export const deleteData = (storeName: string, key: string): Promise<boolean> => {
export const deleteData = (storeName: string, key: number): Promise<boolean> => {
return new Promise((resolve) => {
request = indexedDB.open('myDB', version);
@ -80,7 +80,7 @@ export const deleteData = (storeName: string, key: string): Promise<boolean> =>
});
};
export const updateData = <T>(storeName: string, key: string, data: T): Promise<T|string|null> => {
export const updateData = <T>(storeName: string, key: number, data: T): Promise<T|string|null> => {
return new Promise((resolve) => {
request = indexedDB.open('myDB', version);

View File

@ -7,6 +7,7 @@ import { Stores, addData, deleteData, getStoreData, updateData, initDB } from '.
export const useFetchZones = () => {
const [error, setError] = useState<string | null>(null);
const [zones, setZones] = useState<Flight[]>([]);
let origin = process.env.REACT_APP_ORIGIN;
useEffect(() => {
@ -22,10 +23,14 @@ export const useFetchZones = () => {
fetchZones(origin, null)
.then((data) => {
localStorage.setItem('lastUpdated', newUpdate)
setZones(data);
let toAdd: Flight[] = []
data.map((u) => {
addData(Stores.Flight, u)
if (u.status != 'Deleted') {
addData(Stores.Flight, u)
toAdd.push(u)
}
})
setZones(toAdd);
})
.catch((error) => {});
}
@ -42,20 +47,32 @@ export const useFetchZones = () => {
.then((data) => {
localStorage.setItem('lastUpdated', newUpdate)
let toAdd: Flight[] = []
let toRemove: Flight[] = []
zones.forEach((c, i) => {
let index = data.findIndex(x => x.id === c.id)
if (index >= 0) {
toAdd.push(data[index]);
console.log(",aria")
updateData(Stores.Flight, String(c.id), data[index])
console.log(data[index].status)
if (data[index].status == 'Deleted') {
console.log("sacamos")
toRemove.push(data[index])
deleteData(Stores.Flight, c.id)
} else {
toAdd.push(data[index]);
updateData(Stores.Flight, c.id, data[index])
}
} else {
toAdd.push(c);
if (c.status == 'Deleted') {
toRemove.push(c);
} else {
toAdd.push(c);
}
}
});
console.log(toAdd)
let filtered = data.filter(o => !toAdd.some(b => { return o.id === b.id} ))
console.log(toRemove)
let filtered = data.filter(o => !toAdd.some(b => { return o.id === b.id}) && !toRemove.some(b => { return o.id === b.id}))
const newArray = toAdd.concat(filtered);
filtered.forEach(c => {
addData(Stores.Flight, c)

View File

@ -4,4 +4,4 @@ psycopg2-binary==2.9.5
pyjwt==2.6.0
gunicorn==20.1.0
sqlalchemy==2.0.22
aiohttp==3.8.6
asyncreq==0.0.4

View File

@ -1,5 +1,6 @@
import re
from asyncreq import request
from fastapi import APIRouter, BackgroundTasks, Depends, Response
from sqlalchemy.orm import Session
@ -7,10 +8,9 @@ from src.api.config import API_FLIGHTS
from src.api.cruds import chat as notif_crud
from src.api.cruds import subscription as subs_crud
from src.api.db import get_db
from src.api.schemas.chat import Chat, FlightData, Update
from src.api.schemas.chat import Chat, Update
from src.api.utils import telegram
from src.api.utils.messages import get_flight_message
from src.api.utils.network import request
router = APIRouter()

View File

@ -1,37 +0,0 @@
from typing import Optional
import aiohttp
import async_timeout
from aiohttp import ClientConnectorError, ContentTypeError, JsonPayload
from fastapi import HTTPException
async def make_request(
url: str,
method: str,
headers: dict = None,
query: Optional[dict] = None,
data: str = None,
json: JsonPayload = None,
timeout: int = 60,
):
async with async_timeout.timeout(delay=timeout):
async with aiohttp.ClientSession(headers=headers) as session:
async with session.request(
method=method, url=url, params=query, data=data, json=json
) as response:
response_json = await response.json()
decoded_json = response_json
return decoded_json, response.status, response.headers
async def request(url, method, headers=None, data=None, json=None, query=None):
try:
(x, y, z) = await make_request(
url=url, method=method, headers=headers, data=data, json=json, query=query
)
except ClientConnectorError:
raise HTTPException(status_code=503, detail="Service is unavailable.")
except ContentTypeError:
raise HTTPException(status_code=500, detail="Service error.")
return x, y, z

View File

@ -1,6 +1,6 @@
import os
from src.api.utils.network import request
from asyncreq import request
TOKEN = os.getenv("TOKEN")