diff --git a/examples/with-cypress/.gitignore b/examples/with-cypress/.gitignore new file mode 100644 index 0000000000000..1437c53f70bc2 --- /dev/null +++ b/examples/with-cypress/.gitignore @@ -0,0 +1,34 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/examples/with-cypress/README.md b/examples/with-cypress/README.md new file mode 100644 index 0000000000000..e8fe010feae30 --- /dev/null +++ b/examples/with-cypress/README.md @@ -0,0 +1,27 @@ +# Next.js + Cypress + +This example shows how to configure Cypress to work with Next.js. + +## Preview + +Preview the example live on [StackBlitz](http://stackblitz.com/): + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-cypress) + +## Deploy your own + +Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-cypress&project-name=with-cypress&repository-name=with-cypress) + +## How to use + +Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: + +```bash +npx create-next-app --example with-cypress with-cypress-app +# or +yarn create next-app --example with-cypress with-cypress-app +``` + +Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). diff --git a/examples/with-cypress/cypress.json b/examples/with-cypress/cypress.json new file mode 100644 index 0000000000000..17ef242e711f0 --- /dev/null +++ b/examples/with-cypress/cypress.json @@ -0,0 +1,3 @@ +{ + "baseUrl": "http://localhost:3000" +} diff --git a/examples/with-cypress/cypress/fixtures/example.json b/examples/with-cypress/cypress/fixtures/example.json new file mode 100644 index 0000000000000..02e4254378e97 --- /dev/null +++ b/examples/with-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/examples/with-cypress/cypress/integration/app.spec.js b/examples/with-cypress/cypress/integration/app.spec.js new file mode 100644 index 0000000000000..a1330a1a907ba --- /dev/null +++ b/examples/with-cypress/cypress/integration/app.spec.js @@ -0,0 +1,20 @@ +/* eslint-disable */ +// Disable ESLint to prevent failing linting inside the Next.js repo. +// If you're using ESLint on your project, we recommend installing the ESLint Cypress plugin instead: +// https://github.com/cypress-io/eslint-plugin-cypress + +describe('Navigation', () => { + it('should navigate to the about page', () => { + // Start from the index page + cy.visit('http://localhost:3000/') + + // Find a link with an href attribute containing "about" and click it + cy.get('a[href*="about"]').click() + + // The new url should include "/about" + cy.url().should('include', '/about') + + // The new page should contain an h1 with "About page" + cy.get('h1').contains('About Page') + }) +}) diff --git a/examples/with-cypress/cypress/plugins/index.js b/examples/with-cypress/cypress/plugins/index.js new file mode 100644 index 0000000000000..59b2bab6e4e60 --- /dev/null +++ b/examples/with-cypress/cypress/plugins/index.js @@ -0,0 +1,22 @@ +/// +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +// eslint-disable-next-line no-unused-vars +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/examples/with-cypress/cypress/support/commands.js b/examples/with-cypress/cypress/support/commands.js new file mode 100644 index 0000000000000..119ab03f7cda1 --- /dev/null +++ b/examples/with-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/examples/with-cypress/cypress/support/index.js b/examples/with-cypress/cypress/support/index.js new file mode 100644 index 0000000000000..d68db96df2697 --- /dev/null +++ b/examples/with-cypress/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/examples/with-cypress/package.json b/examples/with-cypress/package.json new file mode 100644 index 0000000000000..966a833f699b4 --- /dev/null +++ b/examples/with-cypress/package.json @@ -0,0 +1,23 @@ +{ + "name": "with-cypress", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "cypress": "cypress open", + "cypress:headless": "cypress run", + "e2e": "start-server-and-test dev http://localhost:3000 cypress", + "e2e:headless": "start-server-and-test dev http://localhost:3000 cypress:headless" + }, + "dependencies": { + "next": "latest", + "react": "17.0.2", + "react-dom": "17.0.2" + }, + "devDependencies": { + "cypress": "8.2.0", + "start-server-and-test": "1.13.1" + } +} diff --git a/examples/with-cypress/pages/_app.js b/examples/with-cypress/pages/_app.js new file mode 100644 index 0000000000000..1e1cec92425c8 --- /dev/null +++ b/examples/with-cypress/pages/_app.js @@ -0,0 +1,7 @@ +import '../styles/globals.css' + +function MyApp({ Component, pageProps }) { + return +} + +export default MyApp diff --git a/examples/with-cypress/pages/about.js b/examples/with-cypress/pages/about.js new file mode 100644 index 0000000000000..0db64404746b1 --- /dev/null +++ b/examples/with-cypress/pages/about.js @@ -0,0 +1,17 @@ +import styles from '../styles/Home.module.css' +import Link from 'next/link' + +export default function About() { + return ( +
+
+

About Page

+

+ + ← Go Back + +

+
+
+ ) +} diff --git a/examples/with-cypress/pages/index.js b/examples/with-cypress/pages/index.js new file mode 100644 index 0000000000000..7af20bc61f526 --- /dev/null +++ b/examples/with-cypress/pages/index.js @@ -0,0 +1,77 @@ +import Head from 'next/head' +import Image from 'next/image' +import Link from 'next/link' +import styles from '../styles/Home.module.css' + +export default function Home() { + return ( +
+ + Create Next App + + + + +
+

+ Welcome to Next.js! +

+ +

+ Get started by editing{' '} + pages/index.js +

+ +
+ + +

About Page →

+

Cypress will test if this link is working.

+
+ + + +

Documentation →

+

Find in-depth information about Next.js features and API.

+
+ + +

Learn →

+

Learn about Next.js in an interactive course with quizzes!

+
+ + +

Examples →

+

Discover and deploy boilerplate example Next.js projects.

+
+ + +

Deploy →

+

+ Instantly deploy your Next.js site to a public URL with Vercel. +

+
+
+
+ + +
+ ) +} diff --git a/examples/with-cypress/public/favicon.ico b/examples/with-cypress/public/favicon.ico new file mode 100644 index 0000000000000..718d6fea4835e Binary files /dev/null and b/examples/with-cypress/public/favicon.ico differ diff --git a/examples/with-cypress/public/vercel.svg b/examples/with-cypress/public/vercel.svg new file mode 100644 index 0000000000000..fbf0e25a651c2 --- /dev/null +++ b/examples/with-cypress/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/examples/with-cypress/styles/Home.module.css b/examples/with-cypress/styles/Home.module.css new file mode 100644 index 0000000000000..35454bb748190 --- /dev/null +++ b/examples/with-cypress/styles/Home.module.css @@ -0,0 +1,121 @@ +.container { + min-height: 100vh; + padding: 0 0.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100vh; +} + +.main { + padding: 5rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + width: 100%; + height: 100px; + border-top: 1px solid #eaeaea; + display: flex; + justify-content: center; + align-items: center; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; + flex-grow: 1; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.description { + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, + Bitstream Vera Sans Mono, Courier New, monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + max-width: 800px; + margin-top: 3rem; +} + +.card { + margin: 1rem; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; + width: 45%; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h2 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; + margin-left: 0.5rem; +} + +@media (max-width: 600px) { + .grid { + width: 100%; + flex-direction: column; + } +} diff --git a/examples/with-cypress/styles/globals.css b/examples/with-cypress/styles/globals.css new file mode 100644 index 0000000000000..e5e2dcc23baf1 --- /dev/null +++ b/examples/with-cypress/styles/globals.css @@ -0,0 +1,16 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +}