mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-09-12 06:10:11 +02:00
Initial commit
This commit is contained in:
96
src/store/__tests__/javGameList.ts
Normal file
96
src/store/__tests__/javGameList.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import javGameList, {
|
||||
initialState,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
fetchJavGameList,
|
||||
} from "../javGameList"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
id: 5,
|
||||
titre: "6 qui prend!",
|
||||
auteur: "Wolfgang Kramer",
|
||||
editeur: "(uncredited) , Design Edge , B",
|
||||
minJoueurs: 2,
|
||||
maxJoueurs: 10,
|
||||
duree: 45,
|
||||
type: "Ambiance",
|
||||
poufpaf: "0-9-2/6-qui-prend-6-nimmt",
|
||||
photo: "https://cf.geekdo-images.com/thumb/img/lzczxR5cw7an7tRWeHdOrRtLyes=/fit-in/200x150/pic772547.jpg",
|
||||
bggPhoto: "",
|
||||
bggId: 432,
|
||||
exemplaires: 1,
|
||||
dispoPret: 1,
|
||||
nonRangee: 0,
|
||||
horodatage: "0000-00-00",
|
||||
ean: "3421272101313",
|
||||
},
|
||||
]
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("javGameList reducer", () => {
|
||||
it("should handle initial state", () => {
|
||||
// @ts-expect-error
|
||||
expect(javGameList(undefined, {})).toEqual(initialState)
|
||||
})
|
||||
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(javGameList(undefined, { type: getRequesting.type })).toEqual({
|
||||
readyStatus: "request",
|
||||
items: [],
|
||||
error: null,
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle success correctly", () => {
|
||||
expect(javGameList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "success",
|
||||
items: mockData,
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle failure correctly", () => {
|
||||
expect(javGameList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "failure",
|
||||
error: mockError,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("javGameList action", () => {
|
||||
it("fetches javGame list successful", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
{ type: getSuccess.type, payload: mockData },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchJavGameList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
it("fetches javGame list failed", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
{ type: getFailure.type, payload: mockError },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchJavGameList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
83
src/store/__tests__/userData.ts
Normal file
83
src/store/__tests__/userData.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import userData, { getRequesting, getSuccess, getFailure, fetchUserData } from "../userData"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = {
|
||||
id: 1,
|
||||
name: "PeL",
|
||||
phone: "+886 0970...",
|
||||
email: "forceoranj@gmail.com",
|
||||
website: "https://www.parisestludique.fr",
|
||||
}
|
||||
const { id } = mockData
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("userData reducer", () => {
|
||||
it("should handle initial state correctly", () => {
|
||||
// @ts-expect-error
|
||||
expect(userData(undefined, {})).toEqual({})
|
||||
})
|
||||
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(userData(undefined, { type: getRequesting.type, payload: id })).toEqual({
|
||||
[id]: { readyStatus: "request" },
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle success correctly", () => {
|
||||
expect(
|
||||
userData(undefined, {
|
||||
type: getSuccess.type,
|
||||
payload: { id, item: mockData },
|
||||
})
|
||||
).toEqual({
|
||||
[id]: { readyStatus: "success", item: mockData },
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle failure correctly", () => {
|
||||
expect(
|
||||
userData(undefined, {
|
||||
type: getFailure.type,
|
||||
payload: { id, error: mockError },
|
||||
})
|
||||
).toEqual({
|
||||
[id]: { readyStatus: "failure", error: mockError },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("userData action", () => {
|
||||
const strId = id.toString()
|
||||
|
||||
it("fetches user data successful", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type, payload: strId },
|
||||
{ type: getSuccess.type, payload: { id: strId, item: mockData } },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchUserData(strId))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
it("fetches user data failed", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type, payload: strId },
|
||||
{ type: getFailure.type, payload: { id: strId, error: mockError } },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchUserData(strId))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
84
src/store/__tests__/userList.ts
Normal file
84
src/store/__tests__/userList.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import userList, {
|
||||
initialState,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
fetchUserList,
|
||||
} from "../userList"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
id: 1,
|
||||
name: "PeL",
|
||||
phone: "+886 0970...",
|
||||
email: "forceoranj@gmail.com",
|
||||
website: "https://www.parisestludique.fr",
|
||||
},
|
||||
]
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("userList reducer", () => {
|
||||
it("should handle initial state", () => {
|
||||
// @ts-expect-error
|
||||
expect(userList(undefined, {})).toEqual(initialState)
|
||||
})
|
||||
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(userList(undefined, { type: getRequesting.type })).toEqual({
|
||||
readyStatus: "request",
|
||||
items: [],
|
||||
error: null,
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle success correctly", () => {
|
||||
expect(userList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "success",
|
||||
items: mockData,
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle failure correctly", () => {
|
||||
expect(userList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "failure",
|
||||
error: mockError,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("userList action", () => {
|
||||
it("fetches user list successful", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
{ type: getSuccess.type, payload: mockData },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchUserList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
it("fetches user list failed", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
{ type: getFailure.type, payload: mockError },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchUserList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
41
src/store/index.ts
Normal file
41
src/store/index.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { createMemoryHistory, createBrowserHistory } from "history"
|
||||
import { Action, configureStore } from "@reduxjs/toolkit"
|
||||
import { ThunkAction } from "redux-thunk"
|
||||
import { routerMiddleware } from "connected-react-router"
|
||||
|
||||
import createRootReducer from "./rootReducer"
|
||||
|
||||
interface Arg {
|
||||
initialState?: typeof window.__INITIAL_STATE__
|
||||
url?: string
|
||||
}
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const createStore = ({ initialState, url }: Arg = {}) => {
|
||||
const history = __SERVER__
|
||||
? createMemoryHistory({ initialEntries: [url || "/"] })
|
||||
: createBrowserHistory()
|
||||
const store = configureStore({
|
||||
preloadedState: initialState,
|
||||
reducer: createRootReducer(history),
|
||||
middleware: (getDefaultMiddleware) => [
|
||||
// Included default middlewares: https://redux-toolkit.js.org/api/getDefaultMiddleware#included-default-middleware
|
||||
...getDefaultMiddleware(),
|
||||
routerMiddleware(history),
|
||||
],
|
||||
devTools: __DEV__,
|
||||
})
|
||||
|
||||
return { store, history }
|
||||
}
|
||||
|
||||
const { store } = createStore()
|
||||
|
||||
export type AppState = ReturnType<typeof store.getState>
|
||||
|
||||
export type AppDispatch = typeof store.dispatch
|
||||
|
||||
export type AppThunk = ThunkAction<void, AppState, unknown, Action<string>>
|
||||
|
||||
export default createStore
|
57
src/store/javGameList.ts
Normal file
57
src/store/javGameList.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
|
||||
import { JavGame, getJavGameList } from "../services/javGames"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface JavGameList {
|
||||
readyStatus: string
|
||||
items: JavGame[]
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export const initialState: JavGameList = {
|
||||
readyStatus: "invalid",
|
||||
items: [],
|
||||
error: null,
|
||||
}
|
||||
|
||||
const javGameList = createSlice({
|
||||
name: "javGameList",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state: JavGameList) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<JavGame[]>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
state.error = payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default javGameList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = javGameList.actions
|
||||
|
||||
export const fetchJavGameList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await getJavGameList()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
} else {
|
||||
dispatch(getSuccess(data as JavGame[]))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchJavGameList = (state: AppState) => state.javGameList.readyStatus !== "success"
|
||||
|
||||
export const fetchJavGameListIfNeed = (): AppThunk => (dispatch, getState) => {
|
||||
if (shouldFetchJavGameList(getState())) return dispatch(fetchJavGameList())
|
||||
|
||||
return null
|
||||
}
|
16
src/store/rootReducer.ts
Normal file
16
src/store/rootReducer.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { History } from "history"
|
||||
import { connectRouter } from "connected-react-router"
|
||||
|
||||
import userList from "./userList"
|
||||
import userData from "./userData"
|
||||
import javGameList from "./javGameList"
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export default (history: History) => ({
|
||||
userList,
|
||||
userData,
|
||||
javGameList,
|
||||
router: connectRouter(history) as any,
|
||||
// Register more reducers...
|
||||
})
|
66
src/store/userData.ts
Normal file
66
src/store/userData.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
|
||||
import { User, getUserData } from "../services/jsonPlaceholder"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface UserDate {
|
||||
[id: string]: {
|
||||
readyStatus: string
|
||||
item?: User
|
||||
error?: string
|
||||
}
|
||||
}
|
||||
|
||||
interface Success {
|
||||
id: string
|
||||
item: User
|
||||
}
|
||||
|
||||
interface Failure {
|
||||
id: string
|
||||
error: string
|
||||
}
|
||||
|
||||
const userData = createSlice({
|
||||
name: "userData",
|
||||
initialState: {} as UserDate,
|
||||
reducers: {
|
||||
getRequesting: (state, { payload }: PayloadAction<string>) => {
|
||||
state[payload] = { readyStatus: "request" }
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Success>) => {
|
||||
state[payload.id] = { readyStatus: "success", item: payload.item }
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<Failure>) => {
|
||||
state[payload.id] = { readyStatus: "failure", error: payload.error }
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default userData.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = userData.actions
|
||||
|
||||
export const fetchUserData =
|
||||
(id: string): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting(id))
|
||||
|
||||
const { error, data } = await getUserData(id)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure({ id, error: error.message }))
|
||||
} else {
|
||||
dispatch(getSuccess({ id, item: data as User }))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchUserData = (state: AppState, id: string) =>
|
||||
state.userData[id]?.readyStatus !== "success"
|
||||
|
||||
export const fetchUserDataIfNeed =
|
||||
(id: string): AppThunk =>
|
||||
(dispatch, getState) => {
|
||||
if (shouldFetchUserData(getState(), id)) return dispatch(fetchUserData(id))
|
||||
|
||||
return null
|
||||
}
|
57
src/store/userList.ts
Normal file
57
src/store/userList.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
|
||||
import { User, getUserList } from "../services/jsonPlaceholder"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface UserList {
|
||||
readyStatus: string
|
||||
items: User[]
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export const initialState: UserList = {
|
||||
readyStatus: "invalid",
|
||||
items: [],
|
||||
error: null,
|
||||
}
|
||||
|
||||
const userList = createSlice({
|
||||
name: "userList",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state: UserList) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<User[]>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
state.error = payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default userList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = userList.actions
|
||||
|
||||
export const fetchUserList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await getUserList()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
} else {
|
||||
dispatch(getSuccess(data as User[]))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchUserList = (state: AppState) => state.userList.readyStatus !== "success"
|
||||
|
||||
export const fetchUserListIfNeed = (): AppThunk => (dispatch, getState) => {
|
||||
if (shouldFetchUserList(getState())) return dispatch(fetchUserList())
|
||||
|
||||
return null
|
||||
}
|
Reference in New Issue
Block a user