mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
fix(web-app-peertube): repair the SeaweedFS object-store e2e test for PeerTube v8.2.1
The test timed out: the publish-button locator no longer matched the v8.2.1 manage-video wizard, and the inline 78-byte MP4 stub was structurally invalid, so PeerTube rejected the upload as "Video file unreadable" and left the Save button disabled. - test-seaweedfs.js: target the v8.2.1 save control (.save-button > button), upload PeerTube's real video_short.mp4 fixture, and assert a version-tolerant saved marker. - add fixture roles/web-app-peertube/files/playwright/fixtures/video_short.mp4. - test-e2e-playwright: stage role-local files/playwright/fixtures/ next to the tests (the *.js glob ships neither binaries nor subdirectories), so specs load a fixture via path.join(__dirname, "fixtures", <name>). - docs: document the fixtures/ folder and the per-scenario test-*.js split in the playwright spec contract and the runner README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
4efe7b0dfc
commit
3b60b36fb2
5 files changed
+25
-35
No files matched your search
@@ -10,6 +10,8 @@ For the env contract see [Agent `playwright.env.j2`](../../../../agents/files/ro
|
||||
|
||||
- The spec MUST be at `roles/<role>/files/playwright/playwright.spec.js`. The role-relative path is the SPOT constant `ROLE_FILE_PLAYWRIGHT_SPEC` in [mapping.py](../../../../../utils/roles/mapping.py); registered as optional on `ROLE_TYPE_APPLICATION`, disallowed elsewhere.
|
||||
- Companion `.js` helpers (role-local utility modules, like `web-app-dashboard/files/playwright/dashboard-card-flow.js`) MAY live next to the spec under the same `files/playwright/` directory. The runner (`roles/test-e2e-playwright/tasks/02_run_one.yml`) globs every `*.js` in that directory and stages them into the same `tests/` tree, so the spec can `require("./<helper>")` without any further wiring.
|
||||
- Each scenario MUST live in its own `test-*.js` module (e.g. `test-login-oidc.js`, `test-seaweedfs.js`). `playwright.spec.js` is the thin aggregator that `require()`s every scenario module, keeping each case atomic and individually inspectable. The runner globs every `*.js`, so no extra wiring is needed.
|
||||
- Binary fixtures (sample images, videos, …) MUST live under `roles/<role>/files/playwright/fixtures/`. The `*.js` glob does not ship binaries or subdirectories, so the runner stages the whole `fixtures/` directory next to the tests; specs load a fixture via `path.join(__dirname, "fixtures", "<name>")`.
|
||||
- `playwright.config.js` and `package.json` are central, NOT per-role. See [Playwright Tests → Role-Local Files](../../../actions/testing/playwright.md#role-local-files-).
|
||||
|
||||
## Three personas, fixed flow 🚶
|
||||
|
||||
@@ -26,7 +26,7 @@ This role:
|
||||
- Supports allow-/deny-lists via `TEST_E2E_PLAYWRIGHT_ONLY_ROLES` and `TEST_E2E_PLAYWRIGHT_SKIP_ROLES`
|
||||
- Stages each Playwright project into `TEST_E2E_PLAYWRIGHT_STAGE_BASE_DIR/<application_id>`
|
||||
- Renders the central `package.json` template into each staged project and injects the central `playwright.config.js`
|
||||
- Copies role-specific `files/playwright/playwright.spec.js` into the staged `tests/playwright.spec.js`
|
||||
- Copies every role-specific `files/playwright/*.js` (the `playwright.spec.js` aggregator plus its `test-*.js` scenario modules) into the staged `tests/` directory, and stages `files/playwright/fixtures/` (binary assets such as sample images/videos) alongside them
|
||||
- Renders `.env` from `templates/playwright.env.j2` using Ansible variables (`application_id`, `domains`, `users`, `applications`)
|
||||
- Optionally waits until the application responds with HTTP `200` or `302`
|
||||
- Injects CA trust automatically for `TLS_MODE=self_signed` (via `CA_TRUST.*`), so Playwright accepts self-signed cert chains
|
||||
|
||||
@@ -156,6 +156,20 @@
|
||||
with_fileglob:
|
||||
- "{{ _playwright_files_dir }}/*.js"
|
||||
|
||||
- name: Create staging fixtures directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ _playwright_stage_tests_dir }}/fixtures"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy role Playwright binary fixtures into staging fixtures directory
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ _playwright_stage_tests_dir }}/fixtures/{{ item | basename }}"
|
||||
mode: "0644"
|
||||
with_fileglob:
|
||||
- "{{ _playwright_files_dir }}/fixtures/*"
|
||||
|
||||
# Stage the shared service-gating helper next to the spec so the spec can
|
||||
# `require("./service-gating")`.
|
||||
- name: Copy shared service-gating helper into staging tests directory
|
||||
|
||||
Binary file not shown.
@@ -1,16 +1,4 @@
|
||||
// SeaweedFS object-store scenario for PeerTube.
|
||||
//
|
||||
// PeerTube is configured with S3 object storage for web videos
|
||||
// (PEERTUBE_OBJECT_STORAGE_ENABLED=true,
|
||||
// PEERTUBE_OBJECT_STORAGE_WEB_VIDEOS_BUCKET_NAME -> the consumer bucket,
|
||||
// PEERTUBE_OBJECT_STORAGE_WEB_VIDEOS_PREFIX=web-videos/). Avatars/thumbnails
|
||||
// stay on the local volume in this config, so the only user action that lands
|
||||
// in S3 is a video upload: PeerTube stores the web video locally and a
|
||||
// background job moves it into the bucket under web-videos/. The action signs
|
||||
// the administrator in over OIDC (mirroring playwright.spec.js), uploads a
|
||||
// minimal valid MP4 through the upload UI and waits for it to be published;
|
||||
// the shared check then proves the bucket grew via the Filer UI.
|
||||
|
||||
const path = require("path");
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { skipUnlessServiceEnabled } = require("./service-gating");
|
||||
const {
|
||||
@@ -28,13 +16,6 @@ const oidcButtonText = decodeDotenvQuotedValue(process.env.OIDC_BUTTON_TEXT || "
|
||||
const adminUsername = decodeDotenvQuotedValue(process.env.ADMIN_USERNAME || "");
|
||||
const adminPassword = decodeDotenvQuotedValue(process.env.ADMIN_PASSWORD || "");
|
||||
|
||||
function minimalMp4Buffer() {
|
||||
const base64 =
|
||||
"AAAAGGZ0eXBpc29tAAAAAGlzb21pc28yAAAACGZyZWUAAAAtbWRhdAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
return Buffer.from(base64, "base64");
|
||||
}
|
||||
|
||||
async function loginAdminViaOidc(page) {
|
||||
await page.goto(`${peertubeBaseUrl}/login`, { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -85,11 +66,7 @@ async function uploadWebVideo(page) {
|
||||
|
||||
const fileInput = page.locator("input[type='file']").first();
|
||||
await fileInput.waitFor({ state: "attached", timeout: 60_000 });
|
||||
await fileInput.setInputFiles({
|
||||
name: `${marker}.mp4`,
|
||||
mimeType: "video/mp4",
|
||||
buffer: minimalMp4Buffer(),
|
||||
});
|
||||
await fileInput.setInputFiles(path.join(__dirname, "fixtures", "video_short.mp4"));
|
||||
|
||||
const nameField = page
|
||||
.getByLabel(/name/i)
|
||||
@@ -98,10 +75,7 @@ async function uploadWebVideo(page) {
|
||||
await nameField.waitFor({ state: "visible", timeout: 60_000 });
|
||||
await nameField.fill(marker);
|
||||
|
||||
const publishButton = page
|
||||
.getByRole("button", { name: /^\s*publish\b/i })
|
||||
.or(page.locator("button.orange-button[type='submit'], my-button[type='submit'] button, button[type='submit']"))
|
||||
.first();
|
||||
const publishButton = page.locator(".save-button > button").first();
|
||||
await publishButton.waitFor({ state: "visible", timeout: 60_000 });
|
||||
|
||||
await expect
|
||||
@@ -113,14 +87,14 @@ async function uploadWebVideo(page) {
|
||||
|
||||
await publishButton.click();
|
||||
|
||||
const publishedMarker = page
|
||||
.locator("my-video-watch, .video-info-name, h1.video-info-name")
|
||||
.or(page.getByRole("heading", { name: marker }))
|
||||
const savedMarker = page
|
||||
.locator(".save-button > button[disabled]")
|
||||
.or(page.locator("my-video-watch, .video-info-name, h1.video-info-name"))
|
||||
.or(page.getByText(marker, { exact: false }))
|
||||
.first();
|
||||
await expect(
|
||||
publishedMarker,
|
||||
`the uploaded video '${marker}' must be accepted by PeerTube before the S3 move job runs`,
|
||||
savedMarker,
|
||||
`the uploaded video '${marker}' must be saved by PeerTube before the S3 move job runs`,
|
||||
).toBeVisible({ timeout: 120_000 });
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user