Compare commits

..

No commits in common. "fa0d194b740d3713403ce3128617d16946f8f632" and "3faf494bd08a4288fdca0739d4734d58a9532373" have entirely different histories.

9 changed files with 62 additions and 56 deletions

View File

@ -1,7 +1,7 @@
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
import { pokeRestApi } from 'app/services/pokeRestApi';
import { pokeApi } from 'app/services/pokeApi';
import { filterSlice } from 'features/Filters/filterSlice';
import { getIdFromUrl } from 'app/services/pokeRestApi';
import { getIdFromUrl } from 'app/services/pokeApi';
import { configureStore } from '@reduxjs/toolkit';
@ -15,25 +15,25 @@ import {
let store: AppStore;
describe('pokeRestApi', () => {
describe('pokeApi', () => {
beforeEach(() => {
store = configureStore({
reducer: {
pokedex: pokedexSlice.reducer,
filter: filterSlice.reducer,
[pokeRestApi.reducerPath]: pokeRestApi.reducer,
[pokeApi.reducerPath]: pokeApi.reducer,
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware().concat(pokeRestApi.middleware),
getDefaultMiddleware().concat(pokeApi.middleware),
});
});
describe('JEST test against mock API', () => {
describe('test getPokemon query', () => {
test('visit https://pokeapi.co/api/v2/pokemon/85 returns Dodrio', async () => {
await store.dispatch(pokeRestApi.endpoints.getPokemon.initiate(85));
await store.dispatch(pokeApi.endpoints.getPokemon.initiate(85));
const pokemon = pokeRestApi.endpoints.getPokemon.select(85)(
const pokemon = pokeApi.endpoints.getPokemon.select(85)(
store.getState(),
).data as PokemonResponseData;
expect(pokemon?.name).toBe('dodrio');
@ -48,13 +48,11 @@ describe('pokeRestApi', () => {
describe('test getPokemonSpecies query', () => {
test('visit https://pokeapi.co/api/v2/pokemon-species/6/', async () => {
await store.dispatch(
pokeRestApi.endpoints.getPokemonSpecies.initiate(6),
);
await store.dispatch(pokeApi.endpoints.getPokemonSpecies.initiate(6));
const pokemonSpecies = pokeRestApi.endpoints.getPokemonSpecies.select(
6,
)(store.getState()).data as PokemonSpeciesResponseData;
const pokemonSpecies = pokeApi.endpoints.getPokemonSpecies.select(6)(
store.getState(),
).data as PokemonSpeciesResponseData;
expect(pokemonSpecies?.evolution_chain.url).toBe(
'https://pokeapi.co/api/v2/evolution-chain/2/',
);
@ -64,13 +62,13 @@ describe('pokeRestApi', () => {
describe('test getPokemonSpecies query', () => {
test('visit https://pokeapi.co/api/v2/pokemon-species/6/', async () => {
await store.dispatch(
pokeRestApi.endpoints.getPokemonSpeciesFromUrl.initiate(
pokeApi.endpoints.getPokemonSpeciesFromUrl.initiate(
'https://pokeapi.co/api/v2/pokemon-species/6/',
),
);
const pokemonSpecies =
pokeRestApi.endpoints.getPokemonSpeciesFromUrl.select(
pokeApi.endpoints.getPokemonSpeciesFromUrl.select(
'https://pokeapi.co/api/v2/pokemon-species/6/',
)(store.getState()).data as PokemonSpeciesResponseData;
expect(pokemonSpecies?.evolution_chain.url).toBe(
@ -81,9 +79,9 @@ describe('pokeRestApi', () => {
describe('test getTypeList query', () => {
test('visit https://pokeapi.co/api/v2/type should return correct data in list', async () => {
await store.dispatch(pokeRestApi.endpoints.getTypeList.initiate());
await store.dispatch(pokeApi.endpoints.getTypeList.initiate());
const typeListData = pokeRestApi.endpoints.getTypeList.select()(
const typeListData = pokeApi.endpoints.getTypeList.select()(
store.getState(),
).data as TypeListResponseData;
expect(typeListData?.results).toHaveLength(typeListData.count + 1);
@ -92,13 +90,11 @@ describe('pokeRestApi', () => {
describe('test getEvolutionChain query', () => {
test('visit https://pokeapi.co/api/v2/evolution-chain/2/', async () => {
await store.dispatch(
pokeRestApi.endpoints.getEvolutionChain.initiate(2),
);
await store.dispatch(pokeApi.endpoints.getEvolutionChain.initiate(2));
const evolutionChainData =
pokeRestApi.endpoints.getEvolutionChain.select(2)(store.getState())
.data as EvolutionChainResponseData;
const evolutionChainData = pokeApi.endpoints.getEvolutionChain.select(
2,
)(store.getState()).data as EvolutionChainResponseData;
expect(evolutionChainData?.chain.species.url).toBe(
'https://pokeapi.co/api/v2/pokemon-species/4/',
);
@ -114,13 +110,13 @@ describe('pokeRestApi', () => {
describe('test getEvolutionChainFromUrl query', () => {
test('visit https://pokeapi.co/api/v2/evolution-chain/2/', async () => {
await store.dispatch(
pokeRestApi.endpoints.getEvolutionChainFromUrl.initiate(
pokeApi.endpoints.getEvolutionChainFromUrl.initiate(
'https://pokeapi.co/api/v2/evolution-chain/2/',
),
);
const evolutionChainData =
pokeRestApi.endpoints.getEvolutionChainFromUrl.select(
pokeApi.endpoints.getEvolutionChainFromUrl.select(
'https://pokeapi.co/api/v2/evolution-chain/2/',
)(store.getState()).data as EvolutionChainResponseData;
expect(evolutionChainData?.chain.species.url).toBe(

View File

@ -12,8 +12,8 @@ export const getIdFromUrl = (url: string) => {
return parseInt(urlParts[urlParts.length - 2]);
};
export const pokeRestApi = createApi({
reducerPath: 'pokeRestApi',
export const pokeApi = createApi({
reducerPath: 'pokeApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: builder => ({
getTypeList: builder.query<TypeListResponseData, void>({
@ -54,4 +54,4 @@ export const {
useGetPokemonSpeciesFromUrlQuery,
useGetEvolutionChainQuery,
useGetEvolutionChainFromUrlQuery,
} = pokeRestApi;
} = pokeApi;

View File

@ -2,7 +2,7 @@ import { configureStore } from '@reduxjs/toolkit';
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
import { filterSlice } from 'features/Filters/filterSlice';
import { infoDialogSlice } from 'features/InfoDialog/infoDialogSlice';
import { pokeRestApi } from './services/pokeRestApi';
import { pokeApi } from './services/pokeApi';
export const store = configureStore({
reducer: {
@ -12,10 +12,10 @@ export const store = configureStore({
infoDialog: infoDialogSlice.reducer,
// api slices
[pokeRestApi.reducerPath]: pokeRestApi.reducer,
[pokeApi.reducerPath]: pokeApi.reducer,
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware().concat(pokeRestApi.middleware),
getDefaultMiddleware().concat(pokeApi.middleware),
devTools: true,
});

View File

@ -3,8 +3,8 @@ import { motion } from 'framer-motion';
import './EvolutionSpecies.css';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import { colorTypeGradients } from 'components/utils';
import { useAppDispatch } from 'app/hooks';
import { fetchSelectedPokemonInfo } from 'features/InfoDialog/infoDialogSlice';
import { useAppDispatch } from '../../app/hooks';
import { fetchSelectedPokemonInfo } from '../../features/InfoDialog/infoDialogSlice';
export type EvolutionSpeciesProps = {
types: string[];

View File

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { useAppDispatch, useAppSelector } from 'app/hooks';
import { fetchPokemonsInTheRegion } from 'features/Pokedex/pokedexSlice';
import {
setSelectedRegion,
@ -8,7 +9,7 @@ import {
setSearchInput,
initializeFilterSlice,
} from './filterSlice';
import { useGetTypeListQuery } from 'app/services/pokeRestApi';
import { useGetTypeListQuery } from 'app/services/pokeApi';
import { RegionPokemonRange } from './types/slice';
import './Filters.css';
@ -53,7 +54,10 @@ const Filters = () => {
<div>REGION</div>
<select
name="regionSelect"
onChange={e => dispatch(setSelectedRegion(e.target.value))}
onChange={e => {
dispatch(setSelectedRegion(e.target.value));
dispatch(fetchPokemonsInTheRegion(e.target.value));
}}
value={selectedRegion}
>
{createRegionPokemonListOptionElements(regionOptions)}

View File

@ -6,8 +6,9 @@ import {
} from '@reduxjs/toolkit';
import { FilterState } from './types/slice';
import { RegionPokemonRange } from './types/slice';
import { pokeRestApi } from 'app/services/pokeRestApi';
import { fetchPokemonsInTheRegion } from 'features/Pokedex/pokedexSlice';
import { pokeApi } from 'app/services/pokeApi';
pokeApi.endpoints.getTypeList.initiate(); // initialize type list fetching
const initialState: FilterState = {
regionOptions: [],
@ -35,7 +36,7 @@ export const initializeFilterSlice = createAsyncThunk(
{ region: 'galar', startId: 810, endId: 898 },
];
dispatch(pokeRestApi.endpoints.getTypeList.initiate());
dispatch(pokeApi.endpoints.getTypeList.initiate());
const sortOptions = [
{ name: 'ID', value: 'id' },
@ -52,7 +53,6 @@ export const filterSlice: Slice<FilterState> = createSlice({
reducers: {
setSelectedRegion: (state, action: PayloadAction<string>) => {
state.selectedRegion = action.payload;
fetchPokemonsInTheRegion(state.selectedRegion);
},
setSelectedType: (state, action: PayloadAction<string>) => {
state.selectedType = action.payload;
@ -87,7 +87,7 @@ export const filterSlice: Slice<FilterState> = createSlice({
}
});
builder.addMatcher(
pokeRestApi.endpoints.getTypeList.matchFulfilled,
pokeApi.endpoints.getTypeList.matchFulfilled,
(state, action) => {
if (action.payload && action.payload.results.length > 0) {
const regionListResults = action.payload.results;

View File

@ -1,7 +1,7 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import type { Slice, PayloadAction } from '@reduxjs/toolkit';
import { pokeRestApi } from 'app/services/pokeRestApi';
import { pokeApi } from 'app/services/pokeApi';
import { EvolutionSpeciesProps } from 'components/EvolutionSpecies';
import { Stat } from 'components/InfoDialogComponent';
import {
@ -119,19 +119,19 @@ export const fetchSelectedPokemonInfo = createAsyncThunk(
try {
const selectedPokemon = await dispatch(
pokeRestApi.endpoints.getPokemon.initiate(pokemonIdOrName),
pokeApi.endpoints.getPokemon.initiate(pokemonIdOrName),
);
if (selectedPokemon.data) {
const selectedPokemonSpecies = await dispatch(
pokeRestApi.endpoints.getPokemonSpeciesFromUrl.initiate(
pokeApi.endpoints.getPokemonSpeciesFromUrl.initiate(
selectedPokemon.data.species.url,
),
);
if (selectedPokemonSpecies.data) {
const selectedPokemonEvolutionChain = await dispatch(
pokeRestApi.endpoints.getEvolutionChainFromUrl.initiate(
pokeApi.endpoints.getEvolutionChainFromUrl.initiate(
selectedPokemonSpecies.data.evolution_chain.url,
),
);
@ -146,7 +146,7 @@ export const fetchSelectedPokemonInfo = createAsyncThunk(
await Promise.all(
evolutionChainName.map(async name => {
const evolutionChainPokemon = await dispatch(
pokeRestApi.endpoints.getPokemon.initiate(name),
pokeApi.endpoints.getPokemon.initiate(name),
);
if (evolutionChainPokemon.data) {
evolutionChain.push({

View File

@ -10,7 +10,7 @@ import { AppStore } from 'app/store';
import { configureStore } from '@reduxjs/toolkit';
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
import { filterSlice } from 'features/Filters/filterSlice';
import { pokeRestApi } from 'app/services/pokeRestApi';
import { pokeApi } from 'app/services/pokeApi';
let store: AppStore;
@ -20,10 +20,10 @@ describe('pokedex Component', () => {
reducer: {
pokedex: pokedexSlice.reducer,
filter: filterSlice.reducer,
[pokeRestApi.reducerPath]: pokeRestApi.reducer,
[pokeApi.reducerPath]: pokeApi.reducer,
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware().concat(pokeRestApi.middleware),
getDefaultMiddleware().concat(pokeApi.middleware),
});
});

View File

@ -1,11 +1,10 @@
import type { PayloadAction, Slice } from '@reduxjs/toolkit';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import type { Slice, PayloadAction } from '@reduxjs/toolkit';
import { PokedexStateProps } from 'features/Pokedex/types/slice';
import { getStartAndEndIdsForRegion } from './utils';
import { PokemonResponseData } from 'types/api';
import { pokeRestApi } from 'app/services/pokeRestApi';
import { RootState } from 'app/store';
export const fetchPokemonsInTheRegion = createAsyncThunk<
@ -23,14 +22,21 @@ export const fetchPokemonsInTheRegion = createAsyncThunk<
{ length: endId - startId + 1 },
(_, i) => i + startId,
);
const pokemonList = pokemonIds.map(id =>
dispatch(pokeRestApi.endpoints.getPokemon.initiate(id))
.unwrap()
.then(data => data),
// use pokemonIds to fetch pokemon data using fetch, which won't save the data in the cache
const pokemonList = await Promise.all(
pokemonIds.map(
id =>
fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then(res =>
res.json(),
) as Promise<PokemonResponseData>,
),
);
return await Promise.all(pokemonList);
const pokemonListData = pokemonList.map(
(pokemon: PokemonResponseData) => pokemon,
);
return pokemonListData;
});
export const initialState: PokedexStateProps = {