1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 13:23:07 +01:00

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
This commit is contained in:
Amir Raminfar
2023-05-22 11:33:25 -07:00
committed by GitHub
parent 0d3bd7246a
commit b2844469d6
46 changed files with 1259 additions and 1746 deletions

3
e2e/.gitignore vendored
View File

@@ -1,3 +0,0 @@
videos
screenshots
__diff_output__

View File

@@ -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
View 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
View 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/);
});

View File

@@ -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);
},
},
});

View File

@@ -1,4 +0,0 @@
{
"DOZZLE_DEFAULT": "http://localhost:8080/",
"DOZZLE_AUTH": "http://localhost:8080/"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -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");
});
});

View File

@@ -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");
});
});

View File

@@ -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");
});
});

View File

@@ -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;
});
});
});

View File

@@ -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");
});
});

View File

@@ -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();
});
});

View File

@@ -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/");
});
});

View File

@@ -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"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -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()));
});

View File

@@ -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')

View File

@@ -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
View 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();
});
});

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "node"]
},
"include": ["**/*.ts"]
}

20
e2e/visual.spec.ts Normal file
View 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({});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB