Initial commit

This commit is contained in:
forceoranj
2021-10-16 01:53:56 +02:00
commit ebdd8dccdd
104 changed files with 29770 additions and 0 deletions

View 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)
})
})

View 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)
})
})

View 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
View 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
View 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
View 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
View 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
View 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
}