When an app rides onion, Playwright routes through the node Tor SOCKS
proxy, which cannot resolve the clearnet-internal SeaweedFS filer UI
domain (net::ERR_SOCKS_CONNECTION_FAILED). Skip the filer storage check
on onion targets in all consumer specs — same pattern already proven in
the nextcloud spec. Clearnet runs are unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Over Tor the redirect chain behind a login/logout/OIDC click routinely exceeds Playwright's fixed 30s action timeout, so the click throws before the flow's scaled waits run. Sweep all role Playwright suites and the shared persona helpers: give every navigation/auth-transition click an onion-scaled timeout (.click({ timeout: resolveTimeout(30_000) })) and route the remaining raw millisecond literals (timeout options, waitForTimeout, sleep-promise setTimeout, positional wait args) through resolveTimeout. Local UI clicks (menus, toggles, modal dismissals, DOM clicks inside evaluate) stay untouched.
Two new lints keep it that way: test_no_raw_timeout_literals forbids raw numeric timeout literals in Playwright specs (opt-out: nocheck: raw-timeout), test_persona_clicks_scaled requires every click in the shared persona auth flows to carry a resolveTimeout timeout (opt-out: nocheck: unscaled-click).
Verified: node --check on all 133 changed JS files, all 13 playwright lints green, make autoformat clean, make test green (2745+196+163+4 tests OK).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A bare input[type=file] .first() can bind the dashboard's .penpot/.zip import uploader during the SPA transition into the workspace, pushing the PNG through the import pipeline (media object not found dialog) instead of the toolbar image upload. Target #image-upload explicitly and scope the layer assertion to the Layers tabpanel, since the import-error dialog lists the filename too and a page-wide match would false-pass on the exact failure.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Penpot is content-addressable and re-encodes uploads server-side, so the fixed fixture image (plus bytes appended after IEND, which the re-encode strips) deduped to a single object; on a second variant deploy the bucket already held it, so 'objects after > before' failed. Add a uniqueImagePng(seed) generator whose decoded pixels vary per run, so each upload produces a genuinely new bucket object.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the global TIMEOUT_FACTOR and a shared timeouts.js helper: resolveTimeout(base) scales by TIMEOUT_FACTOR and, over a .onion target, an extra multiplier, so Tor's per-request latency no longer trips hard-coded timeouts. Migrate every raw timeout in the specs (timeout:/timeout=/setTimeout/waitForTimeout) to resolveTimeout, stage the helper in all three staging paths, and add test_no_raw_timeouts to forbid raw numeric timeouts. Clearnet behaviour is unchanged (factor 1: resolveTimeout(N) === N).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Penpot dedupes assets by content digest, so re-running the seaweedfs
spec against a persistent bucket wrote no new object and the bucket
check failed. The marker is appended to the PNG bytes after IEND.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Penpot validates raster uploads with ImageMagick `identify` and rejected the
1x1 transparent PNG as :invalid-image ("Seems that this is not a valid image"),
so no asset layer was created and the marker assertion timed out at 60s.
Add a real 32x32 opaque RGB PNG (validImagePng) in _shared.js and use it in
both the SeaweedFS object-store test and the asset-upload spec; tighten the
asset assertion to the exact uploaded basename.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add files/playwright/test-seaweedfs.js (+ SEAWEEDFS_* playwright.env vars, spec require wiring, and removal of the playwright-service-flag nocheck above the seaweedfs service) for baserow, bookwyrm, mattermost, openwebui, peertube, penpot, pixelfed. Each test reuses the role's real login flow and triggers an upload that writes to the app's S3 bucket (file-field, avatar, chat attachment, composer photo, video), verified via the shared runSeaweedfsStorageCheck (bucket grew through the Filer UI).
openwebui: also export dismissAllOpenModals from _shared.js (used by the new test) and match the uploaded file by basename (not the full filename) to avoid the extension-split false-negative.
Exempt gitea and opentalk via meta/services.yml nocheck markers (seaweedfs-playwright + playwright-service-flag): gitea has no automatable UI login in this stack (oauth2-proxy + OIDC account-link / native login both fail; personas blocked); opentalk only writes S3 for recordings/whiteboard exports, which need the recorder service + a live multi-party meeting.
Builds on 9b6c6415f (shared runSeaweedfsStorageCheck helper + consumer lint).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>