Implemented pokeApiAllPagesCustomBaseQuery and jest tests

This commit is contained in:
Jason Zhu 2023-03-27 22:52:15 +11:00
parent 6849b97726
commit 5d6c09642c
6 changed files with 118 additions and 5 deletions

View File

@ -101,5 +101,22 @@ describe('pokedexApi', () => {
).data as TypeListResponse;
expect(typeListData?.results).toHaveLength(typeListData.count + 1);
});
test('visit https://pokeapi.co/api/v2/pokemon should return correct data in list', async () => {
await store.dispatch(pokedexApi.endpoints.getPokemonList.initiate());
const pokemonListData = pokedexApi.endpoints.getPokemonList.select()(
store.getState(),
).data;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(pokemonListData?.results).toHaveLength(pokemonListData.count);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(pokemonListData?.next).toBeUndefined();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(pokemonListData?.previous).toBeUndefined();
});
});
});

View File

@ -1,5 +1,5 @@
{
"count": 1281,
"count": 40,
"next": "https://pokeapi.co/api/v2/pokemon?offset=20&limit=20",
"previous": null,
"results": [

View File

@ -0,0 +1,27 @@
{
"count": 40,
"next": null,
"previous": "https://pokeapi.co/api/v2/pokemon?offset=0&limit=20",
"results": [
{ "name": "spearow", "url": "https://pokeapi.co/api/v2/pokemon/21/" },
{ "name": "fearow", "url": "https://pokeapi.co/api/v2/pokemon/22/" },
{ "name": "ekans", "url": "https://pokeapi.co/api/v2/pokemon/23/" },
{ "name": "arbok", "url": "https://pokeapi.co/api/v2/pokemon/24/" },
{ "name": "pikachu", "url": "https://pokeapi.co/api/v2/pokemon/25/" },
{ "name": "raichu", "url": "https://pokeapi.co/api/v2/pokemon/26/" },
{ "name": "sandshrew", "url": "https://pokeapi.co/api/v2/pokemon/27/" },
{ "name": "sandslash", "url": "https://pokeapi.co/api/v2/pokemon/28/" },
{ "name": "nidoran-f", "url": "https://pokeapi.co/api/v2/pokemon/29/" },
{ "name": "nidorina", "url": "https://pokeapi.co/api/v2/pokemon/30/" },
{ "name": "nidoqueen", "url": "https://pokeapi.co/api/v2/pokemon/31/" },
{ "name": "nidoran-m", "url": "https://pokeapi.co/api/v2/pokemon/32/" },
{ "name": "nidorino", "url": "https://pokeapi.co/api/v2/pokemon/33/" },
{ "name": "nidoking", "url": "https://pokeapi.co/api/v2/pokemon/34/" },
{ "name": "clefairy", "url": "https://pokeapi.co/api/v2/pokemon/35/" },
{ "name": "clefable", "url": "https://pokeapi.co/api/v2/pokemon/36/" },
{ "name": "vulpix", "url": "https://pokeapi.co/api/v2/pokemon/37/" },
{ "name": "ninetales", "url": "https://pokeapi.co/api/v2/pokemon/38/" },
{ "name": "jigglypuff", "url": "https://pokeapi.co/api/v2/pokemon/39/" },
{ "name": "wigglytuff", "url": "https://pokeapi.co/api/v2/pokemon/40/" }
]
}

View File

@ -0,0 +1,57 @@
import { fetchBaseQuery, FetchArgs } from '@reduxjs/toolkit/query/react';
export interface pokeApiFullListFetchArgs extends FetchArgs {
fetchAllPages?: boolean;
}
interface PokeAPIPaginatedResponse {
count: number;
next: string | null;
previous: string | null;
results: any[];
}
interface PokeAPIFullListResponse {
count: number;
results: any[];
}
async function fetchAllPages(url: string | null) {
const allResults: any[] = [];
while (url) {
const response = await fetch(url);
const data = (await response.json()) as PokeAPIPaginatedResponse;
allResults.push(...data.results);
url = data.next;
}
return allResults;
}
export const paginationBaseQuery = (baseUrl: string) =>
fetchBaseQuery({ baseUrl });
export const pokeApiAllPagesCustomBaseQuery = async (
args: pokeApiFullListFetchArgs,
api: any,
extra: any,
baseUrl: string,
) => {
const result = await paginationBaseQuery(baseUrl)(args, api, extra);
if (result.data && args.fetchAllPages) {
const data = result.data as PokeAPIPaginatedResponse;
if (data.next) {
const allResults = await fetchAllPages(data.next);
data.results = data.results.concat(allResults);
}
const fullListReponse: PokeAPIFullListResponse = {
count: data.count,
results: data.results,
};
result.data = fullListReponse;
}
return result;
};

View File

@ -5,7 +5,7 @@ import {
} from '@reduxjs/toolkit/query/react';
import type { PokemonProps as Pokemon } from './Pokemon';
import {
paginationCustomBaseQuery,
pokeApiAllPagesCustomBaseQuery,
pokeApiFullListFetchArgs,
} from './paginationBaseQuery';
@ -42,7 +42,7 @@ const pokeApiBaseQuery = async (
const baseUrl = 'https://pokeapi.co/api/v2/';
if (args.fetchAllPages) {
return paginationCustomBaseQuery(args, api, extra, baseUrl);
return pokeApiAllPagesCustomBaseQuery(args, api, extra, baseUrl);
} else {
return fetchBaseQuery({ baseUrl })(args, api, extra);
}

View File

@ -3,6 +3,8 @@ import { rest } from 'msw';
import region1 from 'features/Pokedex/__test__/responses/region1.json';
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';
export const handlers = [
// mock https://pokeapi.co/api/v2/region/1
@ -15,11 +17,21 @@ export const handlers = [
return res(ctx.json(region1));
}),
rest.get('https//pokeapi.co/api/v2/region', (req, res, ctx) => {
rest.get('https://pokeapi.co/api/v2/region', (req, res, ctx) => {
return res(ctx.json(regionList));
}),
rest.get('https//pokeapi.co/api/v2/type', (req, res, ctx) => {
rest.get('https://pokeapi.co/api/v2/type', (req, res, ctx) => {
return res(ctx.json(typeList));
}),
rest.get('https://pokeapi.co/api/v2/pokemon', (req, res, ctx) => {
const offset = req.url.searchParams.get('offset');
const limit = req.url.searchParams.get('limit');
if (offset === null && limit === null) {
return res(ctx.json(pokemonListPg1));
} else {
return res(ctx.json(pokemonListPg2));
}
}),
];