Skip to content
Snippets Groups Projects
Commit abda0046 authored by mateusz-winiarczyk's avatar mateusz-winiarczyk
Browse files

feat(overlays): MIN-191 add possibility to login

parent a185dfbb
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!79feat(overlays): MIN-191 add possibility to login
import { rootSelector } from '@/redux/root/root.selectors';
import { createSelector } from '@reduxjs/toolkit';
export const userSelector = createSelector(rootSelector, state => state.user);
export const authenticatedUserSelector = createSelector(userSelector, state => state.authenticated);
export const loadingUserSelector = createSelector(userSelector, state => state.loading);
import { createSlice } from '@reduxjs/toolkit';
import { getSessionValidReducer, loginReducer } from './user.reducers';
import { UserState } from './user.types';
export const initialState: UserState = {
loading: 'idle',
authenticated: false,
error: { name: '', message: '' },
login: null,
};
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: builder => {
loginReducer(builder);
getSessionValidReducer(builder);
},
});
export default userSlice.reducer;
import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
import { HttpStatusCode } from 'axios';
import { loginFixture } from '@/models/fixtures/loginFixture';
import {
ToolkitStoreWithSingleSlice,
createStoreInstanceUsingSliceReducer,
} from '@/utils/createStoreInstanceUsingSliceReducer';
import { apiPath } from '../apiPath';
import { closeModal } from '../modal/modal.slice';
import userReducer from './user.slice';
import { UserState } from './user.types';
import { login } from './user.thunks';
const mockedAxiosClient = mockNetworkResponse();
const CREDENTIALS = {
login: 'test',
password: 'password',
};
describe('login thunk', () => {
let store = {} as ToolkitStoreWithSingleSlice<UserState>;
beforeEach(() => {
store = createStoreInstanceUsingSliceReducer('user', userReducer);
});
it('dispatches closeModal action on successful login with valid data', async () => {
mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
const mockDispatch = jest.fn(action => {
if (action.type === closeModal.type) {
expect(action).toEqual(closeModal());
}
});
store.dispatch = mockDispatch;
await store.dispatch(login(CREDENTIALS));
});
it('does not dispatch closeModal action on failed login with invalid data', async () => {
mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.NotFound, loginFixture);
const mockDispatch = jest.fn(action => {
if (action.type === closeModal.type) {
expect(action).not.toEqual(closeModal());
}
});
store.dispatch = mockDispatch;
await store.dispatch(login(CREDENTIALS));
});
});
import { axiosInstance } from '@/services/api/utils/axiosInstance';
import { createAsyncThunk } from '@reduxjs/toolkit';
import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
import { loginSchema } from '@/models/loginSchema';
import { sessionSchemaValid } from '@/models/sessionValidSchema';
import { apiPath } from '../apiPath';
import { closeModal } from '../modal/modal.slice';
export const login = createAsyncThunk(
'user/login',
async (credentials: { login: string; password: string }, { dispatch }) => {
const searchParams = new URLSearchParams(credentials);
const response = await axiosInstance.post(apiPath.postLogin(), searchParams, {
withCredentials: true,
});
const isDataValid = validateDataUsingZodSchema(response.data, loginSchema);
dispatch(closeModal());
return isDataValid ? response.data : undefined;
},
);
export const getSessionValid = createAsyncThunk('user/getSessionValid', async () => {
const response = await axiosInstance.get(apiPath.getSessionValid(), {
withCredentials: true,
});
const isDataValid = validateDataUsingZodSchema(response.data, sessionSchemaValid);
return isDataValid ? response.data : undefined;
});
import { Loading } from '@/types/loadingState';
export type UserState = {
loading: Loading;
error: Error;
authenticated: boolean;
login: null | string;
};
export type ModalName = 'none' | 'overview-images'; export type ModalName = 'none' | 'overview-images' | 'login';
...@@ -7,6 +7,7 @@ import { configurationOptionSchema } from '@/models/configurationOptionSchema'; ...@@ -7,6 +7,7 @@ import { configurationOptionSchema } from '@/models/configurationOptionSchema';
import { disease } from '@/models/disease'; import { disease } from '@/models/disease';
import { drugSchema } from '@/models/drugSchema'; import { drugSchema } from '@/models/drugSchema';
import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult'; import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult';
import { loginSchema } from '@/models/loginSchema';
import { mapBackground } from '@/models/mapBackground'; import { mapBackground } from '@/models/mapBackground';
import { mapOverlay } from '@/models/mapOverlay'; import { mapOverlay } from '@/models/mapOverlay';
import { mapModelSchema } from '@/models/modelSchema'; import { mapModelSchema } from '@/models/modelSchema';
...@@ -22,6 +23,7 @@ import { projectSchema } from '@/models/project'; ...@@ -22,6 +23,7 @@ import { projectSchema } from '@/models/project';
import { reactionSchema } from '@/models/reaction'; import { reactionSchema } from '@/models/reaction';
import { reactionLineSchema } from '@/models/reactionLineSchema'; import { reactionLineSchema } from '@/models/reactionLineSchema';
import { referenceSchema } from '@/models/referenceSchema'; import { referenceSchema } from '@/models/referenceSchema';
import { sessionSchemaValid } from '@/models/sessionValidSchema';
import { targetSchema } from '@/models/targetSchema'; import { targetSchema } from '@/models/targetSchema';
import { z } from 'zod'; import { z } from 'zod';
...@@ -46,6 +48,8 @@ export type Reference = z.infer<typeof referenceSchema>; ...@@ -46,6 +48,8 @@ export type Reference = z.infer<typeof referenceSchema>;
export type ReactionLine = z.infer<typeof reactionLineSchema>; export type ReactionLine = z.infer<typeof reactionLineSchema>;
export type ElementSearchResult = z.infer<typeof elementSearchResult>; export type ElementSearchResult = z.infer<typeof elementSearchResult>;
export type ElementSearchResultType = z.infer<typeof elementSearchResultType>; export type ElementSearchResultType = z.infer<typeof elementSearchResultType>;
export type SessionValid = z.infer<typeof sessionSchemaValid>;
export type Login = z.infer<typeof loginSchema>;
export type ConfigurationOption = z.infer<typeof configurationOptionSchema>; export type ConfigurationOption = z.infer<typeof configurationOptionSchema>;
export type OverlayBioEntity = z.infer<typeof overlayBioEntitySchema>; export type OverlayBioEntity = z.infer<typeof overlayBioEntitySchema>;
export type Color = z.infer<typeof colorSchema>; export type Color = z.infer<typeof colorSchema>;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment