Using Playwright for e2e testing
This commit is contained in:
parent
b407553f0d
commit
eb8aee090f
16 changed files with 328 additions and 2608 deletions
27
.github/workflows/playwright.yml
vendored
Normal file
27
.github/workflows/playwright.yml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
name: Playwright Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, master ]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
timeout-minutes: 60
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
- name: Install Playwright Browsers
|
||||||
|
run: pnpm exec playwright install --with-deps
|
||||||
|
- name: Run Playwright tests
|
||||||
|
run: pnpm exec playwright test
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: playwright-report
|
||||||
|
path: playwright-report/
|
||||||
|
retention-days: 30
|
7
leaky-ships/.gitignore
vendored
7
leaky-ships/.gitignore
vendored
|
@ -1,7 +1,5 @@
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
__tests__/screenshots/*
|
|
||||||
|
|
||||||
# logs
|
# logs
|
||||||
/log
|
/log
|
||||||
|
|
||||||
|
@ -43,3 +41,8 @@ yarn-error.log*
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
|
# playwright
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
describe("Check Azure AD auth", () => {
|
|
||||||
const callbackUrl = process.env.NEXTAUTH_URL + "/"
|
|
||||||
|
|
||||||
it("Login process...", async () => {
|
|
||||||
let redirected = false
|
|
||||||
let thirdParty = false
|
|
||||||
|
|
||||||
page.on("framenavigated", (frame) => {
|
|
||||||
if (redirected) return
|
|
||||||
const frameUrl = frame.url()
|
|
||||||
// console.log("Window Location Changed:", frameUrl)
|
|
||||||
if (frameUrl === callbackUrl) redirected = true
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
|
||||||
await page.goto(callbackUrl + "signin")
|
|
||||||
await page.waitForSelector("#microsoft")
|
|
||||||
await page.click("#microsoft")
|
|
||||||
|
|
||||||
thirdParty = true
|
|
||||||
|
|
||||||
await page.waitForNavigation()
|
|
||||||
|
|
||||||
await page.waitForSelector('input[type="email"]')
|
|
||||||
const emailInput = await page.$('input[type="email"]')
|
|
||||||
await emailInput.type(process.env.AUTH_EMAIL)
|
|
||||||
|
|
||||||
await page.waitForSelector('input[value="Next"]')
|
|
||||||
const nextInput = await page.$('input[value="Next"]')
|
|
||||||
await nextInput.click()
|
|
||||||
|
|
||||||
await page.waitForSelector('input[type="password"]')
|
|
||||||
const passwordInput = await page.$('input[type="password"]')
|
|
||||||
await passwordInput.type(process.env.AUTH_PW)
|
|
||||||
|
|
||||||
await page.waitForSelector('input[value="Sign in"]')
|
|
||||||
const signinInput = await page.$('input[value="Sign in"]')
|
|
||||||
await signinInput.click()
|
|
||||||
|
|
||||||
await page.waitForSelector('input[value="No"]')
|
|
||||||
const noInput = await page.$('input[value="No"]')
|
|
||||||
await noInput.click()
|
|
||||||
|
|
||||||
await page.waitForFunction(`window.location.href === '${callbackUrl}'`)
|
|
||||||
} catch (e) {
|
|
||||||
if (!redirected || thirdParty) throw e
|
|
||||||
}
|
|
||||||
}, 60000)
|
|
||||||
|
|
||||||
it("Is logged in", async () => {
|
|
||||||
await page.goto(callbackUrl + "signin")
|
|
||||||
await page.waitForFunction(`window.location.href === '${callbackUrl}'`)
|
|
||||||
}, 30000)
|
|
||||||
|
|
||||||
it("Is logged out", async () => {
|
|
||||||
await page.goto(
|
|
||||||
"https://login.microsoftonline.com/common/oauth2/v2.0/logout",
|
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForSelector(`div[data-test-id="${process.env.AUTH_EMAIL}"]`)
|
|
||||||
const signoutDiv = await page.$(
|
|
||||||
`div[data-test-id="${process.env.AUTH_EMAIL}"]`,
|
|
||||||
)
|
|
||||||
await signoutDiv.click()
|
|
||||||
|
|
||||||
await page.waitForFunction(
|
|
||||||
`window.location.href === 'https://login.microsoftonline.com/common/oauth2/v2.0/logoutsession'`,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Wait for the element to be visible in the page
|
|
||||||
await page.waitForSelector("#login_workload_logo_text")
|
|
||||||
// Get the element handle
|
|
||||||
const elementHandle = await page.$("#login_workload_logo_text")
|
|
||||||
// Get the inner text of the element
|
|
||||||
const innerText = await page.evaluate(
|
|
||||||
(element) => element.innerText,
|
|
||||||
elementHandle,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Assert that the inner text matches the expected text
|
|
||||||
expect(innerText.trim()).toBe("You signed out of your account")
|
|
||||||
}, 30000)
|
|
||||||
})
|
|
|
@ -1,57 +0,0 @@
|
||||||
const { PrismaClient } = require("@prisma/client")
|
|
||||||
const prisma = new PrismaClient()
|
|
||||||
const { createHash, randomBytes } = require("crypto")
|
|
||||||
|
|
||||||
describe("Check Email auth", () => {
|
|
||||||
const callbackUrl = process.env.NEXTAUTH_URL + "/"
|
|
||||||
const player1Email = "player1@example.com"
|
|
||||||
|
|
||||||
it("Email login process...", async () => {
|
|
||||||
await page.goto(callbackUrl + "signin")
|
|
||||||
|
|
||||||
await page.waitForSelector('input[type="email"]')
|
|
||||||
const emailInput = await page.$('input[type="email"]')
|
|
||||||
await emailInput.type(player1Email)
|
|
||||||
|
|
||||||
await page.click('button[type="submit"]')
|
|
||||||
|
|
||||||
await page.waitForFunction(
|
|
||||||
`window.location.href === '${callbackUrl}api/auth/verify-request?provider=email&type=email'`,
|
|
||||||
)
|
|
||||||
}, 30000)
|
|
||||||
|
|
||||||
it("Verify Email...", async () => {
|
|
||||||
const token = randomBytes(32).toString("hex")
|
|
||||||
|
|
||||||
const hash = createHash("sha256")
|
|
||||||
// Prefer provider specific secret, but use default secret if none specified
|
|
||||||
.update(`${token}${process.env.NEXTAUTH_SECRET}`)
|
|
||||||
.digest("hex")
|
|
||||||
|
|
||||||
// Use Prisma to fetch the latest token for the email
|
|
||||||
const latestToken = await prisma.VerificationToken.findFirst({
|
|
||||||
where: { identifier: player1Email },
|
|
||||||
orderBy: { expires: "desc" },
|
|
||||||
})
|
|
||||||
await prisma.VerificationToken.update({
|
|
||||||
where: {
|
|
||||||
identifier_token: {
|
|
||||||
identifier: player1Email,
|
|
||||||
token: latestToken.token,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data: { token: hash },
|
|
||||||
})
|
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
callbackUrl,
|
|
||||||
token,
|
|
||||||
email: player1Email,
|
|
||||||
})
|
|
||||||
const url = callbackUrl + "api/auth/callback/email?" + params
|
|
||||||
|
|
||||||
await page.goto(url)
|
|
||||||
|
|
||||||
await page.waitForFunction(`window.location.href === '${callbackUrl}'`)
|
|
||||||
}, 30000)
|
|
||||||
})
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Build the project
|
|
||||||
pnpm run build
|
|
||||||
|
|
||||||
# Function to kill the server process
|
|
||||||
function kill_server {
|
|
||||||
local server_pid=$(lsof -i :3000 -t)
|
|
||||||
if [[ -n $server_pid ]]; then
|
|
||||||
echo "Killing server..." $server_pid
|
|
||||||
kill -15 $server_pid
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to run the tests
|
|
||||||
function run_tests {
|
|
||||||
pnpm test
|
|
||||||
}
|
|
||||||
|
|
||||||
# Start the server in the background
|
|
||||||
pnpm run start &
|
|
||||||
|
|
||||||
# Capture exit signals and execute the kill_server function
|
|
||||||
trap kill_server EXIT ERR
|
|
||||||
|
|
||||||
# Run the tests
|
|
||||||
run_tests
|
|
85
leaky-ships/e2e/auth.spec.ts
Normal file
85
leaky-ships/e2e/auth.spec.ts
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import { expect, test, type BrowserContext, type Page } from "@playwright/test"
|
||||||
|
|
||||||
|
const callbackUrl = process.env.NEXTAUTH_URL + "/"
|
||||||
|
let context: BrowserContext
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.describe.serial("Check Azure AD auth", () => {
|
||||||
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test.afterAll(async () => {
|
||||||
|
await context.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Login process...", async ({ browser }) => {
|
||||||
|
await page.goto(callbackUrl + "signin")
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole("button", { name: "Microsoft_icon Sign in with Microsoft" })
|
||||||
|
.click()
|
||||||
|
|
||||||
|
const emailLocator = page.locator(
|
||||||
|
`[data-test-id="${process.env.AUTH_EMAIL ?? ""}"]`,
|
||||||
|
)
|
||||||
|
if (await emailLocator.isVisible()) {
|
||||||
|
await emailLocator.click()
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"The email locator is not present on the page. Skipping this step.",
|
||||||
|
)
|
||||||
|
// Optionally, you can throw an error, fail the test, or take any other desired action here.
|
||||||
|
}
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByLabel("someone@example.com")
|
||||||
|
.fill(process.env.AUTH_EMAIL ?? "")
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "Next" }).click()
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
|
||||||
|
await page.getByLabel("Password").fill(process.env.AUTH_PW ?? "")
|
||||||
|
await page.getByRole("button", { name: "Sign in" }).click()
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "No" }).click({})
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
|
||||||
|
await page.waitForURL(
|
||||||
|
callbackUrl + (browser.browserType().name() === "webkit" ? "#" : ""),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Is logged in", async () => {
|
||||||
|
await page.goto(callbackUrl + "signin")
|
||||||
|
await page.waitForURL(callbackUrl)
|
||||||
|
expect(await page.screenshot()).toMatchSnapshot("1.png")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Is logged out", async () => {
|
||||||
|
await page.goto(
|
||||||
|
"https://login.microsoftonline.com/common/oauth2/v2.0/logout",
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.waitForLoadState("domcontentloaded")
|
||||||
|
|
||||||
|
const emailLocator = page.locator(
|
||||||
|
`[data-test-id="${process.env.AUTH_EMAIL ?? ""}"]`,
|
||||||
|
)
|
||||||
|
if (await emailLocator.isVisible()) {
|
||||||
|
await emailLocator.click()
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"The email locator is not present on the page. Skipping this step.",
|
||||||
|
)
|
||||||
|
// Optionally, you can throw an error, fail the test, or take any other desired action here.
|
||||||
|
}
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole("heading", { name: "You signed out of your account" })
|
||||||
|
.click()
|
||||||
|
})
|
||||||
|
})
|
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-chromium-linux.png
Normal file
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-chromium-linux.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-firefox-linux.png
Normal file
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-firefox-linux.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-webkit-linux.png
Normal file
BIN
leaky-ships/e2e/auth.spec.ts-snapshots/1-webkit-linux.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
72
leaky-ships/e2e/email.spec.ts
Normal file
72
leaky-ships/e2e/email.spec.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import {
|
||||||
|
test,
|
||||||
|
type Browser,
|
||||||
|
type BrowserContext,
|
||||||
|
type Page,
|
||||||
|
} from "@playwright/test"
|
||||||
|
import { createHash, randomBytes } from "crypto"
|
||||||
|
import prisma from "../lib/prisma"
|
||||||
|
|
||||||
|
const callbackUrl = process.env.NEXTAUTH_URL + "/"
|
||||||
|
const player1Email = (browser: Browser) =>
|
||||||
|
browser.browserType().name() + "-player-1@example.com"
|
||||||
|
|
||||||
|
let context: BrowserContext
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.describe.serial("Check Email auth", () => {
|
||||||
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test.afterAll(async () => {
|
||||||
|
await context.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Email login process...", async ({ browser }) => {
|
||||||
|
await page.goto(callbackUrl + "signin")
|
||||||
|
|
||||||
|
await page.getByPlaceholder("user@example.com").fill(player1Email(browser))
|
||||||
|
await page.getByRole("button", { name: "Sign in with Email" }).click()
|
||||||
|
|
||||||
|
await page.waitForURL(
|
||||||
|
callbackUrl + "api/auth/verify-request?provider=email&type=email",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Verify Email...", async ({ browser }) => {
|
||||||
|
const token = randomBytes(32).toString("hex")
|
||||||
|
|
||||||
|
const hash = createHash("sha256")
|
||||||
|
// Prefer provider specific secret, but use default secret if none specified
|
||||||
|
.update(`${token}${process.env.NEXTAUTH_SECRET}`)
|
||||||
|
.digest("hex")
|
||||||
|
|
||||||
|
// Use Prisma to fetch the latest token for the email
|
||||||
|
const latestToken = await prisma.verificationToken.findFirst({
|
||||||
|
where: { identifier: player1Email(browser) },
|
||||||
|
orderBy: { expires: "desc" },
|
||||||
|
})
|
||||||
|
await prisma.verificationToken.update({
|
||||||
|
where: {
|
||||||
|
identifier_token: {
|
||||||
|
identifier: player1Email(browser),
|
||||||
|
token: latestToken?.token ?? "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: { token: hash },
|
||||||
|
})
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
callbackUrl,
|
||||||
|
token,
|
||||||
|
email: player1Email(browser),
|
||||||
|
})
|
||||||
|
const url = callbackUrl + "api/auth/callback/email?" + params
|
||||||
|
|
||||||
|
await page.goto(url)
|
||||||
|
|
||||||
|
await page.waitForLoadState("domcontentloaded")
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
verbose: true,
|
|
||||||
preset: "jest-puppeteer",
|
|
||||||
setupFiles: ["dotenv/config"],
|
|
||||||
}
|
|
5
leaky-ships/kill-server.sh
Executable file
5
leaky-ships/kill-server.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
server_pid=$(lsof -i :3000 -t)
|
||||||
|
if [[ -n $server_pid ]]; then
|
||||||
|
echo "Killing server..." $server_pid
|
||||||
|
kill -9 $server_pid
|
||||||
|
fi
|
|
@ -7,8 +7,7 @@
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"test": "jest -w 1",
|
"test": "pnpm playwright test --ui"
|
||||||
"build-start-test": "./build-start-test.sh"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||||
|
@ -46,6 +45,7 @@
|
||||||
"zustand": "^4.3.9"
|
"zustand": "^4.3.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.36.2",
|
||||||
"@total-typescript/ts-reset": "^0.3.7",
|
"@total-typescript/ts-reset": "^0.3.7",
|
||||||
"@types/node": "^18.17.0",
|
"@types/node": "^18.17.0",
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
|
@ -54,8 +54,6 @@
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"jest": "^29.6.1",
|
|
||||||
"jest-puppeteer": "^9.0.0",
|
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"prettier-plugin-organize-imports": "^3.2.3",
|
"prettier-plugin-organize-imports": "^3.2.3",
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default function Home() {
|
||||||
<Logo />
|
<Logo />
|
||||||
<BurgerMenu />
|
<BurgerMenu />
|
||||||
<div className="flex h-36 w-64 items-center justify-center overflow-hidden rounded-xl border-8 border-black bg-[#2227] sm:h-48 sm:w-96 md:h-72 md:w-[32rem] md:border-[6px] xl:h-[26rem] xl:w-[48rem]">
|
<div className="flex h-36 w-64 items-center justify-center overflow-hidden rounded-xl border-8 border-black bg-[#2227] sm:h-48 sm:w-96 md:h-72 md:w-[32rem] md:border-[6px] xl:h-[26rem] xl:w-[48rem]">
|
||||||
<video controls>
|
<video controls preload="metadata">
|
||||||
<source src="/Regelwerk.mp4" type="video/mp4" />
|
<source src="/Regelwerk.mp4" type="video/mp4" />
|
||||||
Your browser does not support the video tag.
|
Your browser does not support the video tag.
|
||||||
</video>
|
</video>
|
||||||
|
|
77
leaky-ships/playwright.config.ts
Normal file
77
leaky-ships/playwright.config.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import { defineConfig, devices } from "@playwright/test"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
require("dotenv").config()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: "./e2e",
|
||||||
|
/* Run tests in files in parallel */
|
||||||
|
fullyParallel: true,
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: "html",
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://127.0.0.1:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: "on-first-retry",
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Configure projects for major browsers */
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: "chromium",
|
||||||
|
use: { ...devices["Desktop Chrome"] },
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "firefox",
|
||||||
|
use: { ...devices["Desktop Firefox"] },
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "webkit",
|
||||||
|
use: { ...devices["Desktop Safari"] },
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Test against mobile viewports. */
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Chrome',
|
||||||
|
// use: { ...devices['Pixel 5'] },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Safari',
|
||||||
|
// use: { ...devices['iPhone 12'] },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Test against branded browsers. */
|
||||||
|
// {
|
||||||
|
// name: 'Microsoft Edge',
|
||||||
|
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Google Chrome',
|
||||||
|
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
|
||||||
|
/* Run your local dev server before starting the tests */
|
||||||
|
webServer: {
|
||||||
|
command: "pnpm run start",
|
||||||
|
url: process.env.NEXTAUTH_URL,
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
},
|
||||||
|
})
|
2483
leaky-ships/pnpm-lock.yaml
generated
2483
leaky-ships/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue