1
0

Remove e2e folder

This commit is contained in:
2026-03-25 19:28:55 +01:00
parent dfe13b093d
commit 202b827d8b
18 changed files with 81 additions and 82 deletions

View File

@@ -92,5 +92,5 @@ jobs:
- name: Full integration test (Playwright)
if: steps.check-e2e.outputs.run == 'true' && env.GITEA_ACTIONS != 'true'
run: |
cd tests/e2e
cd tests
./run-e2e.sh

10
.gitignore vendored
View File

@@ -33,11 +33,11 @@ electron/release/
tests/cached_assets/
# E2E tests
tests/e2e/node_modules/
tests/e2e/test-results/
tests/e2e/playwright-report/
tests/e2e/screenshots/
tests/e2e/test_firmware.zip
tests/node_modules/
tests/test-results/
tests/playwright-report/
tests/screenshots/
tests/test_firmware.zip
# NickelMenu build artifacts
nickelmenu/kobo-config/

View File

@@ -114,19 +114,19 @@ kobopatch-wasm/
tests/
cached_assets/ # Downloaded test assets (gitignored)
e2e/
helpers/ # Shared test utilities
assets.js # Asset availability checks, firmware symlink helpers
mock-device.js # Mock File System Access API (simulated Kobo device)
paths.js # Test asset paths, expected checksums
tar.js # Tar archive parser for output verification
integration.spec.js # Playwright E2E tests
playwright.config.js # Parallel by default; serial when --headed or --slow
global-setup.js # Creates firmware symlink once before all tests
run-e2e.sh
screenshots.mjs # Captures screenshots of every wizard step
screenshots.config.js # Mobile + desktop project config for screenshots
run-screenshots.sh # Runs screenshot capture
helpers/ # Shared test utilities
assets.js # Asset availability checks, firmware symlink helpers
mock-device.js # Mock File System Access API (simulated Kobo device)
paths.js # Test asset paths, expected checksums
tar.js # Tar archive parser for output verification
build.spec.js # Build output verification tests
integration.spec.js # Playwright E2E tests
playwright.config.js # Parallel by default; serial when --headed or --slow
global-setup.js # Creates firmware symlink once before all tests
run-e2e.sh
screenshots.mjs # Captures screenshots of every wizard step
screenshots.config.js # Mobile + desktop project config for screenshots
run-screenshots.sh # Runs screenshot capture
# Root scripts
test.sh # Runs all tests (WASM + E2E)
@@ -262,7 +262,7 @@ The simulated device tests mock the File System Access API with an in-memory fil
Custom patches tests use firmware 4.45.23646 (~150 MB, cached in `tests/cached_assets/`), enable a single patch, and verify SHA1 checksums of all 4 patched binaries. This specific combination is used because the author has tested it on an actual device. KOReader tests use a real KOReader zip (~39 MB, also cached) to verify the full installation flow.
```bash
cd tests/e2e
cd tests
./run-e2e.sh
```
@@ -291,11 +291,11 @@ Extra Playwright arguments can be passed after `--`:
Capture screenshots of every wizard step for visual review (mobile + desktop):
```bash
cd tests/e2e
cd tests
./run-screenshots.sh
```
Output is saved to `tests/e2e/screenshots/mobile/` and `tests/e2e/screenshots/desktop/` (gitignored). The script uses a separate Playwright config (`screenshots.config.js`) with two projects: mobile (393×852, 3× DPI) and desktop (1280×900, 3× DPI). Screenshots cover the full wizard flow including device connection, mode selection, NickelMenu configuration, custom patches, error states, dialogs, and the feedback widget.
Output is saved to `tests/screenshots/mobile/` and `tests/screenshots/desktop/` (gitignored). The script uses a separate Playwright config (`screenshots.config.js`) with two projects: mobile (393×852, 3× DPI) and desktop (1280×900, 3× DPI). Screenshots cover the full wizard flow including device connection, mode selection, NickelMenu configuration, custom patches, error states, dialogs, and the feedback widget.
### WASM integration test

View File

@@ -88,7 +88,7 @@ fi
echo ""
echo "=== Running E2E tests (Playwright) ==="
cd "$SCRIPT_DIR/tests/e2e"
cd "$SCRIPT_DIR/tests"
if [ ! -d "node_modules" ]; then
npm install
npx playwright install --with-deps

53
tests/build.spec.js Normal file
View File

