[#58] changed the error detection to prevent displaying error on first connection

This commit is contained in:
Camille Moussu
2025-08-22 10:26:51 +02:00
committed by Benoit TELLIER
parent a6c6f944a6
commit 4ba8be73b7
5 changed files with 45 additions and 35 deletions
+11 -10
View File
@@ -1,18 +1,21 @@
import { screen, waitFor } from "@testing-library/react"; import { screen, waitFor } from "@testing-library/react";
import thunk from "redux-thunk"; import thunk, { ThunkDispatch } from "redux-thunk";
import HandleLogin from "../../../src/features/User/HandleLogin"; import HandleLogin from "../../../src/features/User/HandleLogin";
import * as oidcAuth from "../../../src/features/User/oidcAuth"; import * as oidcAuth from "../../../src/features/User/oidcAuth";
import { renderWithProviders } from "../../utils/Renderwithproviders"; import { renderWithProviders } from "../../utils/Renderwithproviders";
import { clientConfig } from "../../../src/features/User/oidcAuth"; import { clientConfig } from "../../../src/features/User/oidcAuth";
import * as apiUtils from "../../../src/utils/apiUtils"; import * as apiUtils from "../../../src/utils/apiUtils";
clientConfig.url = "https://example.com"; import * as appHooks from "../../../src/app/hooks";
import { push } from "redux-first-history";
clientConfig.url = "https://example.com";
describe("HandleLogin", () => { describe("HandleLogin", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(apiUtils, "redirectTo").mockImplementation(() => {});
jest.clearAllMocks(); jest.clearAllMocks();
jest.spyOn(apiUtils, "redirectTo").mockImplementation(() => {});
const dispatch = jest.fn() as ThunkDispatch<any, any, any>;
jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch);
sessionStorage.clear(); sessionStorage.clear();
}); });
@@ -37,8 +40,6 @@ describe("HandleLogin", () => {
); );
expect(apiUtils.redirectTo).toHaveBeenCalledWith(loginUrlMock.redirectTo); expect(apiUtils.redirectTo).toHaveBeenCalledWith(loginUrlMock.redirectTo);
}); });
expect(screen.getByText(/error/i)).toBeInTheDocument();
}); });
test("shows Loading when userData exists and calendars pending is true", () => { test("shows Loading when userData exists and calendars pending is true", () => {
@@ -72,9 +73,9 @@ describe("HandleLogin", () => {
expect(screen.getByAltText("loading")).toBeInTheDocument(); expect(screen.getByAltText("loading")).toBeInTheDocument();
}); });
test("shows Error when userData doesnt exists and calendars pending is false", () => { test("goes to error page when userData doesnt exists after loading and calendars pending is false", () => {
renderWithProviders(<HandleLogin />); const dispatch = appHooks.useAppDispatch();
renderWithProviders(<HandleLogin />, { user: { loading: false } });
expect(screen.getByText("Error")).toBeInTheDocument(); expect(dispatch).toHaveBeenCalledWith(push("/error"));
}); });
}); });
+2
View File
@@ -8,6 +8,7 @@ import "./App.css";
import { Loading } from "./components/Loading/Loading"; import { Loading } from "./components/Loading/Loading";
import HandleLogin from "./features/User/HandleLogin"; import HandleLogin from "./features/User/HandleLogin";
import CalendarApp from "./components/Calendar/Calendar"; import CalendarApp from "./components/Calendar/Calendar";
import { Error } from "./components/Error/Error";
function App() { function App() {
return ( return (
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
@@ -24,6 +25,7 @@ function App() {
} }
/> />
<Route path="/callback" element={<CallbackResume />} /> <Route path="/callback" element={<CallbackResume />} />
<Route path="/error" element={<Error />} />
</Routes> </Routes>
</Router> </Router>
</Suspense> </Suspense>
-3
View File
@@ -1,6 +1,3 @@
import React from "react";
import logo from "../../static/images/calendar.svg";
export function Error() { export function Error() {
return <p>Error</p>; return <p>Error</p>;
} }
+5 -5
View File
@@ -7,12 +7,12 @@ import { push } from "redux-first-history";
import { redirectTo } from "../../utils/apiUtils"; import { redirectTo } from "../../utils/apiUtils";
export function HandleLogin() { export function HandleLogin() {
const userData = useAppSelector((state) => state.user.userData); const userData = useAppSelector((state) => state.user);
const calendars = useAppSelector((state) => state.calendars); const calendars = useAppSelector((state) => state.calendars);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
useEffect(() => { useEffect(() => {
const initiateLogin = async () => { const initiateLogin = async () => {
if (!userData) { if (!userData.userData) {
const loginurl = await Auth(); const loginurl = await Auth();
sessionStorage.setItem( sessionStorage.setItem(
@@ -30,10 +30,10 @@ export function HandleLogin() {
initiateLogin(); initiateLogin();
}, [userData]); }, [userData]);
if (!userData) { if (!calendars.pending && !userData.loading) {
return <Error />; dispatch(push("/error"));
} }
if (!calendars.pending) { if (!calendars.pending && !userData.loading) {
dispatch(push("/calendar")); dispatch(push("/calendar"));
} }
return <Loading />; return <Loading />;
+27 -17
View File
@@ -17,6 +17,7 @@ export const userSlice = createSlice({
userData: null as unknown as userData, userData: null as unknown as userData,
organiserData: null as unknown as userOrganiser, organiserData: null as unknown as userOrganiser,
tokens: null as unknown as Record<string, string>, tokens: null as unknown as Record<string, string>,
loading: true,
}, },
reducers: { reducers: {
setUserData: (state, action) => { setUserData: (state, action) => {
@@ -24,29 +25,38 @@ export const userSlice = createSlice({
if (!state.organiserData) { if (!state.organiserData) {
state.organiserData = {} as userOrganiser; state.organiserData = {} as userOrganiser;
} }
state.organiserData.cn = action.payload.name; state.organiserData.cn = action.payload.sub;
state.organiserData.cal_address = action.payload.email; state.organiserData.cal_address = `mailto:${action.payload.email}`;
state.loading = false;
}, },
setTokens: (state, action) => { setTokens: (state, action) => {
state.tokens = action.payload; state.tokens = action.payload;
}, },
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(getOpenPaasUserDataAsync.fulfilled, (state, action) => { builder
state.userData.name = action.payload.firstname; .addCase(getOpenPaasUserDataAsync.fulfilled, (state, action) => {
state.userData.family_name = action.payload.lastname; state.loading = false;
state.userData.openpaasId = action.payload.id; state.userData.name = action.payload.firstname;
if (!state.organiserData) { state.userData.family_name = action.payload.lastname;
state.organiserData = {} as userOrganiser; state.userData.openpaasId = action.payload.id;
} if (!state.organiserData) {
if (action.payload.firstname && action.payload.lastname) { state.organiserData = {} as userOrganiser;
state.organiserData.cn = `${action.payload.firstname} ${action.payload.lastname}`; }
} if (action.payload.firstname && action.payload.lastname) {
if (action.payload.preferredEmail) { state.organiserData.cn = `${action.payload.firstname} ${action.payload.lastname}`;
state.organiserData.cal_address = action.payload.preferredEmail; }
state.userData.email = action.payload.preferredEmail; if (action.payload.preferredEmail) {
} state.organiserData.cal_address = action.payload.preferredEmail;
}); state.userData.email = action.payload.preferredEmail;
}
})
.addCase(getOpenPaasUserDataAsync.pending, (state) => {
state.loading = true;
})
.addCase(getOpenPaasUserDataAsync.rejected, (state) => {
state.loading = false;
});
}, },
}); });