chore(e2e): updates testing to use playwright (#2181)
* chore(e2e): updates testing to use playwright * chore: updates workflows * fixes spaces * fixes space again * fixes int test to add docker * chore: ignore e2e tests for vite * updates screenshots for linux * updates screenshots again * chore: uses docker compose for e2e * adds PWTEST_SKIP_TEST_OUTPUT * add ci * updates screenshots again * updates with css * adds more tests * updates tests
28
.github/workflows/test.yml
vendored
@@ -61,19 +61,37 @@ jobs:
|
||||
run: make test SKIP_ASSET=1
|
||||
int-test:
|
||||
name: Integration Tests
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
name: Install Node
|
||||
with:
|
||||
node-version: latest
|
||||
- run: corepack enable
|
||||
- run: pnpm --version
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: latest
|
||||
cache: "pnpm"
|
||||
cache-dependency-path: "**/pnpm-lock.yaml"
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Build
|
||||
uses: docker/bake-action@v3
|
||||
with:
|
||||
workdir: ./e2e
|
||||
load: true
|
||||
set: |
|
||||
*.cache-from=type=gha
|
||||
*.cache-to=type=gha,mode=max
|
||||
- name: Run tests
|
||||
run: docker compose -f e2e/docker-compose.yml up --exit-code-from cypress
|
||||
- name: Run Playwright tests
|
||||
run: docker compose up --exit-code-from playwright
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
|
||||
3
.gitignore
vendored
@@ -9,3 +9,6 @@ coverage
|
||||
.vscode
|
||||
coverage.out
|
||||
.netlify
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
|
||||
2
Makefile
@@ -31,4 +31,4 @@ dev:
|
||||
|
||||
.PHONY: int
|
||||
int:
|
||||
docker-compose -f e2e/docker-compose.yml up --build --force-recreate --exit-code-from cypress
|
||||
docker compose up --force-recreate --exit-code-from playwright
|
||||
|
||||
999
assets/auto-imports.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<time :datetime="date.toISOString()">{{ text }}</time>
|
||||
<time :datetime="date.toISOString()" data-ci-skip>{{ text }}</time>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -40,7 +40,12 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="column is-narrow py-0" :class="secured ? 'pl-0 pr-1' : 'px-0'">
|
||||
<router-link :to="{ name: 'settings' }" active-class="is-active" class="button is-rounded is-small">
|
||||
<router-link
|
||||
:to="{ name: 'settings' }"
|
||||
active-class="is-active"
|
||||
class="button is-rounded is-small"
|
||||
:aria-label="$t('title.settings')"
|
||||
>
|
||||
<span class="icon">
|
||||
<mdi:light-cog />
|
||||
</span>
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
<p class="heading">{{ $t("label.running") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item has-text-centered">
|
||||
<div class="level-item has-text-centered" data-ci-skip>
|
||||
<div>
|
||||
<p class="title" data-ci-skip>{{ totalCpu }}%</p>
|
||||
<p class="title">{{ totalCpu }}%</p>
|
||||
<p class="heading">{{ $t("label.total-cpu-usage") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item has-text-centered">
|
||||
<div class="level-item has-text-centered" data-ci-skip>
|
||||
<div>
|
||||
<p class="title" data-ci-skip>{{ formatBytes(totalMem) }}</p>
|
||||
<p class="title">{{ formatBytes(totalMem) }}</p>
|
||||
<p class="heading">{{ $t("label.total-mem-usage") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
52
docker-compose.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
custom_base:
|
||||
container_name: custom_base
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=custom_base
|
||||
- DOZZLE_BASE=/foobarbase
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
ports:
|
||||
- 8080:8080
|
||||
build:
|
||||
context: .
|
||||
auth:
|
||||
container_name: auth
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=auth
|
||||
- DOZZLE_USERNAME=foo
|
||||
- DOZZLE_PASSWORD=bar
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
ports:
|
||||
- 9090:8080
|
||||
build:
|
||||
context: .
|
||||
dozzle:
|
||||
container_name: dozzle
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=dozzle
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
ports:
|
||||
- 7070:8080
|
||||
build:
|
||||
context: .
|
||||
playwright:
|
||||
container_name: playwright
|
||||
image: mcr.microsoft.com/playwright:v1.33.0-jammy
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
command: npx --yes playwright test
|
||||
environment:
|
||||
- PWTEST_SKIP_TEST_OUTPUT=1
|
||||
- CI=1
|
||||
depends_on:
|
||||
- dozzle
|
||||
- custom_base
|
||||
- auth
|
||||
3
e2e/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
videos
|
||||
screenshots
|
||||
__diff_output__
|
||||
@@ -1,11 +0,0 @@
|
||||
FROM cypress/included:12.12.0
|
||||
|
||||
RUN npm i -g pnpm
|
||||
|
||||
WORKDIR /e2e
|
||||
|
||||
COPY pnpm-lock.yaml ./
|
||||
RUN pnpm fetch
|
||||
|
||||
COPY package.json tsconfig.json ./
|
||||
RUN pnpm install --offline
|
||||
9
e2e/auth.spec.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("authentication", async ({ page }) => {
|
||||
await page.goto("http://auth:8080/");
|
||||
await page.locator('input[name="username"]').fill("foo");
|
||||
await page.locator('input[name="password"]').fill("bar");
|
||||
await page.getByRole("button", { name: "Login" }).click();
|
||||
await expect(page.locator("p.menu-label")).toHaveText("Containers");
|
||||
});
|
||||
13
e2e/custom.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://custom_base:8080/foobarbase");
|
||||
});
|
||||
|
||||
test("has right title", async ({ page }) => {
|
||||
await expect(page).toHaveTitle(/.* - Dozzle/);
|
||||
});
|
||||
|
||||
test("url should have custom base", async ({ page }) => {
|
||||
await expect(page).toHaveURL(/foobarbase/);
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import { defineConfig } from "cypress";
|
||||
import { initPlugin } from "@frsource/cypress-plugin-visual-regression-diff/dist/plugins";
|
||||
|
||||
export default defineConfig({
|
||||
fixturesFolder: false,
|
||||
projectId: "8cua4m",
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
initPlugin(on, config);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"DOZZLE_DEFAULT": "http://localhost:8080/",
|
||||
"DOZZLE_AUTH": "http://localhost:8080/"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 34 KiB |
@@ -1,14 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle default mode", { baseUrl: Cypress.env("DOZZLE_AUTH") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
|
||||
it("login screen", () => {
|
||||
cy.get("input[name=username]").type("foo");
|
||||
cy.get("input[name=password]").type("bar");
|
||||
cy.get("button[type=submit]").click();
|
||||
cy.get("p.menu-label").should("contain", "Containers");
|
||||
});
|
||||
});
|
||||
@@ -1,31 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle default mode", { baseUrl: Cypress.env("DOZZLE_DEFAULT") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
|
||||
it("home screen", () => {
|
||||
cy.get("li.running", { timeout: 10000 }).removeDates().replaceSkippedElements().matchImage();
|
||||
});
|
||||
|
||||
it("correct title is shown", () => {
|
||||
cy.title().should("eq", "1 containers - Dozzle");
|
||||
|
||||
cy.get("li.running:first a").click();
|
||||
|
||||
cy.title().should("include", "- Dozzle");
|
||||
});
|
||||
|
||||
it("navigating to setting page works ", () => {
|
||||
cy.get("a[href='/settings']").click();
|
||||
|
||||
cy.contains("About");
|
||||
});
|
||||
|
||||
it("shortcut for fuzzy search works", () => {
|
||||
cy.get("body").type("{ctrl}k");
|
||||
|
||||
cy.get("input[placeholder='Search containers (⌘ + k, ⌃k)']").should("be.visible");
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle es lang", { baseUrl: Cypress.env("DOZZLE_DEFAULT") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/", {
|
||||
onBeforeLoad(win) {
|
||||
Object.defineProperty(win.navigator, "language", {
|
||||
value: "es_MX",
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should find contenedores", () => {
|
||||
cy.get("p.menu-label").should("contain", "Contenedores");
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle settings mode", { baseUrl: Cypress.env("DOZZLE_DEFAULT") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/version").clearLocalStorage().visit("/settings");
|
||||
});
|
||||
|
||||
it("scrollbars", () => {
|
||||
cy.contains("Use smaller scrollbars").click();
|
||||
cy.get("html").should("have.class", "has-custom-scrollbars");
|
||||
});
|
||||
|
||||
it("stopped containers", () => {
|
||||
cy.contains("Show stopped containers")
|
||||
.click()
|
||||
.then(() => {
|
||||
expect(JSON.parse(localStorage.getItem("DOZZLE_SETTINGS")).showAllContainers).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle custom base", { baseUrl: Cypress.env("DOZZLE_CUSTOM") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
|
||||
it("custom base should work", () => {
|
||||
cy.get("p.menu-label").should("contain", "Containers");
|
||||
});
|
||||
|
||||
it("url should be custom", () => {
|
||||
cy.url().should("include", "foobarbase");
|
||||
});
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle dark mode", { baseUrl: Cypress.env("DOZZLE_DEFAULT") }, () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
cy.window().then((win) => win.document.documentElement.setAttribute("data-theme", "dark"));
|
||||
});
|
||||
|
||||
it("home screen", () => {
|
||||
cy.get("li.running", { timeout: 10000 }).removeDates().replaceSkippedElements().matchImage();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context("Dozzle routes", { baseUrl: Cypress.env("DOZZLE_DEFAULT") }, () => {
|
||||
it("show", () => {
|
||||
cy.visit("/show?name=dozzle").url().should("include", "/container/");
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,45 +0,0 @@
|
||||
/// <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>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Cypress.Commands.add("removeDates", () => {
|
||||
cy.window().then((win) => win.document.querySelectorAll("time").forEach((el) => el.remove()));
|
||||
});
|
||||
|
||||
Cypress.Commands.add("replaceSkippedElements", () => {
|
||||
cy.window().then((win) => win.document.querySelectorAll("[data-ci-skip]").forEach((el) => el.remove()));
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
// ***********************************************************
|
||||
// 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";
|
||||
import "@frsource/cypress-plugin-visual-regression-diff/dist/support";
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
// be explicit about types included
|
||||
// to avoid clashing with Jest types
|
||||
"types": ["cypress"]
|
||||
},
|
||||
"include": [
|
||||
"../node_modules/cypress",
|
||||
"./**/*.ts",
|
||||
"./**/*.js"
|
||||
]
|
||||
}
|
||||
32
e2e/default.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://dozzle:8080/");
|
||||
});
|
||||
|
||||
test("has right title", async ({ page }) => {
|
||||
await expect(page).toHaveTitle(/.* - Dozzle/);
|
||||
});
|
||||
|
||||
test("click on settings button", async ({ page }) => {
|
||||
await page.getByRole("link", { name: "Settings" }).click();
|
||||
await expect(page.getByRole("heading", { name: "About" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("shortcut for fuzzy search", async ({ page }) => {
|
||||
await page.locator("body").press("Control+k");
|
||||
await expect(page.locator(".modal").getByPlaceholder("Search containers (⌘ + k, ⌃k)")).toBeVisible();
|
||||
});
|
||||
|
||||
test("route by name", async ({ page }) => {
|
||||
await page.goto("http://dozzle:8080/show?name=dozzle");
|
||||
await expect(page).toHaveURL(/\/container/);
|
||||
});
|
||||
|
||||
test.describe("es locale", () => {
|
||||
test.use({ locale: "es" });
|
||||
|
||||
test("translated text", async ({ page }) => {
|
||||
await expect(page.locator("p.menu-label").getByText("Contenedores")).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
custom_base:
|
||||
container_name: custom_base
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=custom_base
|
||||
- DOZZLE_BASE=/foobarbase
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
image: amir20/dozzle_custom_cache
|
||||
build:
|
||||
context: ..
|
||||
cache_from:
|
||||
- amir20/dozzle_custom_cache:latest
|
||||
auth:
|
||||
container_name: auth
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=auth
|
||||
- DOZZLE_USERNAME=foo
|
||||
- DOZZLE_PASSWORD=bar
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
image: amir20/dozzle_custom_cache
|
||||
build:
|
||||
context: ..
|
||||
cache_from:
|
||||
- amir20/dozzle_custom_cache:latest
|
||||
dozzle:
|
||||
container_name: dozzle
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DOZZLE_FILTER=name=dozzle
|
||||
- DOZZLE_NO_ANALYTICS=1
|
||||
image: amir20/dozzle_cache:latest
|
||||
build:
|
||||
context: ..
|
||||
cache_from:
|
||||
- amir20/dozzle_cache:latest
|
||||
cypress:
|
||||
build:
|
||||
context: .
|
||||
cache_from:
|
||||
- amir20/dozzle_cypress_cache:latest
|
||||
image: amir20/dozzle_cypress_cache:latest
|
||||
working_dir: /e2e
|
||||
volumes:
|
||||
- ./cypress:/e2e/cypress
|
||||
- ./cypress.config.ts:/e2e/cypress.config.ts
|
||||
environment:
|
||||
- CYPRESS_DOZZLE_DEFAULT=http://dozzle:8080/
|
||||
- CYPRESS_DOZZLE_AUTH=http://auth:8080/
|
||||
- CYPRESS_DOZZLE_CUSTOM=http://custom_base:8080/foobarbase
|
||||
- CYPRESS_RECORD_KEY=155c3cf8-b2dd-4f5e-9fb3-7635f5b79d4d
|
||||
- COMMIT_INFO_BRANCH=${GITHUB_REF_NAME}
|
||||
- COMMIT_INFO_AUTHOR=${GITHUB_ACTOR}
|
||||
- COMMIT_INFO_SHA=${GITHUB_SHA}
|
||||
- COMMIT_INFO_MESSAGE=${GIT_LOG_MESSAGE}
|
||||
- COMMIT_INFO_REMOTE=https://github.com/amir20/dozzle
|
||||
command: cypress run --record
|
||||
depends_on:
|
||||
- dozzle
|
||||
- custom_base
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "e2e",
|
||||
"scripts": {
|
||||
"test": "cypress run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@frsource/cypress-plugin-visual-regression-diff": "^3.3.0",
|
||||
"cypress": "^12.12.0",
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
}
|
||||
1414
e2e/pnpm-lock.yaml
generated
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["es5", "dom"],
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
20
e2e/visual.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://dozzle:8080/");
|
||||
});
|
||||
|
||||
test.describe("default", () => {
|
||||
test("homepage", async ({ page }) => {
|
||||
await page.addStyleTag({ content: `[data-ci-skip] { visibility: hidden; }` });
|
||||
await expect(page).toHaveScreenshot({});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("dark", () => {
|
||||
test.use({ colorScheme: "dark" });
|
||||
test("homepage", async ({ page }) => {
|
||||
await page.addStyleTag({ content: `[data-ci-skip] { visibility: hidden; }` });
|
||||
await expect(page).toHaveScreenshot({});
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 17 KiB |
BIN
e2e/visual.spec.ts-snapshots/dark-homepage-1-chromium-linux.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
e2e/visual.spec.ts-snapshots/dark-homepage-1-webkit-linux.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 29 KiB |
BIN
e2e/visual.spec.ts-snapshots/default-homepage-1-webkit-linux.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
@@ -57,6 +57,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pinia/testing": "^0.1.2",
|
||||
"@playwright/test": "^1.33.0",
|
||||
"@types/d3-array": "^3.0.4",
|
||||
"@types/d3-ease": "^3.0.0",
|
||||
"@types/d3-scale": "^4.0.3",
|
||||
|
||||
71
playwright.config.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
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: "webkit",
|
||||
use: { ...devices["Desktop Safari"] },
|
||||
},
|
||||
|
||||
{
|
||||
name: "Mobile Chrome",
|
||||
use: { ...devices["Pixel 5"] },
|
||||
testMatch: "**/visual.spec.ts",
|
||||
},
|
||||
{
|
||||
name: "Mobile Safari",
|
||||
use: { ...devices["iPhone 12"] },
|
||||
testMatch: "**/visual.spec.ts",
|
||||
},
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
|
||||
// },
|
||||
],
|
||||
// webServer: {
|
||||
// command: "docker compose up",
|
||||
// url: "http://127.0.0.1:7070",
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
});
|
||||
20
pnpm-lock.yaml
generated
@@ -90,6 +90,9 @@ devDependencies:
|
||||
'@pinia/testing':
|
||||
specifier: ^0.1.2
|
||||
version: 0.1.2(pinia@2.1.3)(vue@3.3.4)
|
||||
'@playwright/test':
|
||||
specifier: ^1.33.0
|
||||
version: 1.33.0
|
||||
'@types/d3-array':
|
||||
specifier: ^3.0.4
|
||||
version: 3.0.4
|
||||
@@ -868,6 +871,17 @@ packages:
|
||||
- vue
|
||||
dev: true
|
||||
|
||||
/@playwright/test@1.33.0:
|
||||
resolution: {integrity: sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/node': 20.2.1
|
||||
playwright-core: 1.33.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@5.0.2:
|
||||
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -3430,6 +3444,12 @@ packages:
|
||||
pathe: 1.1.0
|
||||
dev: true
|
||||
|
||||
/playwright-core@1.33.0:
|
||||
resolution: {integrity: sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/postcss@8.4.23:
|
||||
resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
@@ -8,8 +8,7 @@ import IconsResolver from "unplugin-icons/resolver";
|
||||
import Pages from "vite-plugin-pages";
|
||||
import Layouts from "vite-plugin-vue-layouts";
|
||||
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
|
||||
import basicSsl from '@vitejs/plugin-basic-ssl'
|
||||
|
||||
import basicSsl from "@vitejs/plugin-basic-ssl";
|
||||
|
||||
export default defineConfig(() => ({
|
||||
resolve: {
|
||||
@@ -66,7 +65,7 @@ export default defineConfig(() => ({
|
||||
strictMessage: false,
|
||||
include: [path.resolve(__dirname, "locales/**")],
|
||||
}),
|
||||
basicSsl()
|
||||
basicSsl(),
|
||||
],
|
||||
server: {
|
||||
proxy: {
|
||||
@@ -79,4 +78,7 @@ export default defineConfig(() => ({
|
||||
},
|
||||
},
|
||||
},
|
||||
test: {
|
||||
include: ["assets/**/*.spec.ts"],
|
||||
},
|
||||
}));
|
||||
|
||||