Skip to content

Commit f45cce8

Browse files
committed
add client-side mocking with next
1 parent 759bf1c commit f45cce8

File tree

7 files changed

+131
-354
lines changed

7 files changed

+131
-354
lines changed

examples/with-next/app/globals.css

Lines changed: 0 additions & 107 deletions
This file was deleted.

examples/with-next/app/layout.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import type { Metadata } from "next";
2-
import { Inter } from "next/font/google";
3-
import "./globals.css";
1+
import type { Metadata } from 'next'
2+
import { Inter } from 'next/font/google'
3+
import { MockProvider } from './mockProvider'
44

5-
const inter = Inter({ subsets: ["latin"] });
5+
const inter = Inter({ subsets: ['latin'] })
66

77
export const metadata: Metadata = {
8-
title: "Create Next App",
9-
description: "Generated by create next app",
10-
};
8+
title: 'Create Next App',
9+
description: 'Generated by create next app',
10+
}
1111

1212
export default function RootLayout({
1313
children,
1414
}: Readonly<{
15-
children: React.ReactNode;
15+
children: React.ReactNode
1616
}>) {
1717
return (
1818
<html lang="en">
19-
<body className={inter.className}>{children}</body>
19+
<body className={inter.className}>
20+
<MockProvider>{children}</MockProvider>
21+
</body>
2022
</html>
21-
);
23+
)
2224
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client'
2+
import { useEffect, useState } from 'react'
3+
4+
if (typeof window === 'undefined') {
5+
throw new Error('Is not this a browser-only module?')
6+
}
7+
8+
export async function MockProvider({
9+
children,
10+
}: Readonly<{
11+
children: React.ReactNode
12+
}>) {
13+
const [mockingEnabled, enableMocking] = useState(false)
14+
15+
useEffect(() => {
16+
async function enableApiMocking() {
17+
/**
18+
* @fixme Next puts this import to the top of
19+
* this module and runs it during the build
20+
* in Node.js. This makes "msw/browser" import to fail.
21+
*/
22+
const { worker } = await import('../mocks/browser')
23+
await worker.start()
24+
enableMocking(true)
25+
}
26+
27+
enableApiMocking()
28+
}, [])
29+
30+
if (!mockingEnabled) {
31+
return null
32+
}
33+
34+
return <>{children}</>
35+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use client'
2+
import { useState } from 'react'
3+
4+
export type Movie = {
5+
id: string
6+
title: string
7+
}
8+
9+
export function MovieList() {
10+
const [movies, setMovies] = useState<Array<Movie>>([])
11+
12+
const fetchMovies = () => {
13+
fetch('/graphql', {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/json',
17+
},
18+
body: JSON.stringify({
19+
query: `
20+
query ListMovies {
21+
movies {
22+
id
23+
title
24+
}
25+
}
26+
`,
27+
}),
28+
})
29+
.then((response) => response.json())
30+
.then((movies) => setMovies(movies))
31+
.catch(() => setMovies([]))
32+
}
33+
34+
return (
35+
<div>
36+
<button onClick={fetchMovies}>Fetch movies</button>
37+
{movies.length > 0 ? (
38+
<ul>
39+
{movies.map((movie) => (
40+
<li id={movie.id}>{movie.title}</li>
41+
))}
42+
</ul>
43+
) : null}
44+
</div>
45+
)
46+
}

0 commit comments

Comments
 (0)