Add e2e tests with playwright (#8123)

This commit is contained in:
Michael Geers 2023-06-05 08:31:00 +02:00 • committed by GitHub
parent 05e2281765
commit 0df815729b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 219 additions and 13 deletions

View file

@ -44,15 +44,31 @@ jobs:
steps:
- uses: actions/checkout@v3
# - uses: actions/setup-go@v4
- uses: erezrokah/setup-go@feat/add_cache_prefix
with:
go-version: ^1.20
cache-key-prefix: build-cache-
id: go
- uses: actions/setup-node@v3
with:
node-version: "18"
cache: "npm"
- name: Install UI
run: make install-ui
- name: Build UI
run: make ui
- name: Build
run: mkdir dist && touch dist/empty && make build
run: make build
- name: Upload
uses: actions/upload-artifact@v3
with:
name: evcc-binary
path: ./evcc
test:
name: Test
@ -92,7 +108,7 @@ jobs:
version: latest
args: --timeout 5m
build-ui:
ui:
name: UI
runs-on: ubuntu-latest
@ -104,7 +120,7 @@ jobs:
node-version: "18"
cache: "npm"
- name: Install tools
- name: Install
run: make install-ui
- name: Lint
@ -113,12 +129,48 @@ jobs:
- name: Test
run: make test-ui
- name: Build
run: make ui
- name: Porcelain
run: |
test -z "$(git status --porcelain)" || (git status; git diff; false)
- name: Cache dist
uses: actions/cache/save@v3
id: cache-dist
integration:
name: Integration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
path: dist
key: ${{ runner.os }}-${{ github.sha }}-dist
node-version: "18"
cache: "npm"
- name: Install npm
run: npm ci
- run: npx playwright install --with-deps chromium
- name: Wait for Build
uses: lewagon/wait-on-check-action@v1.3.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
check-name: Build
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
- uses: actions/download-artifact@v3
with:
name: evcc-binary
- name: Make executable
run: chmod +x evcc
- name: Run tests
run: npx playwright test
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30

4
.gitignore vendored
View file

@ -12,6 +12,7 @@ __debug_bin
!util/templates/**/*.yaml
!package*.json
!evcc.dist.yaml
!tests/**/*.evcc.yaml
evcc
evcc.exe
evcc_*
@ -32,3 +33,6 @@ fly.toml
vendor/*
QEMU_EFI.fd
asset-stats.html
/test-results/
/playwright-report/
/playwright/.cache/

View file

@ -1,5 +1,9 @@
<template>
<div class="visualization" :class="{ 'visualization--ready': visualizationReady }">
<div
data-testid="visualization"
class="visualization"
:class="{ 'visualization--ready': visualizationReady }"
>
<div class="label-scale d-flex">
<div class="d-flex justify-content-start flex-grow-1">
<LabelBar v-bind="labelBarProps('top', 'pvProduction')">

View file

@ -11,6 +11,7 @@
<Loadpoint
v-bind="loadpoint"
:id="index + 1"
data-testid="loadpoint"
:vehicles="vehicles"
:smartCostLimit="smartCostLimit"
:smartCostType="smartCostType"

30
package-lock.json generated
View file

@ -10,6 +10,7 @@
"@babel/core": "^7.17.2",
"@h2d2/shopicons": "^1.2.0",
"@histoire/plugin-vue": "^0.16.1",
"@playwright/test": "^1.34.3",
"@popperjs/core": "^2.11.5",
"@vitejs/plugin-legacy": "^4.0.2",
"@vitejs/plugin-vue": "^4.1.0",
@ -2356,6 +2357,24 @@
"node": ">= 8"
}
},
"node_modules/@playwright/test": {
"version": "1.34.3",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.34.3.tgz",
"integrity": "sha512-zPLef6w9P6T/iT6XDYG3mvGOqOyb6eHaV9XtkunYs0+OzxBtrPAAaHotc0X+PJ00WPPnLfFBTl7mf45Mn8DBmw==",
"dependencies": {
"@types/node": "*",
"playwright-core": "1.34.3"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=14"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.21",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
@ -6124,6 +6143,17 @@
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz",
"integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w=="
},
"node_modules/playwright-core": {
"version": "1.34.3",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.34.3.tgz",
"integrity": "sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/postcss": {
"version": "8.4.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",

View file

@ -7,13 +7,15 @@
"test": "TZ=Europe/Berlin vitest",
"lint": "prettier assets './**/*.{yml,yaml,toml}' --write && eslint assets/**/*.js assets/**/*.vue --fix",
"dev": "vite",
"histoire": "histoire dev"
"histoire": "histoire dev",
"playwright": "playwright test --ui"
},
"main": "index.js",
"dependencies": {
"@babel/core": "^7.17.2",
"@h2d2/shopicons": "^1.2.0",
"@histoire/plugin-vue": "^0.16.1",
"@playwright/test": "^1.34.3",
"@popperjs/core": "^2.11.5",
"@vitejs/plugin-legacy": "^4.0.2",
"@vitejs/plugin-vue": "^4.1.0",

32
playwright.config.js Normal file
View file

@ -0,0 +1,32 @@
const { defineConfig, devices } = require("@playwright/test");
/**
* @see https://playwright.dev/docs/test-configuration
*/
module.exports = defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: false,
/* 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:7070",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
});

34
tests/basics.evcc.yaml Executable file
View file

@ -0,0 +1,34 @@
site:
title: Hello World
meters:
grid: grid
meters:
- name: grid
type: custom
power:
source: js
script: |
1000
loadpoints:
- title: Carport
charger: charger
chargers:
- name: charger
type: custom
enable:
source: js
script:
enabled:
source: js
script: |
false
status:
source: js
script: |
"B"
maxcurrent:
source: js
script:

40
tests/basics.spec.js Normal file
View file

@ -0,0 +1,40 @@
const { test, expect } = require("@playwright/test");
const { execEvcc } = require("./utils");
let server;
test.beforeAll(() => {
server = execEvcc("basics.evcc.yaml");
});
test.afterAll(() => {
server.kill();
});
test.beforeEach(async ({ page }) => {
await page.goto("/");
});
test.describe("main screen", async () => {
test("site title", async ({ page }) => {
await expect(page.getByRole("heading", { name: "Hello World" })).toBeVisible();
});
test("visualization", async ({ page }) => {
const locator = page.getByTestId("visualization");
await expect(locator).toBeVisible();
await expect(locator).toContainText("1,000 W");
});
test("one loadpoint", async ({ page }) => {
await expect(page.getByTestId("loadpoint")).toHaveCount(1);
});
test("loadpoint title", async ({ page }) => {
await expect(page.getByRole("heading", { name: "Carport" })).toBeVisible();
});
test("guest vehicle", async ({ page }) => {
await expect(page.getByRole("heading", { name: "Guest vehicle" })).toBeVisible();
});
});

7
tests/utils.js Normal file
View file

@ -0,0 +1,7 @@
import { exec } from "child_process";
export function execEvcc(config) {
const server = exec(`./evcc --config tests/${config}`);
server.stdout.pipe(process.stdout);
return server;
}