Merged in feat/cypress (pull request #52)
feat: add cypress Approved-by: Michael Zetterberg
This commit is contained in:
@@ -6,4 +6,5 @@ public/_static
|
|||||||
app/core.css
|
app/core.css
|
||||||
app/scandic.css
|
app/scandic.css
|
||||||
.env.local.example
|
.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({
|
export const env = createEnv({
|
||||||
server: {
|
server: {
|
||||||
|
ADOBE_SCRIPT_SRC: z.string().optional(),
|
||||||
|
BUILD_ID: z.string().default("64rYXBu8o2eHp0Jf"),
|
||||||
CMS_ACCESS_TOKEN: z.string(),
|
CMS_ACCESS_TOKEN: z.string(),
|
||||||
CMS_API_KEY: z.string(),
|
CMS_API_KEY: z.string(),
|
||||||
CMS_ENVIRONMENT: z.enum(["development", "production", "staging", "test"]),
|
CMS_ENVIRONMENT: z.enum(["development", "production", "staging", "test"]),
|
||||||
CMS_URL: z.string(),
|
CMS_URL: z.string(),
|
||||||
CMS_PREVIEW_URL: z.string(),
|
CMS_PREVIEW_URL: z.string(),
|
||||||
CMS_PREVIEW_TOKEN: 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"]),
|
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||||
PRINT_QUERY: z.boolean().default(false),
|
PRINT_QUERY: z.boolean().default(false),
|
||||||
REVALIDATE_SECRET: z.string(),
|
REVALIDATE_SECRET: z.string(),
|
||||||
ADOBE_SCRIPT_SRC: z.string().optional(),
|
|
||||||
},
|
},
|
||||||
emptyStringAsUndefined: true,
|
emptyStringAsUndefined: true,
|
||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
|
ADOBE_SCRIPT_SRC: process.env.ADOBE_SCRIPT_SRC,
|
||||||
|
BUILD_ID: process.env.BUILD_ID,
|
||||||
CMS_ACCESS_TOKEN: process.env.CMS_ACCESS_TOKEN,
|
CMS_ACCESS_TOKEN: process.env.CMS_ACCESS_TOKEN,
|
||||||
CMS_API_KEY: process.env.CMS_API_KEY,
|
CMS_API_KEY: process.env.CMS_API_KEY,
|
||||||
CMS_ENVIRONMENT: process.env.CMS_ENVIRONMENT,
|
CMS_ENVIRONMENT: process.env.CMS_ENVIRONMENT,
|
||||||
CMS_URL: process.env.CMS_URL,
|
CMS_URL: process.env.CMS_URL,
|
||||||
CMS_PREVIEW_URL: process.env.CMS_PREVIEW_URL,
|
CMS_PREVIEW_URL: process.env.CMS_PREVIEW_URL,
|
||||||
CMS_PREVIEW_TOKEN: process.env.CMS_PREVIEW_TOKEN,
|
CMS_PREVIEW_TOKEN: process.env.CMS_PREVIEW_TOKEN,
|
||||||
|
CYPRESS_BASE_URL: process.env.CYPRESS_TEST_URL,
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
NODE_ENV: process.env.NODE_ENV,
|
||||||
PRINT_QUERY: process.env.PRINT_QUERY,
|
PRINT_QUERY: process.env.PRINT_QUERY,
|
||||||
REVALIDATE_SECRET: process.env.REVALIDATE_SECRET,
|
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 { NextResponse } from "next/server"
|
||||||
import type { NextRequest } from "next/server"
|
import type { NextRequest } from "next/server"
|
||||||
|
|
||||||
@@ -70,6 +69,6 @@ export const config = {
|
|||||||
* - _next/image (image optimization files)
|
* - _next/image (image optimization files)
|
||||||
* - favicon.ico (favicon file)
|
* - 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]]
|
[[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} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
eslint: { ignoreDuringBuilds: true },
|
eslint: { ignoreDuringBuilds: true },
|
||||||
|
|
||||||
|
generateBuildId: async () => {
|
||||||
|
return process.env.BUILD_ID
|
||||||
|
},
|
||||||
|
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
@@ -18,6 +23,14 @@ const nextConfig = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logging: {
|
||||||
|
fetches: {
|
||||||
|
fullUrl: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
output: "standalone",
|
||||||
|
|
||||||
webpack: function (config, options) {
|
webpack: function (config, options) {
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.(graphql|gql)/,
|
test: /\.(graphql|gql)/,
|
||||||
@@ -25,14 +38,8 @@ const nextConfig = {
|
|||||||
loader: "graphql-tag/loader",
|
loader: "graphql-tag/loader",
|
||||||
})
|
})
|
||||||
|
|
||||||
return config;
|
return config
|
||||||
},
|
},
|
||||||
|
}
|
||||||
logging: {
|
|
||||||
fetches: {
|
|
||||||
fullUrl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default nextConfig
|
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,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"dev": "next dev",
|
||||||
"lint": "next lint && tsc",
|
"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": {
|
"dependencies": {
|
||||||
"@contentstack/live-preview-utils": "^1.4.0",
|
"@contentstack/live-preview-utils": "^1.4.0",
|
||||||
@@ -28,12 +33,16 @@
|
|||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
|
"cypress": "^13.6.6",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "^14.0.4",
|
"eslint-config-next": "^14.0.4",
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"jiti": "^1.21.0",
|
"jiti": "^1.21.0",
|
||||||
"lint-staged": "^15.2.2",
|
"lint-staged": "^15.2.2",
|
||||||
|
"netlify-plugin-cypress": "^2.2.1",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
|
"start-server-and-test": "^2.0.3",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
Reference in New Issue
Block a user