Implement getRegionPokemonList with queryFn and related test cases
parent
5c87c25620
commit
f4da542ecd
|
@ -114,5 +114,16 @@ describe('pokedexApi', () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
expect(pokemonListData?.previous).toBeUndefined();
|
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,
|
pokeApiFullListFetchArgs,
|
||||||
} from './paginationBaseQuery';
|
} from './paginationBaseQuery';
|
||||||
import {
|
import {
|
||||||
|
AreaResponseData,
|
||||||
|
LocationResponseData,
|
||||||
PokemonListResponseData,
|
PokemonListResponseData,
|
||||||
PokemonResponseData,
|
PokemonResponseData,
|
||||||
RegionListResponseData,
|
RegionListResponseData,
|
||||||
RegionResponseData,
|
RegionResponseData,
|
||||||
TypeListResponseData,
|
TypeListResponseData,
|
||||||
TypeResponseData,
|
TypeResponseData,
|
||||||
|
PokemonListItem,
|
||||||
|
nameUrlPair,
|
||||||
|
PokemonList,
|
||||||
} from './types/api';
|
} from './types/api';
|
||||||
|
|
||||||
const pokeApiBaseQuery = async (
|
const pokeApiBaseQuery = async (
|
||||||
|
@ -54,6 +59,69 @@ export const pokedexApi = createApi({
|
||||||
getType: builder.query<TypeResponseData, number | string>({
|
getType: builder.query<TypeResponseData, number | string>({
|
||||||
query: IdOrName => ({ url: `type/${IdOrName}` }),
|
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,
|
useGetPokemonQuery,
|
||||||
useGetRegionQuery,
|
useGetRegionQuery,
|
||||||
useGetTypeQuery,
|
useGetTypeQuery,
|
||||||
|
useGetAreaQuery,
|
||||||
|
useGetLocationQuery,
|
||||||
} = pokedexApi;
|
} = pokedexApi;
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
import { PokemonProps } from './Pokemon';
|
||||||
import type { RootState } from 'app/store';
|
import type { RootState } from 'app/store';
|
||||||
|
|
||||||
interface PokedexState {
|
interface PokedexState {
|
||||||
selectedRegion: string;
|
selectedRegion: string;
|
||||||
selectedType: string;
|
selectedType: string;
|
||||||
selectedSort: string;
|
selectedSort: string;
|
||||||
|
pokemonList: PokemonProps[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: PokedexState = {
|
const initialState: PokedexState = {
|
||||||
selectedRegion: '',
|
selectedRegion: '',
|
||||||
selectedType: '',
|
selectedType: '',
|
||||||
selectedSort: '',
|
selectedSort: '',
|
||||||
|
pokemonList: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pokedexSlice = createSlice({
|
export const pokedexSlice = createSlice({
|
||||||
|
|
|
@ -12,6 +12,17 @@ export type PokemonListResponseData = ListResponse;
|
||||||
export type RegionListResponseData = ListResponse;
|
export type RegionListResponseData = ListResponse;
|
||||||
export type TypeListResponseData = ListResponse;
|
export type TypeListResponseData = ListResponse;
|
||||||
|
|
||||||
|
export interface PokemonListItem {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
type: string[];
|
||||||
|
image: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PokemonList {
|
||||||
|
PokemonList: PokemonListItem[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface RegionResponseData {
|
export interface RegionResponseData {
|
||||||
// many fields are ignored
|
// many fields are ignored
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -58,4 +69,32 @@ export interface PokemonResponseData {
|
||||||
stats: StatItem[];
|
stats: StatItem[];
|
||||||
types: typeItem[];
|
types: typeItem[];
|
||||||
weight: number;
|
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 typeList from 'features/Pokedex/__test__/responses/typeList.json';
|
||||||
import pokemonListPg1 from 'features/Pokedex/__test__/responses/pokemonListPage1.json';
|
import pokemonListPg1 from 'features/Pokedex/__test__/responses/pokemonListPage1.json';
|
||||||
import pokemonListPg2 from 'features/Pokedex/__test__/responses/pokemonListPage2.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 = [
|
export const handlers = [
|
||||||
// mock https://pokeapi.co/api/v2/region/1
|
// mock https://pokeapi.co/api/v2/region/1
|
||||||
|
@ -34,4 +40,24 @@ export const handlers = [
|
||||||
return res(ctx.json(pokemonListPg2));
|
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