Skip to content

Commit 1d86f42

Browse files
fix: api mocking with msw
1 parent e98aa3c commit 1d86f42

File tree

5 files changed

+1042
-24
lines changed

5 files changed

+1042
-24
lines changed

.storybook/preview.tsx

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,267 @@ import React from 'react';
22
import type { Preview } from '@storybook/react';
33
import { Analytics } from '@vercel/analytics/react';
44
import { Code } from './components/CodeBlock';
5+
import { initialize, mswLoader } from 'msw-storybook-addon';
6+
import { http, HttpResponse } from 'msw';
7+
58
import 'tailwindcss/tailwind.css';
69
import './styles/docs.styles.css';
710

11+
initialize();
12+
13+
const mockPokemonCards = [
14+
// Grass Type Pokemon
15+
{
16+
id: 'grass-1',
17+
name: 'Venusaur',
18+
types: ['Grass'],
19+
supertype: 'pokemon',
20+
images: { small: 'https://images.pokemontcg.io/base1/15.png' }
21+
},
22+
{
23+
id: 'grass-2',
24+
name: 'Ivysaur',
25+
types: ['Grass'],
26+
supertype: 'pokemon',
27+
images: { small: 'https://images.pokemontcg.io/base1/30.png' }
28+
},
29+
{
30+
id: 'grass-3',
31+
name: 'Bulbasaur',
32+
types: ['Grass'],
33+
supertype: 'pokemon',
34+
images: { small: 'https://images.pokemontcg.io/base1/44.png' }
35+
},
36+
{
37+
id: 'grass-4',
38+
name: 'Scyther',
39+
types: ['Grass'],
40+
supertype: 'pokemon',
41+
images: { small: 'https://images.pokemontcg.io/base1/26.png' }
42+
},
43+
44+
// Fire Type Pokemon
45+
{
46+
id: 'fire-1',
47+
name: 'Charizard',
48+
types: ['Fire'],
49+
supertype: 'pokemon',
50+
images: { small: 'https://images.pokemontcg.io/base1/4.png' }
51+
},
52+
{
53+
id: 'fire-2',
54+
name: 'Charmeleon',
55+
types: ['Fire'],
56+
supertype: 'pokemon',
57+
images: { small: 'https://images.pokemontcg.io/base1/24.png' }
58+
},
59+
{
60+
id: 'fire-3',
61+
name: 'Charmander',
62+
types: ['Fire'],
63+
supertype: 'pokemon',
64+
images: { small: 'https://images.pokemontcg.io/base1/46.png' }
65+
},
66+
{
67+
id: 'fire-4',
68+
name: 'Arcanine',
69+
types: ['Fire'],
70+
supertype: 'pokemon',
71+
images: { small: 'https://images.pokemontcg.io/base1/23.png' }
72+
},
73+
74+
// Water Type Pokemon
75+
{
76+
id: 'water-1',
77+
name: 'Blastoise',
78+
types: ['Water'],
79+
supertype: 'pokemon',
80+
images: { small: 'https://images.pokemontcg.io/base1/2.png' }
81+
},
82+
{
83+
id: 'water-2',
84+
name: 'Wartortle',
85+
types: ['Water'],
86+
supertype: 'pokemon',
87+
images: { small: 'https://images.pokemontcg.io/base1/42.png' }
88+
},
89+
{
90+
id: 'water-3',
91+
name: 'Squirtle',
92+
types: ['Water'],
93+
supertype: 'pokemon',
94+
images: { small: 'https://images.pokemontcg.io/base1/63.png' }
95+
},
96+
{
97+
id: 'water-4',
98+
name: 'Gyarados',
99+
types: ['Water'],
100+
supertype: 'pokemon',
101+
images: { small: 'https://images.pokemontcg.io/base1/6.png' }
102+
},
103+
104+
// Electric Type Pokemon
105+
{
106+
id: 'electric-1',
107+
name: 'Pikachu',
108+
types: ['Lightning'],
109+
supertype: 'pokemon',
110+
images: { small: 'https://images.pokemontcg.io/base1/58.png' }
111+
},
112+
{
113+
id: 'electric-2',
114+
name: 'Raichu',
115+
types: ['Lightning'],
116+
supertype: 'pokemon',
117+
images: { small: 'https://images.pokemontcg.io/base1/14.png' }
118+
},
119+
{
120+
id: 'electric-3',
121+
name: 'Zapdos',
122+
types: ['Lightning'],
123+
supertype: 'pokemon',
124+
images: { small: 'https://images.pokemontcg.io/base1/16.png' }
125+
},
126+
{
127+
id: 'electric-4',
128+
name: 'Electabuzz',
129+
types: ['Lightning'],
130+
supertype: 'pokemon',
131+
images: { small: 'https://images.pokemontcg.io/base1/20.png' }
132+
},
133+
134+
// Psychic Type Pokemon
135+
{
136+
id: 'psychic-1',
137+
name: 'Mewtwo',
138+
types: ['Psychic'],
139+
supertype: 'pokemon',
140+
images: { small: 'https://images.pokemontcg.io/base1/10.png' }
141+
},
142+
{
143+
id: 'psychic-2',
144+
name: 'Alakazam',
145+
types: ['Psychic'],
146+
supertype: 'pokemon',
147+
images: { small: 'https://images.pokemontcg.io/base1/1.png' }
148+
},
149+
{
150+
id: 'psychic-3',
151+
name: 'Kadabra',
152+
types: ['Psychic'],
153+
supertype: 'pokemon',
154+
images: { small: 'https://images.pokemontcg.io/base1/32.png' }
155+
},
156+
{
157+
id: 'psychic-4',
158+
name: 'Abra',
159+
types: ['Psychic'],
160+
supertype: 'pokemon',
161+
images: { small: 'https://images.pokemontcg.io/base1/43.png' }
162+
},
163+
164+
// Fighting Type Pokemon
165+
{
166+
id: 'fighting-1',
167+
name: 'Machamp',
168+
types: ['Fighting'],
169+
supertype: 'pokemon',
170+
images: { small: 'https://images.pokemontcg.io/base1/8.png' }
171+
},
172+
{
173+
id: 'fighting-2',
174+
name: 'Machoke',
175+
types: ['Fighting'],
176+
supertype: 'pokemon',
177+
images: { small: 'https://images.pokemontcg.io/base1/34.png' }
178+
},
179+
{
180+
id: 'fighting-3',
181+
name: 'Machop',
182+
types: ['Fighting'],
183+
supertype: 'pokemon',
184+
images: { small: 'https://images.pokemontcg.io/base1/52.png' }
185+
},
186+
{
187+
id: 'fighting-4',
188+
name: 'Hitmonlee',
189+
types: ['Fighting'],
190+
supertype: 'pokemon',
191+
images: { small: 'https://images.pokemontcg.io/base1/22.png' }
192+
}
193+
];
194+
195+
const mockPokemonTypes = [
196+
'Grass',
197+
'Fire',
198+
'Water',
199+
'Lightning',
200+
'Psychic',
201+
'Fighting',
202+
'Darkness',
203+
'Metal',
204+
'Fairy',
205+
'Dragon',
206+
'Colorless'
207+
];
208+
8209
const preview: Preview = {
9210
parameters: {
211+
msw: {
212+
handlers: [
213+
http.get(
214+
'https://api.pokemontcg.io/v2/cards',
215+
({ request }) => {
216+
const url = new URL(request.url);
217+
const pageSize = parseInt(
218+
url.searchParams.get('pageSize') || '10'
219+
);
220+
const query = url.searchParams.get('q') || '';
221+
222+
let filteredCards = mockPokemonCards;
223+
224+
// Filter by type if specified in query
225+
if (query.includes('types:')) {
226+
const typeMatch = query.match(/types:([^&]+)/);
227+
if (typeMatch) {
228+
const requestedType = typeMatch[1];
229+
filteredCards = mockPokemonCards.filter((card) =>
230+
card.types.includes(requestedType)
231+
);
232+
}
233+
}
234+
235+
// Filter by supertype if specified
236+
if (query.includes('supertype:')) {
237+
const supertypeMatch = query.match(/supertype:([^&]+)/);
238+
if (supertypeMatch) {
239+
const requestedSupertype = supertypeMatch[1];
240+
filteredCards = filteredCards.filter(
241+
(card) => card.supertype === requestedSupertype
242+
);
243+
}
244+
}
245+
246+
const data = filteredCards.slice(0, pageSize);
247+
248+
return HttpResponse.json({
249+
data,
250+
page: 1,
251+
pageSize,
252+
count: data.length,
253+
totalCount: filteredCards.length
254+
});
255+
}
256+
),
257+
258+
// Types endpoint
259+
http.get('https://api.pokemontcg.io/v2/types', () => {
260+
return HttpResponse.json({
261+
data: mockPokemonTypes
262+
});
263+
})
264+
]
265+
},
10266
docs: {
11267
components: {
12268
code: Code
@@ -25,6 +281,7 @@ const preview: Preview = {
25281
}
26282
}
27283
},
284+
loaders: [mswLoader],
28285
decorators: [
29286
(Story) => (
30287
<div className="p-2">

0 commit comments

Comments
 (0)