Compare commits
3 Commits
804c145b11
...
f8fb41e837
Author | SHA1 | Date | |
---|---|---|---|
f8fb41e837 | |||
08c8af5f4f | |||
a0adfb0268 |
81
src/app/services/__test__/responses/evolution-chain_2.json
Normal file
81
src/app/services/__test__/responses/evolution-chain_2.json
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"baby_trigger_item": null,
|
||||||
|
"chain": {
|
||||||
|
"evolution_details": [],
|
||||||
|
"evolves_to": [
|
||||||
|
{
|
||||||
|
"evolution_details": [
|
||||||
|
{
|
||||||
|
"gender": null,
|
||||||
|
"held_item": null,
|
||||||
|
"item": null,
|
||||||
|
"known_move": null,
|
||||||
|
"known_move_type": null,
|
||||||
|
"location": null,
|
||||||
|
"min_affection": null,
|
||||||
|
"min_beauty": null,
|
||||||
|
"min_happiness": null,
|
||||||
|
"min_level": 16,
|
||||||
|
"needs_overworld_rain": false,
|
||||||
|
"party_species": null,
|
||||||
|
"party_type": null,
|
||||||
|
"relative_physical_stats": null,
|
||||||
|
"time_of_day": "",
|
||||||
|
"trade_species": null,
|
||||||
|
"trigger": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/evolution-trigger/1/"
|
||||||
|
},
|
||||||
|
"turn_upside_down": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"evolves_to": [
|
||||||
|
{
|
||||||
|
"evolution_details": [
|
||||||
|
{
|
||||||
|
"gender": null,
|
||||||
|
"held_item": null,
|
||||||
|
"item": null,
|
||||||
|
"known_move": null,
|
||||||
|
"known_move_type": null,
|
||||||
|
"location": null,
|
||||||
|
"min_affection": null,
|
||||||
|
"min_beauty": null,
|
||||||
|
"min_happiness": null,
|
||||||
|
"min_level": 36,
|
||||||
|
"needs_overworld_rain": false,
|
||||||
|
"party_species": null,
|
||||||
|
"party_type": null,
|
||||||
|
"relative_physical_stats": null,
|
||||||
|
"time_of_day": "",
|
||||||
|
"trade_species": null,
|
||||||
|
"trigger": {
|
||||||
|
"name": "level-up",
|
||||||
|
"url": "https://pokeapi.co/api/v2/evolution-trigger/1/"
|
||||||
|
},
|
||||||
|
"turn_upside_down": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"evolves_to": [],
|
||||||
|
"is_baby": false,
|
||||||
|
"species": {
|
||||||
|
"name": "charizard",
|
||||||
|
"url": "https://pokeapi.co/api/v2/pokemon-species/6/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_baby": false,
|
||||||
|
"species": {
|
||||||
|
"name": "charmeleon",
|
||||||
|
"url": "https://pokeapi.co/api/v2/pokemon-species/5/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_baby": false,
|
||||||
|
"species": {
|
||||||
|
"name": "charmander",
|
||||||
|
"url": "https://pokeapi.co/api/v2/pokemon-species/4/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 2
|
||||||
|
}
|
1337
src/app/services/__test__/responses/pokemon-species_6.json
Normal file
1337
src/app/services/__test__/responses/pokemon-species_6.json
Normal file
File diff suppressed because it is too large
Load Diff
9141
src/app/services/__test__/responses/pokemon_85.json
Normal file
9141
src/app/services/__test__/responses/pokemon_85.json
Normal file
File diff suppressed because it is too large
Load Diff
90
src/app/services/pokeApi.test.ts
Normal file
90
src/app/services/pokeApi.test.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
||||||
|
import { pokeApi } from 'app/services/pokeApi';
|
||||||
|
import { filterSlice } from '../../features/Filters/filterSlice';
|
||||||
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
import { AppStore } from 'app/store';
|
||||||
|
import {
|
||||||
|
EvolutionChainResponseData,
|
||||||
|
PokemonResponseData,
|
||||||
|
PokemonSpeciesResponseData,
|
||||||
|
TypeListResponseData,
|
||||||
|
} from 'types/api';
|
||||||
|
|
||||||
|
let store: AppStore;
|
||||||
|
|
||||||
|
describe('pokeApi', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
pokedex: pokedexSlice.reducer,
|
||||||
|
filter: filterSlice.reducer,
|
||||||
|
[pokeApi.reducerPath]: pokeApi.reducer,
|
||||||
|
},
|
||||||
|
middleware: getDefaultMiddleware =>
|
||||||
|
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(pokeApi.endpoints.getPokemon.initiate(85));
|
||||||
|
|
||||||
|
const pokemon = pokeApi.endpoints.getPokemon.select(85)(
|
||||||
|
store.getState(),
|
||||||
|
).data as PokemonResponseData;
|
||||||
|
expect(pokemon?.name).toBe('dodrio');
|
||||||
|
expect(pokemon?.types).toHaveLength(2);
|
||||||
|
expect(pokemon?.types[0].type.name).toBe('normal');
|
||||||
|
expect(pokemon?.types[1].type.name).toBe('flying');
|
||||||
|
expect(pokemon?.sprites.other.dream_world.front_default).toBe(
|
||||||
|
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/85.svg',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test getPokemonSpecies query', () => {
|
||||||
|
test('visit https://pokeapi.co/api/v2/pokemon-species/6/', async () => {
|
||||||
|
await store.dispatch(pokeApi.endpoints.getPokemonSpecies.initiate(6));
|
||||||
|
|
||||||
|
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/',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test getTypeList query', () => {
|
||||||
|
test('visit https://pokeapi.co/api/v2/type should return correct data in list', async () => {
|
||||||
|
await store.dispatch(pokeApi.endpoints.getTypeList.initiate());
|
||||||
|
|
||||||
|
const typeListData = pokeApi.endpoints.getTypeList.select()(
|
||||||
|
store.getState(),
|
||||||
|
).data as TypeListResponseData;
|
||||||
|
expect(typeListData?.results).toHaveLength(typeListData.count + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test getEvolutionChain query', () => {
|
||||||
|
test('visit https://pokeapi.co/api/v2/evolution-chain/2/', async () => {
|
||||||
|
await store.dispatch(pokeApi.endpoints.getEvolutionChain.initiate(2));
|
||||||
|
|
||||||
|
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/',
|
||||||
|
);
|
||||||
|
expect(evolutionChainData?.chain.evolves_to[0].species.url).toBe(
|
||||||
|
'https://pokeapi.co/api/v2/pokemon-species/5/',
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
evolutionChainData?.chain.evolves_to[0].evolves_to[0].species.url,
|
||||||
|
).toBe('https://pokeapi.co/api/v2/pokemon-species/6/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,15 @@
|
|||||||
import { fetchBaseQuery, FetchArgs } from '@reduxjs/toolkit/query/react';
|
import {
|
||||||
|
fetchBaseQuery,
|
||||||
|
FetchArgs,
|
||||||
|
createApi,
|
||||||
|
} from '@reduxjs/toolkit/query/react';
|
||||||
|
import {
|
||||||
|
RegionListResponseData,
|
||||||
|
TypeListResponseData,
|
||||||
|
PokemonResponseData,
|
||||||
|
EvolutionChainResponseData,
|
||||||
|
PokemonSpeciesResponseData,
|
||||||
|
} from 'types/api';
|
||||||
|
|
||||||
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
export interface pokeApiFullListFetchArgs extends FetchArgs {
|
||||||
fetchAllPages?: boolean;
|
fetchAllPages?: boolean;
|
||||||
@ -69,3 +80,38 @@ export const pokeApiBaseQuery = async (
|
|||||||
return fetchBaseQuery({ baseUrl })(args, api, extra);
|
return fetchBaseQuery({ baseUrl })(args, api, extra);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const pokeApi = createApi({
|
||||||
|
reducerPath: 'pokeApi',
|
||||||
|
baseQuery: pokeApiBaseQuery,
|
||||||
|
endpoints: builder => ({
|
||||||
|
getTypeList: builder.query<TypeListResponseData, void>({
|
||||||
|
query: () => ({ url: 'type', fetchAllPages: true }),
|
||||||
|
transformResponse: (response: RegionListResponseData) => {
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
results: [{ name: 'All Types', url: '' }, ...response.results],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
getPokemon: builder.query<PokemonResponseData, number | string>({
|
||||||
|
query: IdOrName => ({ url: `pokemon/${IdOrName}` }),
|
||||||
|
}),
|
||||||
|
getPokemonSpecies: builder.query<
|
||||||
|
PokemonSpeciesResponseData,
|
||||||
|
number | string
|
||||||
|
>({
|
||||||
|
query: IdOrName => ({ url: `pokemon-species/${IdOrName}` }),
|
||||||
|
}),
|
||||||
|
getEvolutionChain: builder.query<EvolutionChainResponseData, number>({
|
||||||
|
query: Id => ({ url: `evolution-chain/${Id}` }),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {
|
||||||
|
useGetTypeListQuery,
|
||||||
|
useGetPokemonQuery,
|
||||||
|
useGetPokemonSpeciesQuery,
|
||||||
|
useGetEvolutionChainQuery,
|
||||||
|
} = pokeApi;
|
@ -1,7 +1,7 @@
|
|||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
||||||
import { filterSlice } from 'features/Filters/filterSlice';
|
import { filterSlice } from 'features/Filters/filterSlice';
|
||||||
import { filterApi } from 'features/Filters/filterApi';
|
import { pokeApi } from './services/pokeApi';
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@ -10,10 +10,10 @@ export const store = configureStore({
|
|||||||
filter: filterSlice.reducer,
|
filter: filterSlice.reducer,
|
||||||
|
|
||||||
// api slices
|
// api slices
|
||||||
[filterApi.reducerPath]: filterApi.reducer,
|
[pokeApi.reducerPath]: pokeApi.reducer,
|
||||||
},
|
},
|
||||||
middleware: getDefaultMiddleware =>
|
middleware: getDefaultMiddleware =>
|
||||||
getDefaultMiddleware().concat(filterApi.middleware),
|
getDefaultMiddleware().concat(pokeApi.middleware),
|
||||||
devTools: true,
|
devTools: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
setSortOptions,
|
setSortOptions,
|
||||||
setSearchInput,
|
setSearchInput,
|
||||||
} from './filterSlice';
|
} from './filterSlice';
|
||||||
import { useGetTypeListQuery } from './filterApi';
|
import { useGetTypeListQuery } from 'app/services/pokeApi';
|
||||||
import { RegionPokemonRange } from './types/slice';
|
import { RegionPokemonRange } from './types/slice';
|
||||||
import './Filters.css';
|
import './Filters.css';
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
|
||||||
import { filterApi } from './filterApi';
|
|
||||||
import { filterSlice } from './filterSlice';
|
|
||||||
import { configureStore } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
import { AppStore } from 'app/store';
|
|
||||||
import { TypeListResponseData } from 'types/api';
|
|
||||||
|
|
||||||
let store: AppStore;
|
|
||||||
|
|
||||||
describe('filterApi', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
store = configureStore({
|
|
||||||
reducer: {
|
|
||||||
pokedex: pokedexSlice.reducer,
|
|
||||||
filter: filterSlice.reducer,
|
|
||||||
[filterApi.reducerPath]: filterApi.reducer,
|
|
||||||
},
|
|
||||||
middleware: getDefaultMiddleware =>
|
|
||||||
getDefaultMiddleware().concat(filterApi.middleware),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('JEST test against mock API', () => {
|
|
||||||
test('visit https://pokeapi.co/api/v2/type should return correct data in list', async () => {
|
|
||||||
await store.dispatch(filterApi.endpoints.getTypeList.initiate());
|
|
||||||
|
|
||||||
const typeListData = filterApi.endpoints.getTypeList.select()(
|
|
||||||
store.getState(),
|
|
||||||
).data as TypeListResponseData;
|
|
||||||
expect(typeListData?.results).toHaveLength(typeListData.count + 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,21 +0,0 @@
|
|||||||
import { createApi } from '@reduxjs/toolkit/query/react';
|
|
||||||
import { pokeApiBaseQuery } from '../../services/pokeapi/paginationBaseQuery';
|
|
||||||
import { RegionListResponseData, TypeListResponseData } from 'types/api';
|
|
||||||
|
|
||||||
export const filterApi = createApi({
|
|
||||||
reducerPath: 'filterApi',
|
|
||||||
baseQuery: pokeApiBaseQuery,
|
|
||||||
endpoints: builder => ({
|
|
||||||
getTypeList: builder.query<TypeListResponseData, void>({
|
|
||||||
query: () => ({ url: 'type', fetchAllPages: true }),
|
|
||||||
transformResponse: (response: RegionListResponseData) => {
|
|
||||||
return {
|
|
||||||
...response,
|
|
||||||
results: [{ name: 'All Types', url: '' }, ...response.results],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const { useGetTypeListQuery } = filterApi;
|
|
@ -1,9 +1,9 @@
|
|||||||
import { createSlice, PayloadAction, Slice } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction, Slice } from '@reduxjs/toolkit';
|
||||||
import { FilterState } from './types/slice';
|
import { FilterState } from './types/slice';
|
||||||
import { RegionPokemonRange } from './types/slice';
|
import { RegionPokemonRange } from './types/slice';
|
||||||
import { filterApi } from './filterApi';
|
import { pokeApi } from 'app/services/pokeApi';
|
||||||
|
|
||||||
filterApi.endpoints.getTypeList.initiate(); // initialize type list fetching
|
pokeApi.endpoints.getTypeList.initiate(); // initialize type list fetching
|
||||||
|
|
||||||
const initialState: FilterState = {
|
const initialState: FilterState = {
|
||||||
regionOptions: [],
|
regionOptions: [],
|
||||||
@ -46,7 +46,7 @@ export const filterSlice: Slice<FilterState> = createSlice({
|
|||||||
},
|
},
|
||||||
extraReducers: builder => {
|
extraReducers: builder => {
|
||||||
builder.addMatcher(
|
builder.addMatcher(
|
||||||
filterApi.endpoints.getTypeList.matchFulfilled,
|
pokeApi.endpoints.getTypeList.matchFulfilled,
|
||||||
(state, action) => {
|
(state, action) => {
|
||||||
if (action.payload && action.payload.results.length > 0) {
|
if (action.payload && action.payload.results.length > 0) {
|
||||||
const regionListResults = action.payload.results;
|
const regionListResults = action.payload.results;
|
||||||
|
@ -10,7 +10,7 @@ import { AppStore } from 'app/store';
|
|||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
import { pokedexSlice } from 'features/Pokedex/pokedexSlice';
|
||||||
import { filterSlice } from 'features/Filters/filterSlice';
|
import { filterSlice } from 'features/Filters/filterSlice';
|
||||||
import { filterApi } from 'features/Filters/filterApi';
|
import { pokeApi } from 'app/services/pokeApi';
|
||||||
|
|
||||||
let store: AppStore;
|
let store: AppStore;
|
||||||
|
|
||||||
@ -20,10 +20,10 @@ describe('pokedex Component', () => {
|
|||||||
reducer: {
|
reducer: {
|
||||||
pokedex: pokedexSlice.reducer,
|
pokedex: pokedexSlice.reducer,
|
||||||
filter: filterSlice.reducer,
|
filter: filterSlice.reducer,
|
||||||
[filterApi.reducerPath]: filterApi.reducer,
|
[pokeApi.reducerPath]: pokeApi.reducer,
|
||||||
},
|
},
|
||||||
middleware: getDefaultMiddleware =>
|
middleware: getDefaultMiddleware =>
|
||||||
getDefaultMiddleware().concat(filterApi.middleware),
|
getDefaultMiddleware().concat(pokeApi.middleware),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
||||||
import type { Slice, PayloadAction } from '@reduxjs/toolkit';
|
import type { Slice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { PokedexState } from 'features/Pokedex/types/slice';
|
import { PokedexStateProps } from 'features/Pokedex/types/slice';
|
||||||
|
|
||||||
import { getStartAndEndIdsForRegion } from './utils';
|
import { getStartAndEndIdsForRegion } from './utils';
|
||||||
import { PokemonResponseData } from 'types/api';
|
import { PokemonResponseData } from 'types/api';
|
||||||
@ -39,12 +39,12 @@ export const fetchPokemonsInTheRegion = createAsyncThunk<
|
|||||||
return pokemonListData;
|
return pokemonListData;
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState: PokedexState = {
|
export const initialState: PokedexStateProps = {
|
||||||
isLoadingPokemons: true,
|
isLoadingPokemons: true,
|
||||||
pokemonCardList: [],
|
pokemonCardList: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pokedexSlice: Slice<PokedexState> = createSlice({
|
export const pokedexSlice: Slice<PokedexStateProps> = createSlice({
|
||||||
name: 'pokedex',
|
name: 'pokedex',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { PokemonCardProps } from 'components/PokemonCard';
|
import { PokemonCardProps } from 'components/PokemonCard';
|
||||||
|
|
||||||
export type PokedexState = {
|
export type PokedexStateProps = {
|
||||||
isLoadingPokemons: boolean;
|
isLoadingPokemons: boolean;
|
||||||
pokemonCardList: PokemonCardProps[];
|
pokemonCardList: PokemonCardProps[];
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,10 @@ import typeList from 'features/Filters/__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 dodrio from 'app/services/__test__/responses/pokemon_85.json';
|
||||||
|
import pokemonSpecies6 from 'app/services/__test__/responses/pokemon-species_6.json';
|
||||||
|
import evolutionChain2 from 'app/services/__test__/responses/evolution-chain_2.json';
|
||||||
|
|
||||||
export const handlers = [
|
export const handlers = [
|
||||||
// mock https://pokeapi.co/api/v2/region/1
|
// mock https://pokeapi.co/api/v2/region/1
|
||||||
rest.get('https://pokeapi.co/api/v2/region/999999', (req, res, ctx) => {
|
rest.get('https://pokeapi.co/api/v2/region/999999', (req, res, ctx) => {
|
||||||
@ -34,4 +38,19 @@ export const handlers = [
|
|||||||
return res(ctx.json(pokemonListPg2));
|
return res(ctx.json(pokemonListPg2));
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// mock https://pokeapi.co/api/v2/pokemon/85
|
||||||
|
rest.get('https://pokeapi.co/api/v2/pokemon/85', (req, res, ctx) => {
|
||||||
|
return res(ctx.json(dodrio));
|
||||||
|
}),
|
||||||
|
|
||||||
|
// mock https://pokeapi.co/api/v2/pokemon-species/6
|
||||||
|
rest.get('https://pokeapi.co/api/v2/pokemon-species/6', (req, res, ctx) => {
|
||||||
|
return res(ctx.json(pokemonSpecies6));
|
||||||
|
}),
|
||||||
|
|
||||||
|
// mock https://pokeapi.co/api/v2/evolution-chain/2
|
||||||
|
rest.get('https://pokeapi.co/api/v2/evolution-chain/2', (req, res, ctx) => {
|
||||||
|
return res(ctx.json(evolutionChain2));
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
@ -60,3 +60,23 @@ export interface PokemonResponseData {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PokemonSpeciesResponseData = {
|
||||||
|
// many fields are ignored
|
||||||
|
evolution_chain: {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type EvolutionChain = {
|
||||||
|
evolves_to: EvolutionChain[];
|
||||||
|
species: {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EvolutionChainResponseData = {
|
||||||
|
// many fields are ignored
|
||||||
|
chain: EvolutionChain;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user