Implement getRegionPokemonList with queryFn and related test cases
parent
5c87c25620
commit
f4da542ecd
|
@ -114,5 +114,16 @@ describe('pokedexApi', () => {
|
|||
// @ts-ignore
|
||||
expect(pokemonListData?.previous).toBeUndefined();
|
||||
});
|
||||
|
||||
test('query getRegionPokemonList for kanto should return correct data in list', async () => {
|
||||
await store.dispatch(
|
||||
pokedexApi.endpoints.getRegionPokemonList.initiate('johto'),
|
||||
);
|
||||
|
||||
const pokemonListData = pokedexApi.endpoints.getRegionPokemonList.select(
|
||||
'johto',
|
||||
)(store.getState()).data;
|
||||
expect(pokemonListData).toHaveLength(19);
|
||||
}, 100000000000);
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"areas": [
|
||||
{
|
||||
"name": "blackthorn-city-area",
|
||||
"url": "https://pokeapi.co/api/v2/location-area/249/"
|
||||
}
|
||||
],
|
||||
"game_indices": [
|
||||
{
|
||||
"game_index": 136,
|
||||
"generation": {
|
||||
"name": "generation-iv",
|
||||
"url": "https://pokeapi.co/api/v2/generation/4/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": 65,
|
||||
"name": "blackthorn-city",
|
||||
"names": [
|
||||
{
|
||||
"language": {
|
||||
"name": "fr",
|
||||
"url": "https://pokeapi.co/api/v2/language/5/"
|
||||
},
|
||||
"name": "Ebènelle"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "en",
|
||||
"url": "https://pokeapi.co/api/v2/language/9/"
|
||||
},
|
||||
"name": "Blackthorn City"
|
||||
}
|
||||
],
|
||||
"region": { "name": "johto", "url": "https://pokeapi.co/api/v2/region/2/" }
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"areas": [
|
||||
{
|
||||
"name": "burned-tower-1f",
|
||||
"url": "https://pokeapi.co/api/v2/location-area/212/"
|
||||
},
|
||||
{
|
||||
"name": "burned-tower-b1f",
|
||||
"url": "https://pokeapi.co/api/v2/location-area/213/"
|
||||
}
|
||||
],
|
||||
"game_indices": [
|
||||
{
|
||||
"game_index": 206,
|
||||
"generation": {
|
||||
"name": "generation-iv",
|
||||
"url": "https://pokeapi.co/api/v2/generation/4/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": 66,
|
||||
"name": "burned-tower",
|
||||
"names": [
|
||||
{
|
||||
"language": {
|
||||
"name": "fr",
|
||||
"url": "https://pokeapi.co/api/v2/language/5/"
|
||||
},
|
||||
"name": "Tour Cendrée"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "en",
|
||||
"url": "https://pokeapi.co/api/v2/language/9/"
|
||||
},
|
||||
"name": "Burned Tower"
|
||||
}
|
||||
],
|
||||
"region": { "name": "johto", "url": "https://pokeapi.co/api/v2/region/2/" }
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"id": 2,
|
||||
"locations": [
|
||||
{
|
||||
"name": "blackthorn-city",
|
||||
"url": "https://pokeapi.co/api/v2/location/65/"
|
||||
},
|
||||
{ "name": "burned-tower", "url": "https://pokeapi.co/api/v2/location/66/" }
|
||||
],
|
||||
"main_generation": {
|
||||
"name": "generation-ii",
|
||||
"url": "https://pokeapi.co/api/v2/generation/2/"
|
||||
},
|
||||
"name": "johto",
|
||||
"names": [
|
||||
{
|
||||
"language": {
|
||||
"name": "ja-Hrkt",
|
||||
"url": "https://pokeapi.co/api/v2/language/1/"
|
||||
},
|
||||
"name": "ジョウト地方"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "ko",
|
||||
"url": "https://pokeapi.co/api/v2/language/3/"
|
||||
},
|
||||
"name": "성도지방"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "fr",
|
||||
"url": "https://pokeapi.co/api/v2/language/5/"
|
||||
},
|
||||
"name": "Johto"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "de",
|
||||
"url": "https://pokeapi.co/api/v2/language/6/"
|
||||
},
|
||||
"name": "Johto"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "it",
|
||||
"url": "https://pokeapi.co/api/v2/language/8/"
|
||||
},
|
||||
"name": "Johto"
|
||||
},
|
||||
{
|
||||
"language": {
|
||||
"name": "en",
|
||||
"url": "https://pokeapi.co/api/v2/language/9/"
|
||||
},
|
||||
"name": "Johto"
|
||||
}
|
||||
],
|
||||
"pokedexes": [
|
||||
{ "name": "original-johto", "url": "https://pokeapi.co/api/v2/pokedex/3/" },
|
||||
{ "name": "updated-johto", "url": "https://pokeapi.co/api/v2/pokedex/7/" }
|
||||
],
|
||||
"version_groups": [
|
||||
{
|
||||
"name": "gold-silver",
|
||||
"url": "https://pokeapi.co/api/v2/version-group/3/"
|
||||
},
|
||||
{ "name": "crystal", "url": "https://pokeapi.co/api/v2/version-group/4/" },
|
||||
{
|
||||
"name": "heartgold-soulsilver",
|
||||
"url": "https://pokeapi.co/api/v2/version-group/10/"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -4,12 +4,17 @@ import {
|
|||
pokeApiFullListFetchArgs,
|
||||
} from './paginationBaseQuery';
|
||||
import {
|
||||
AreaResponseData,
|
||||
LocationResponseData,
|
||||
PokemonListResponseData,
|
||||
PokemonResponseData,
|
||||
RegionListResponseData,
|
||||
RegionResponseData,
|
||||
TypeListResponseData,
|
||||
TypeResponseData,
|
||||
PokemonListItem,
|
||||
nameUrlPair,
|
||||
PokemonList,
|
||||
} from './types/api';
|
||||
|
||||
const pokeApiBaseQuery = async (
|
||||
|
@ -54,6 +59,69 @@ export const pokedexApi = createApi({
|
|||
getType: builder.query<TypeResponseData, number | string>({
|
||||
query: IdOrName => ({ url: `type/${IdOrName}` }),
|
||||
}),
|
||||
getLocation: builder.query<LocationResponseData, number | string>({
|
||||
query: IdOrName => ({ url: `location/${IdOrName}` }),
|
||||
}),
|
||||
getArea: builder.query<AreaResponseData, number | string>({
|
||||
query: IdOrName => ({ url: `location-area/${IdOrName}` }),
|
||||
}),
|
||||
getRegionPokemonList: builder.query<PokemonListItem[], number | string>({
|
||||
async queryFn(regionIdOrName, api) {
|
||||
// Get region data
|
||||
const regionData: RegionResponseData = await api
|
||||
.dispatch(pokedexApi.endpoints.getRegion.initiate(regionIdOrName))
|
||||
.unwrap();
|
||||
|
||||
// Get location data
|
||||
const locationDataList: LocationResponseData[] = await Promise.all(
|
||||
regionData.locations.map(location =>
|
||||
api
|
||||
.dispatch(
|
||||
pokedexApi.endpoints.getLocation.initiate(location.name),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
);
|
||||
|
||||
// Get area datas
|
||||
const areaDataList: AreaResponseData[] = await Promise.all(
|
||||
locationDataList
|
||||
.flatMap(locationData => locationData.areas)
|
||||
.map(area =>
|
||||
api
|
||||
.dispatch(pokedexApi.endpoints.getArea.initiate(area.name))
|
||||
.unwrap(),
|
||||
),
|
||||
);
|
||||
|
||||
// Collect unique Pokemon
|
||||
const uniquePokemonList = new Set<nameUrlPair>();
|
||||
areaDataList.forEach(areaData => {
|
||||
areaData.pokemon_encounters.forEach(pokemon => {
|
||||
uniquePokemonList.add(pokemon.pokemon);
|
||||
});
|
||||
});
|
||||
|
||||
// Get Pokemon data
|
||||
const pokemonDataList: PokemonListItem[] = await Promise.all(
|
||||
Array.from(uniquePokemonList).map(pokemon =>
|
||||
api
|
||||
.dispatch(pokedexApi.endpoints.getPokemon.initiate(pokemon.name))
|
||||
.unwrap()
|
||||
.then(pokemonData => {
|
||||
return {
|
||||
name: pokemonData.name,
|
||||
id: pokemonData.id,
|
||||
type: pokemonData.types.map(type => type.type.name),
|
||||
image: pokemonData.sprites.other.dream_world.front_default,
|
||||
};
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return { data: Array.from(pokemonDataList) };
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -64,4 +132,6 @@ export const {
|
|||
useGetPokemonQuery,
|
||||
useGetRegionQuery,
|
||||
useGetTypeQuery,
|
||||
useGetAreaQuery,
|
||||
useGetLocationQuery,
|
||||
} = pokedexApi;
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { PokemonProps } from './Pokemon';
|
||||
import type { RootState } from 'app/store';
|
||||
|
||||
interface PokedexState {
|
||||
selectedRegion: string;
|
||||
selectedType: string;
|
||||
selectedSort: string;
|
||||
pokemonList: PokemonProps[];
|
||||
}
|
||||
|
||||
const initialState: PokedexState = {
|
||||
selectedRegion: '',
|
||||
selectedType: '',
|
||||
selectedSort: '',
|
||||
pokemonList: [],
|
||||
};
|
||||
|
||||
export const pokedexSlice = createSlice({
|
||||
|
|
|
@ -12,6 +12,17 @@ export type PokemonListResponseData = ListResponse;
|
|||
export type RegionListResponseData = ListResponse;
|
||||
export type TypeListResponseData = ListResponse;
|
||||
|
||||
export interface PokemonListItem {
|
||||
name: string;
|
||||
id: number;
|
||||
type: string[];
|
||||
image: string;
|
||||
}
|
||||
|
||||
export interface PokemonList {
|
||||
PokemonList: PokemonListItem[];
|
||||
}
|
||||
|
||||
export interface RegionResponseData {
|
||||
// many fields are ignored
|
||||
id: number;
|
||||
|
@ -58,4 +69,32 @@ export interface PokemonResponseData {
|
|||
stats: StatItem[];
|
||||
types: typeItem[];
|
||||
weight: number;
|
||||
sprites: {
|
||||
back_default: string;
|
||||
front_default: string;
|
||||
other: {
|
||||
dream_world: {
|
||||
front_default: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface LocationResponseData {
|
||||
// many fields are ignored
|
||||
areas: nameUrlPair[];
|
||||
id: number;
|
||||
name: string;
|
||||
region: nameUrlPair;
|
||||
}
|
||||
|
||||
export interface PokemonEncounter {
|
||||
// many fields are ignored
|
||||
pokemon: nameUrlPair;
|
||||
}
|
||||
export interface AreaResponseData {
|
||||
// many fields are ignored
|
||||
id: number;
|
||||
name: string;
|
||||
pokemon_encounters: PokemonEncounter[];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,12 @@ import regionList from 'features/Pokedex/__test__/responses/regionList.json';
|
|||
import typeList from 'features/Pokedex/__test__/responses/typeList.json';
|
||||
import pokemonListPg1 from 'features/Pokedex/__test__/responses/pokemonListPage1.json';
|
||||
import pokemonListPg2 from 'features/Pokedex/__test__/responses/pokemonListPage2.json';
|
||||
import region_johto from 'features/Pokedex/__test__/responses/region_johto.json';
|
||||
import location_blackthorn_city from 'features/Pokedex/__test__/responses/location_blackthorn-city.json';
|
||||
import location_burned_tower from 'features/Pokedex/__test__/responses/location_burned-tower.json';
|
||||
import area_blackthorn_city_area from 'features/Pokedex/__test__/responses/area_blackthorn-city-area.json';
|
||||
import area_burned_tower_1f from 'features/Pokedex/__test__/responses/area_burned-tower-1f.json';
|
||||
import area_burned_tower_b1f from 'features/Pokedex/__test__/responses/area_burned-tower-b1f.json';
|
||||
|
||||
export const handlers = [
|
||||
// mock https://pokeapi.co/api/v2/region/1
|
||||
|
@ -34,4 +40,24 @@ export const handlers = [
|
|||
return res(ctx.json(pokemonListPg2));
|
||||
}
|
||||
}),
|
||||
|
||||
// getRegionPokemonList
|
||||
rest.get('https://pokeapi.co/api/v2/region/johto', (req, res, ctx) => {
|
||||
return res(ctx.json(region_johto));
|
||||
}),
|
||||
rest.get('https://pokeapi.co/api/v2/location/65', (req, res, ctx) => {
|
||||
return res(ctx.json(location_blackthorn_city));
|
||||
}),
|
||||
rest.get('https://pokeapi.co/api/v2/location/66', (req, res, ctx) => {
|
||||
return res(ctx.json(location_burned_tower));
|
||||
}),
|
||||
rest.get('https://pokeapi.co/api/v2/location-area/249', (req, res, ctx) => {
|
||||
return res(ctx.json(area_blackthorn_city_area));
|
||||
}),
|
||||
rest.get('https://pokeapi.co/api/v2/location-area/212', (req, res, ctx) => {
|
||||
return res(ctx.json(area_burned_tower_1f));
|
||||
}),
|
||||
rest.get('https://pokeapi.co/api/v2/location-area/213', (req, res, ctx) => {
|
||||
return res(ctx.json(area_burned_tower_b1f));
|
||||
}),
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue