Skip to content

Commit 717a548

Browse files
author
Tiffany Le-Nguyen
authored
chore: add e2e tests and demos (#1172)
* chore: recommit as one * chore: fix eslint * chore: fix eslint * chore: fix order and typo * chore: add middleware test * chore: redo lock * chore: update snapidoos * chore: snapidoos please * chore: update to node version 16 * chore: update to npm 8 * chore: swc please * chore: snapidoodidoo * chore: snapidoodidoodoo * chore: manual snap * chore: manual snap 2 * Apply suggestions from code review
1 parent ef13731 commit 717a548

24 files changed

+23567
-3980
lines changed

.vscode/feat-test.code-snippets

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
// Place your netlify-plugin-nextjs workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
3+
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
4+
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
5+
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
6+
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
7+
// Placeholders with the same ids are connected.
8+
// Example:
9+
"Create Next Test Feature": {
10+
"scope": "javascriptreact,typescriptreact",
11+
"prefix": "ft",
12+
"body": [
13+
"import Link from 'next/link'",
14+
"",
15+
"function $1() {",
16+
"\treturn (",
17+
"\t\t<div>",
18+
"\t\t<h1>$1</h1>",
19+
"\t\t<Link href=\"\"><a>Read Docs</a></Link>",
20+
"\t\t<p>Description of feature</p>",
21+
"\t\t<p>Example/test of feature</p>",
22+
"\t\t</div>",
23+
"\t)",
24+
"}",
25+
"",
26+
"export default $1"
27+
],
28+
"description": "Log output to console"
29+
}
30+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('CSS handling', () => {
2+
beforeEach(() => {
3+
cy.visit('/css')
4+
})
5+
6+
it('should properly handle css', () => {
7+
// Sass variable loaded
8+
cy.findByText(/ Sass variable imported, color: #64FF00/i)
9+
10+
// CSS-in-JS loaded
11+
cy.findByTestId('css-in-js').should('have.css', 'background', 'rgb(255, 165, 0) none repeat scroll 0% 0% / auto padding-box border-box')
12+
})
13+
})
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
describe('Environment Varialbes', () => {
2+
beforeEach(() => {
3+
cy.visit('/env')
4+
})
5+
6+
it('should show a public environment token and not show private ones', () => {
7+
cy.findByText('Greetings Vi')
8+
cy.findByText('Everything worked')
9+
})
10+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
describe('Layouts', () => {
2+
beforeEach(() => {
3+
cy.visit('/layouts')
4+
})
5+
6+
it('should properly have a layout and title change', () => {
7+
cy.findByText(/Test layout wrapper/i)
8+
cy.title().should('eq', 'Per Page Layout test title')
9+
})
10+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
describe('Middleware', () => {
2+
beforeEach(() => {
3+
cy.request('/middle')
4+
})
5+
6+
it('should properly load custom headers', () => {
7+
cy.request({
8+
url: '/',
9+
}).then((response) => {
10+
expect(response.headers).to.have.property('x-custom-1', 'value-1')
11+
expect(response.headers).to.have.property('x-custom-2', 'value-2')
12+
expect(response.headers).to.have.property('x-custom-3', 'value-3')
13+
expect(response.headers).to.have.property('x-custom-4', 'value-4')
14+
})
15+
})
16+
})
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
describe('Environment Varialbes', () => {
2+
beforeEach(() => {
3+
cy.intercept('GET', 'https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX').as('test-gtm')
4+
cy.visit('https://61f2c7c9fad2c70ee2737a81--netlify-plugin-nextjs-demo.netlify.app/script/')
5+
})
6+
7+
it('should load a script after interactive', () => {
8+
cy.wait('@test-gtm')
9+
})
10+
})

demos/default/.env.production

+8-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
HELLO_WORLD="Hello Production"
1+
HELLO_WORLD="Hello Production"
2+
3+
TEST_ENV_VAR="This test shouldn't show up on the page. If it does, something is wrong"
4+
5+
# In order to expose a variable to the browser you have to prefix the variable with NEXT_PUBLIC_.
6+
7+
NEXT_PUBLIC_NAME="Vi"
8+
NEXT_PUBLIC_GREETINGS="Greetings $NEXT_PUBLIC_NAME"

demos/default/next-env.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.

demos/default/next.config.js

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const path = require('path')
2+
13
module.exports = {
24
// Configurable site features we support:
35
// distDir: 'build',
@@ -49,4 +51,12 @@ module.exports = {
4951
},
5052
]
5153
},
54+
// https://nextjs.org/docs/basic-features/image-optimization#domains
55+
images: {
56+
domains: ['raw.githubusercontent.com'],
57+
},
58+
// https://nextjs.org/docs/basic-features/built-in-css-support#customizing-sass-options
59+
sassOptions: {
60+
includePaths: [path.join(__dirname, 'styles-sass-test')],
61+
},
5262
}

demos/default/pages/_app.js renamed to demos/default/pages/_app.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import '../styles/globals.css'
22

33
function MyApp({ Component, pageProps }) {
4+
const getLayout = Component.getLayout || ((page) => page)
5+
46
return (
57
<div className='prose ml-14 mt-10 mb-20'>
6-
<Component {...pageProps} />
8+
{getLayout(<Component {...pageProps} />)}
79
</div>
810
)
911
}

demos/default/pages/broken-image.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Image from 'next/image'
2+
3+
// This should cause an error, because broken-domain is not part of the configured next.config.js image domains
4+
const Images = () => (
5+
<Image
6+
src="https://broken-domain/netlify/netlify-plugin-nextjs/main/next-on-netlify.png"
7+
alt="Picture of the author"
8+
width={500}
9+
height={500}
10+
/>
11+
)
12+
13+
export default Images
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
You do not need to worry about .error {} colliding with any other `.css` or
3+
`.module.css` files!
4+
*/
5+
.error {
6+
color: white;
7+
background-color: red;
8+
}

demos/default/pages/css/index.tsx

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import Link from 'next/link'
2+
3+
import styles from './index.module.css'
4+
import '@reach/dialog/styles.css'
5+
import { useState } from 'react'
6+
import { Dialog } from '@reach/dialog'
7+
import { VisuallyHidden } from '@reach/visually-hidden'
8+
import variables from '../../style-sass-test/variables.module.scss'
9+
10+
// Missing: disabling javascript
11+
function BuiltInCSSSupport() {
12+
return (
13+
<div>
14+
<h1>Built In CSS Support</h1>
15+
<Link href="https://nextjs.org/docs/basic-features/built-in-css-support"><a>Read Docs</a></Link>
16+
17+
18+
<h2>CSS Modules</h2>
19+
<p>CSS Modules are an optional feature and are only enabled for files with the .module.css extension. </p>
20+
<p className={styles.error}>This is made with an imported css module</p>
21+
22+
<h2>Import styles from <code>node_modules</code></h2>
23+
<p>This page imports a node module&apos;s css file for the dialog below:</p>
24+
<ExampleDialog/>
25+
26+
<h2>Sass Support</h2>
27+
<p>✅ Sass variable imported, color: {variables.primaryColor || <code>Error. Something went wrong</code>}</p>
28+
29+
<div data-testid="css-in-js">
30+
<h2>CSS-in-JS</h2>
31+
<p>NextJS bundles styled-jsx to provide support for isolated scoped CSS. The aim is to support &quot;shadow CSS&quot; similar to Web Components, which unfortunately do not support server-rendering and are JS-only.</p>
32+
<style jsx>{`
33+
p {
34+
color: white;
35+
font-weight: 500;
36+
margin: 20px;
37+
}
38+
div {
39+
background: orange;
40+
}
41+
`}</style>
42+
<p>This section should be differently styled compared to the others (i.e. orange background)</p>
43+
<style global jsx>{`
44+
body {
45+
background: lightgrey;
46+
}
47+
`}</style>
48+
</div>
49+
50+
</div>
51+
)
52+
}
53+
54+
export default BuiltInCSSSupport
55+
56+
function ExampleDialog() {
57+
const [showDialog, setShowDialog] = useState(false)
58+
const open = () => setShowDialog(true)
59+
const close = () => setShowDialog(false)
60+
61+
return (
62+
<div>
63+
<button onClick={open}>Open Dialog</button>
64+
<Dialog isOpen={showDialog} onDismiss={close}>
65+
<button className="close-button" onClick={close}>
66+
<VisuallyHidden>Close</VisuallyHidden>
67+
<span aria-hidden>×</span>
68+
</button>
69+
<p>Hello there. I am a dialog</p>
70+
</Dialog>
71+
</div>
72+
)
73+
}

demos/default/pages/env.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* https://nextjs.org/docs/basic-features/environment-variables
3+
*/
4+
function EnvTest() {
5+
return (
6+
<div>
7+
<h1>Environment Variables</h1>
8+
<a href="https://nextjs.org/docs/basic-features/environment-variables">Read Docs</a>
9+
<p>By default environment variables are only available in the Node.js environment, meaning they won&apos;t be exposed to the browser.</p>
10+
<p>
11+
<code>NEXT_PUBLIC_</code> environment variables are available in the browser, and can be used to configure the application.
12+
</p>
13+
<p>✅ Public Environment token found: <code>{process.env.NEXT_PUBLIC_GREETINGS || 'NOT FOUND (something went wrong)'}</code></p>
14+
<p>❌ Private Environment token should not be found: <code>{process.env.TEST_ENV_VAR || 'Everything worked'}</code></p>
15+
</div>
16+
)
17+
}
18+
19+
export default EnvTest

demos/default/pages/font.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Head from 'next/head'
2+
import Link from 'next/link'
3+
4+
function Font() {
5+
return (
6+
<div>
7+
{/* <Head> */}
8+
<link
9+
href="https://fonts.googleapis.com/css2?family=Inter&display=optional"
10+
rel="stylesheet"
11+
/>
12+
{/* </Head> */}
13+
<h1>Font Optimization</h1>
14+
<Link href="https://nextjs.org/docs/basic-features/font-optimization"><a>Read Docs</a></Link>
15+
<p>
16+
By default, Next.js will automatically inline font CSS at build time, eliminating an extra round trip to fetch font declarations.
17+
</p>
18+
<p>If optimized font is enabled (default), it should show <code>style</code>, otherwise it should show <code>link</code> in the head</p>
19+
</div>
20+
)
21+
}
22+
23+
export default Font

demos/default/pages/image.js

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ const Images = () => (
1414
</p>
1515
<p>
1616
<Image src={logo} alt="netlify logomark" />
17+
18+
<Image
19+
src="https://raw.githubusercontent.com/netlify/netlify-plugin-nextjs/main/next-on-netlify.png"
20+
alt="Picture of the author"
21+
width={500}
22+
height={500}
23+
/>
1724
</p>
1825
</div>
1926
)

demos/default/pages/layouts.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Link from 'next/link'
2+
import { useEffect } from 'react';
3+
4+
function Layouts() {
5+
return (
6+
<div>
7+
<h1>Layout</h1>
8+
<Link href="https://nextjs.org/docs/basic-features/layouts#per-page-layouts"><a>Read Docs</a></Link>
9+
<p>The React model allows us to deconstruct a page into a series of components. Many of these components are often reused between pages. For example, you might have the same navigation bar and footer on every page.</p>
10+
<p>This page should have an <code>span</code> tag that is added through a layout and the title should have changed in a <code>useEffect</code></p>
11+
</div>
12+
)
13+
}
14+
15+
16+
Layouts.getLayout = function getLayout(page) {
17+
return (
18+
<TestLayout>{page}</TestLayout>
19+
)
20+
}
21+
22+
function TestLayout({children}) {
23+
useEffect(() => {
24+
// Update the document title using the browser API
25+
document.title = `Per Page Layout test title`;
26+
});
27+
28+
return (
29+
<div>
30+
<span>Test layout wrapper</span>
31+
{children}
32+
</div>
33+
)
34+
}
35+
36+
export default Layouts
+21-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
11
export function middleware(req, ev) {
2-
return new Response('Hello, middleware!');
2+
// 1. Add a header to the `Headers` interface
3+
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
4+
const headers = new Headers({ 'x-custom-1': 'value-1' })
5+
headers.set('x-custom-2', 'value-2')
6+
7+
// 2. Add existing headers to a new `Response`
8+
const res = new Response(null, { headers })
9+
10+
// 3. Add a header to an existing response
11+
res.headers.set('x-custom-3', 'value-3')
12+
13+
// 4. Merge existing headers with new ones in a response
14+
return new Response(
15+
'Open the network tab in devtools to see the response headers',
16+
{
17+
headers: {
18+
...Object.fromEntries(res.headers),
19+
'x-custom-4': 'value-4',
20+
},
21+
}
22+
)
323
}

0 commit comments

Comments
 (0)