@@ -0,0 +1,53 @@
// @ts-check
const { test, expect } = require('@playwright/test');
const fs = require('fs');
const path = require('path');
const distDir = path.join(__dirname, '..', 'web', 'dist');
test.describe('Build output', () => {
test('CSS cache-bust hash is present on style.css link', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).toMatch(/css\/style\.css\?h=[0-9a-f]{8}/);
});
test('JS cache-bust hash is present on bundle.js script', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).toMatch(/bundle\.js\?h=[0-9a-f]{8}/);
});
test('critical CSS is inlined with :root tokens', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
// :root block should be inside an inline <style> tag, not in a <link>
expect(html).toMatch(/<style>[^<]*:root\{[^}]*--primary:/);
// var() references should be used (not hardcoded hex colors for themed values)
expect(html).toMatch(/<style>[^<]*var\(--primary\)/);
});
test('style.css does not contain a :root block', async () => {
const css = fs.readFileSync(path.join(distDir, 'css', 'style.css'), 'utf-8');
expect(css).not.toContain(':root');
});
test('--primary-hover differs from --primary', async () => {
const critical = fs.readFileSync(
path.join(__dirname, '..', 'web', 'src', 'css', 'critical.css'), 'utf-8'
);
const primary = critical.match(/--primary:\s*([^;]+);/);
const hover = critical.match(/--primary-hover:\s*([^;]+);/);
expect(primary).not.toBeNull();
expect(hover).not.toBeNull();
expect(primary[1].trim()).not.toBe(hover[1].trim());
});
test('no jszip script tag in built HTML', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).not.toContain('jszip');
});
test('no unreplaced template placeholders in built HTML', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).not.toMatch(/\{\{[\w-]+\}\}/);
expect(html).not.toContain('@critical-css');
});
});

View File

@@ -1,10 +1,10 @@
const path = require('path');
const CACHED_ASSETS = path.resolve(__dirname, '..', '..', 'cached_assets');
const CACHED_ASSETS = path.resolve(__dirname, '..', 'cached_assets');
const FIRMWARE_PATH = path.join(CACHED_ASSETS, 'kobo-update-4.45.23646.zip');
const WEBROOT = path.resolve(__dirname, '..', '..', '..', 'web', 'dist');
const WEBROOT = path.resolve(__dirname, '..', '..', 'web', 'dist');
const WEBROOT_FIRMWARE = path.join(WEBROOT, '_test_firmware.zip');
// Expected SHA1 checksums for Kobo Libra Color, firmware 4.45.23646,

View File

@@ -1156,57 +1156,3 @@ test.describe('Custom patches', () => {
await expect(page.locator('#step-connect')).not.toBeHidden();
});
});
// ============================================================
// Build output
// ============================================================
test.describe('Build output', () => {
const path = require('path');
const distDir = path.join(__dirname, '..', '..', 'web', 'dist');
test('CSS cache-bust hash is present on style.css link', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).toMatch(/css\/style\.css\?h=[0-9a-f]{8}/);
});
test('JS cache-bust hash is present on bundle.js script', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).toMatch(/bundle\.js\?h=[0-9a-f]{8}/);
});
test('critical CSS is inlined with :root tokens', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
// :root block should be inside an inline <style> tag, not in a <link>
expect(html).toMatch(/<style>[^<]*:root\{[^}]*--primary:/);
// var() references should be used (not hardcoded hex colors for themed values)
expect(html).toMatch(/<style>[^<]*var\(--primary\)/);
});
test('style.css does not contain a :root block', async () => {
const css = fs.readFileSync(path.join(distDir, 'css', 'style.css'), 'utf-8');
expect(css).not.toContain(':root');
});
test('--primary-hover differs from --primary', async () => {
const critical = fs.readFileSync(
path.join(__dirname, '..', '..', 'web', 'src', 'css', 'critical.css'), 'utf-8'
);
const primary = critical.match(/--primary:\s*([^;]+);/);
const hover = critical.match(/--primary-hover:\s*([^;]+);/);
expect(primary).not.toBeNull();
expect(hover).not.toBeNull();
expect(primary[1].trim()).not.toBe(hover[1].trim());
});
test('no jszip script tag in built HTML', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).not.toContain('jszip');
});
test('no unreplaced template placeholders in built HTML', async () => {
const html = fs.readFileSync(path.join(distDir, 'index.html'), 'utf-8');
expect(html).not.toMatch(/\{\{[\w-]+\}\}/);
expect(html).not.toContain('@critical-css');
});
});

View File

@@ -22,7 +22,7 @@ module.exports = defineConfig({
},
},
webServer: {
command: 'cd ../../web && npm install && node build.mjs && cd ../kobopatch-wasm && bash build.sh && cd ../web && PORT=8889 node serve.mjs',
command: 'cd ../web && npm install && node build.mjs && cd ../kobopatch-wasm && bash build.sh && cd ../web && PORT=8889 node serve.mjs',
port: 8889,
reuseExistingServer: true,
},

View File

@@ -16,7 +16,7 @@ set -euo pipefail
cd "$(dirname "$0")"
PROJECT_ROOT="$(cd ../.. && pwd)"
PROJECT_ROOT="$(cd .. && pwd)"
WEB_DIR="$PROJECT_ROOT/web"
SRC_DIR="$WEB_DIR/src"
DIST_DIR="$WEB_DIR/dist"

View File

@@ -14,4 +14,4 @@ rm -rf screenshots
npx playwright test --config screenshots.config.js --reporter=list "$@"
echo ""
echo "Screenshots saved to tests/e2e/screenshots/"
echo "Screenshots saved to tests/screenshots/"