feat: add cypress
This commit is contained in:
@@ -6,4 +6,5 @@ public/_static
|
||||
app/core.css
|
||||
app/scandic.css
|
||||
.env.local.example
|
||||
.prettierignore
|
||||
.prettierignore
|
||||
netlify.toml
|
||||
17
app/[lang]/(test)/layout.tsx
Normal file
17
app/[lang]/(test)/layout.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { Metadata } from "next"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Test Site",
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
params,
|
||||
}: React.PropsWithChildren<LayoutArgs<LangParams>>) {
|
||||
return (
|
||||
<html lang={params.lang}>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
15
app/[lang]/(test)/test/page.tsx
Normal file
15
app/[lang]/(test)/test/page.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { Metadata } from "next"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Hello World",
|
||||
}
|
||||
|
||||
export default function HelloWorldTestPage() {
|
||||
return (
|
||||
<main>
|
||||
<header>
|
||||
<h1>Hello World!</h1>
|
||||
</header>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
18
cypress.config.ts
Normal file
18
cypress.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineConfig } from "cypress"
|
||||
import { config } from "dotenv"
|
||||
|
||||
config({ path: "./.env.local" })
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: process.env.CYPRESS_BASE_URL,
|
||||
setupNodeEvents(on, config) {},
|
||||
},
|
||||
|
||||
component: {
|
||||
devServer: {
|
||||
bundler: "webpack",
|
||||
framework: "next",
|
||||
},
|
||||
},
|
||||
})
|
||||
6
cypress/e2e/hello-world.cy.js
Normal file
6
cypress/e2e/hello-world.cy.js
Normal file
@@ -0,0 +1,6 @@
|
||||
describe("Hello World", () => {
|
||||
it("should have an h1 tag", () => {
|
||||
cy.visit("/en/test")
|
||||
cy.get("h1").contains("Hello World")
|
||||
})
|
||||
})
|
||||
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@@ -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"
|
||||
}
|
||||
37
cypress/support/commands.ts
Normal file
37
cypress/support/commands.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************
|
||||
// This example commands.ts 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) => { ... })
|
||||
//
|
||||
// declare global {
|
||||
// namespace Cypress {
|
||||
// interface Chainable {
|
||||
// login(email: string, password: string): Chainable<void>
|
||||
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
14
cypress/support/component-index.html
Normal file
14
cypress/support/component-index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<title>Components App</title>
|
||||
<!-- Used by Next.js to inject CSS. -->
|
||||
<div id="__next_css__DO_NOT_USE__"></div>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
39
cypress/support/component.ts
Normal file
39
cypress/support/component.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// ***********************************************************
|
||||
// This example support/component.ts 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')
|
||||
|
||||
import { mount } from "cypress/react18"
|
||||
|
||||
// Augment the Cypress namespace to include type definitions for
|
||||
// your custom command.
|
||||
// Alternatively, can be defined in cypress/support/component.d.ts
|
||||
// with a <reference path="./component" /> at the top of your spec.
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
mount: typeof mount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add("mount", mount)
|
||||
|
||||
// Example use:
|
||||
// cy.mount(<MyComponent />)
|
||||
20
cypress/support/e2e.ts
Normal file
20
cypress/support/e2e.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.ts 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')
|
||||
8
env/server.ts
vendored
8
env/server.ts
vendored
@@ -3,28 +3,32 @@ import { z } from "zod"
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
ADOBE_SCRIPT_SRC: z.string().optional(),
|
||||
BUILD_ID: z.string().default("64rYXBu8o2eHp0Jf"),
|
||||
CMS_ACCESS_TOKEN: z.string(),
|
||||
CMS_API_KEY: z.string(),
|
||||
CMS_ENVIRONMENT: z.enum(["development", "production", "staging", "test"]),
|
||||
CMS_URL: z.string(),
|
||||
CMS_PREVIEW_URL: z.string(),
|
||||
CMS_PREVIEW_TOKEN: z.string(),
|
||||
CYPRESS_BASE_URL: z.string().default("http://127.0.0.1:3000"),
|
||||
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||
PRINT_QUERY: z.boolean().default(false),
|
||||
REVALIDATE_SECRET: z.string(),
|
||||
ADOBE_SCRIPT_SRC: z.string().optional(),
|
||||
},
|
||||
emptyStringAsUndefined: true,
|
||||
runtimeEnv: {
|
||||
ADOBE_SCRIPT_SRC: process.env.ADOBE_SCRIPT_SRC,
|
||||
BUILD_ID: process.env.BUILD_ID,
|
||||
CMS_ACCESS_TOKEN: process.env.CMS_ACCESS_TOKEN,
|
||||
CMS_API_KEY: process.env.CMS_API_KEY,
|
||||
CMS_ENVIRONMENT: process.env.CMS_ENVIRONMENT,
|
||||
CMS_URL: process.env.CMS_URL,
|
||||
CMS_PREVIEW_URL: process.env.CMS_PREVIEW_URL,
|
||||
CMS_PREVIEW_TOKEN: process.env.CMS_PREVIEW_TOKEN,
|
||||
CYPRESS_BASE_URL: process.env.CYPRESS_TEST_URL,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
PRINT_QUERY: process.env.PRINT_QUERY,
|
||||
REVALIDATE_SECRET: process.env.REVALIDATE_SECRET,
|
||||
ADOBE_SCRIPT_SRC: process.env.ADOBE_SCRIPT_SRC,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ContentstackLivePreview from "@contentstack/live-preview-utils"
|
||||
import { NextResponse } from "next/server"
|
||||
import type { NextRequest } from "next/server"
|
||||
|
||||
@@ -70,6 +69,6 @@ export const config = {
|
||||
* - _next/image (image optimization files)
|
||||
* - favicon.ico (favicon file)
|
||||
*/
|
||||
"/((?!api|_next/static|_next/image|_static|imageVault|contentassets|favicon.ico).*)",
|
||||
"/((?!api|_next/static|_next/image|_static|imageVault|contentassets|favicon.ico|en/test).*)",
|
||||
],
|
||||
}
|
||||
|
||||
23
netlify.toml
23
netlify.toml
@@ -1,2 +1,23 @@
|
||||
[build]
|
||||
command = "npm run build"
|
||||
publish = ".next"
|
||||
|
||||
[[plugins]]
|
||||
package = "@netlify/plugin-nextjs"
|
||||
package = "netlify-plugin-cypress"
|
||||
[plugins.inputs]
|
||||
configFile = "cypress.config.ts"
|
||||
[plugins.inputs.postBuild]
|
||||
enable = true
|
||||
start = "npm start"
|
||||
wait-on = "http://127.0.0.1:3000/en/test"
|
||||
wait-on-timeout = "30" # seconds
|
||||
|
||||
[build.environment]
|
||||
# cache Cypress binary in local "node_modules" folder
|
||||
# so Netlify caches it
|
||||
CYPRESS_CACHE_FOLDER = "./node_modules/CypressBinary"
|
||||
# set TERM variable for terminal output
|
||||
TERM = "xterm"
|
||||
|
||||
[[plugins]]
|
||||
package = "@netlify/plugin-nextjs"
|
||||
|
||||
@@ -8,6 +8,11 @@ jiti("./env/client")
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
eslint: { ignoreDuringBuilds: true },
|
||||
|
||||
generateBuildId: async () => {
|
||||
return process.env.BUILD_ID
|
||||
},
|
||||
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
@@ -18,6 +23,14 @@ const nextConfig = {
|
||||
],
|
||||
},
|
||||
|
||||
logging: {
|
||||
fetches: {
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
|
||||
output: "standalone",
|
||||
|
||||
webpack: function (config, options) {
|
||||
config.module.rules.push({
|
||||
test: /\.(graphql|gql)/,
|
||||
@@ -25,14 +38,8 @@ const nextConfig = {
|
||||
loader: "graphql-tag/loader",
|
||||
})
|
||||
|
||||
return config;
|
||||
return config
|
||||
},
|
||||
|
||||
logging: {
|
||||
fetches: {
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
|
||||
4416
package-lock.json
generated
4416
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -4,11 +4,16 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"dev": "next dev",
|
||||
"lint": "next lint && tsc",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky install",
|
||||
"start": "node .next/standalone/server.js",
|
||||
"test:component": "cypress open --component",
|
||||
"test:component:headless": "cypress run --component",
|
||||
"test:e2e": "start-server-and-test test:setup http://127.0.0.1:3000/en/test \"cypress open --e2e\"",
|
||||
"test:e2e:headless": "start-server-and-test test:setup http://127.0.0.1:3000/en/test \"cypress run --e2e\"",
|
||||
"test:setup": "npm run build && npm run start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@contentstack/live-preview-utils": "^1.4.0",
|
||||
@@ -28,12 +33,16 @@
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"cypress": "^13.6.6",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.0.4",
|
||||
"husky": "^9.0.11",
|
||||
"jiti": "^1.21.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"netlify-plugin-cypress": "^2.2.1",
|
||||
"prettier": "^3.2.5",
|
||||
"start-server-and-test": "^2.0.3",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
Reference in New Issue
Block a user