Skip to content

v0.65.0

Choose a tag to compare

@PhenX PhenX released this 03 Nov 21:56
5615b3b

This release keeps the errors Playwright reports outside the tests and what each test wrote to its output, lets you pause and watch a running test from its row on the run page, tightens sign-in, host checks and request limits, and fixes how runs are ingested, sharded, counted, clustered and announced.

Full diff: v0.64.0…v0.65.0

✨ Highlights

  • 🧾 Errors outside the tests and test output — The reporter keeps the errors Playwright reports outside the tests, shown on the run page, and what each test wrote to stdout and stderr, shown on its Output tab; an imported blob report brings both along.
  • ⏸️ Pause and watch from the run page — A running test can be paused and watched from its row on the run page, in the dashboard and in the desktop app.
  • 🔐 Sign-in, hosts and request limits — Bodies read before a credential are capped at 64 KiB, password hashes are queued with a share per client, PIWI_AUTH_SECRET must be at least 32 characters, and with authentication off the server answers only local hosts, the site URL and the names PIWI_ALLOWED_HOSTS lists.
  • 🙈 Secrets in errors and output — Credential shapes are hidden in a test's error text, in the hook errors a run stores and in errors stored before ingest hid them, and named values and Piwi's own keys are hidden in test output.
  • 📦 Batches and shards — A batch sent again counts its failures once, a batch of more than 690 executions or a case PostgreSQL would refuse is stored, a shard joins only a run of its own shard count, a lost or repeated /finish settles the run once, and a sharded run settles to the worst status its shards reported.
  • 📊 Counts over passed and failed runs — Run, test and analytics rates, flaky rates and the editors' pass rates divide by the runs that passed or failed; skipped tests stay out of durations and timeout opportunities, and a test's page counts as its catalog row does.
  • ⏹️ Interrupted tests — Interrupted tests stay out of failure clusters, an interrupted or cancelled run stays out of project health, and an interrupted test is drawn in no outcome, with the gap it leaves named in run bars, the trend chart, the copied run summary and notifications.
  • 🧩 Failure clusters keep their history — Clusters keep their live failures, notes, assignees and triage through a merge, a fingerprint version bump carries merges and moved tests through, and more volatile text is masked.
  • 🔔 Notification delivery — cluster.new is announced once, also when runs overlap; a crashing outbox row, an SMTP server silent for 30 seconds and a digest row that cannot be drawn are given up alone; every queued delivery is checked against its subscription and recipient when sent.
  • 🗃️ Imports and stored files — Stored files stream and answer a Range request with 206, an import archive of 2 GiB or more is refused before it is uploaded, and a failed import removes the files it stored.
  • 🛠️ Reporter setup and coverage — A workspace package is wired with a Playwright config from the workspace root, piwi init keeps the API key out of a .env git tracks, the reporter's temp files are owner-only, and coverage.browser: 'lines' records browser lines.
  • ⚙️ Setup in settings — Setup, the MCP server and the API reference move into settings.

Features

Run errors and test output

  • reporter: keep run errors and test output, and harden ingest, numbers and clustering (c95053f)
  • reporter: keep the errors Playwright reports outside the tests, shown on the run page (9f7f588), closes #1016
  • reporter: keep what each test wrote to stdout and stderr, shown on its Output tab (030687e), closes #1016

Live runs

  • app, desktop: pause and watch a running test from its row on the run page (e98d6cc, c28bc6f)

Sign-in and hosts

  • app: harden sign-in, host and origin checks, request limits and the reporter's temp files (724720a)
  • app: allow more host names with authentication off through PIWI_ALLOWED_HOSTS (36b40ba)

Setup, coverage and settings

  • reporter: wire the workspace package with a Playwright config from the workspace root (79b78b9), closes #1015
  • reporter: record browser lines with coverage.browser: 'lines', and read source on an SSH host alias (d59155b, 97c8caa)
  • ui: move setup, the MCP server and the API reference into settings (#1037) (7311ab5)

Demo

  • demo: group the run simulator's scenarios, fit its menu on a phone and add two scenarios (34924f1, 36eceb4)

Bug Fixes

Ingest, batches and uploads

  • app: accept a batch case with an empty title (b5fb764), closes #1013
  • app: answer 400 naming the field for a malformed batch run or case (604e547), closes #1013
  • app: announce an uploaded run once its executions are stored (8622626), closes #1013
  • app: count a failure once when its batch is sent again (1801692), closes #1013
  • app: leave no run behind when a batch's executions cannot be stored (bb9e2bf), closes #1013
  • app: store a run case PostgreSQL would refuse without failing its batch (6e91e64), closes #1013
  • app: store a run batch of more than 690 executions (d6f3f66)
  • app: find a long-named test by the name its rows store (4710769), closes #1013
  • app: store a test's names whole until together they outgrow an index entry (9eb808b)
  • app: attach live case files to the execution of their Playwright project (2e8d092), closes #1013
  • reporter: name the Playwright project of a live case-files upload (d7a2c80), closes #1013
  • app: take a batch run's results ahead of its files (ec70d35), closes #1013
  • reporter: send a batch run's files in requests of their own (9174798), closes #1013
  • reporter: send a batch run's results again when their answer was lost (50792fc)
  • app: settle every attempt of a batch and complete a retry's history stored before an attempt (d45b282)
  • app: give a retry an older reporter sends without a history the one its attempts make (6019132)
  • db: fill in the attempt history of retries stored without one (b6838ca)
  • app: store a trace's attempt history so every page reads its flakiness alike (d730206)
  • app: take back a skipped batch's cluster counts without erasing another's (11233dd)
  • app: answer a repeated submit or upload of a run held for its files with a new token for its files (cb51dbc, ce8b507, de78ba5)
  • app: restart the finalizing wait when a repeated delivery renews a held run's token (c6af2b7)
  • reporter: send the files of a run its JSON submit or its one upload is answered as held for (63223aa, 72610e1)
  • app: cap a run's results sent as JSON at PIWI_SUBMIT_MAX_BYTES (7f73d0f)
  • app: take the results of a run uploaded in parts at any size (a736c2a)
  • app: close and remove an aborted upload's temp file (ccc79ca)
  • app: never run a multipart upload's check once the request failed (763df07)
  • reporter: skip the multipart upload when the run has no file to attach (bf72307), closes #1015
  • reporter: stage no attachment for a reporter that is not enabled (10099bb), closes #1015
  • reporter: stop a run's file uploads once the dashboard says it takes no more (b76e578), closes #1013 #1014
  • reporter: stream the report archive, and leave a report over the upload limit out of it and of a shard's one upload (0b92adb, 0ba8965), closes #1015
  • reporter: upload a report of any size and let the dashboard's limit decide (5dc8fdd)
  • reporter: upload only the HTML report the run's html reporter wrote (5846653), closes #1015
  • reporter: name report archive entries with forward slashes on Windows (a16b04e), closes #1015
  • reporter: count a run as delivered only when the dashboard's answer names it (936d972), closes #1015
  • reporter: decode the dashboard's answer whole so a split character survives (20b4f38), closes #1015
  • db: tell a unique violation from the other SQLite constraint failures (8d8a5a2)

Sharding, streaming and the run lifecycle

  • app: join a shard only to a run of its own shard count (3644d92), closes #1014
  • app: count a shard once when its /finish answer is lost (2be7203), closes #1014
  • reporter: ask /finish again when its answer was lost before falling back (e467a5c), closes #1014
  • reporter: keep part of submitTimeout for /finish so a streamed run is finished (6dc3ac8), closes #1014
  • reporter: end the trace check at the files deadline so /finish keeps its budget (9a13cf7)
  • app: settle a run once when its /finish is sent again (b9a9f40), closes #1014
  • app: settle a sharded run to the worst status its shards reported (04bd3ed), closes #1014
  • app: keep a run's suite setup steps from the batch routes and every shard of a sharded run (d4292de, 3c9d84d)
  • reporter: send the suite's setup steps with the batch run body too (558cc91)
  • app: let a run wait through a long global setup, and keep a run begun after one from being reaped (89a8dcd, b8a184c), closes #1014
  • app: leave a finalizing run to settle when another run of its instance starts (54348a5), closes #1014
  • app: refuse the events of a run another run of its instance cancelled (de72674), closes #1014
  • app: cancel the run in flight that a batch upload replaces, also when only the reporter's batch fallback names it (8a9e4d0, 4efc3e1)
  • reporter: stop streaming a run the dashboard ended and send it as a batch (7ee8217), closes #1014
  • reporter: hand each run its own registration from the global setup (42dc4d7), closes #1014
  • reporter: register no run in the global setup when streaming is off (9696695)
  • reporter: trust the global setup's run registration only when this user wrote it (672115a)
  • reporter: chain the global setup once in a config wrapped twice (36ea2f4), closes #1015
  • app: check a streaming run's token header, and refuse a run that does not exist or is not streaming, before reading its body (ee73734, 09d830e, 58a6622)
  • reporter: send a streaming run's token in a header beside the body (2926720)
  • reporter: set aside live events the dashboard keeps refusing for two and a half minutes, so later ones flow (2670e9a, 0f5c084), closes #1015
  • app: store a streamed result and its files when its test title is empty (4e63bba)
  • app: release an event stream whose client left before it opened (153542f)

Playwright fidelity

  • reporter, app: invert an expected failure by Playwright's expected status, in the reporter and in imports (db27363, dd05a72), closes #1016
  • reporter: count failed tests, not failed attempts, against maxFailures (0a649c5), closes #1016
  • reporter: read a failed test whose retry did not run as failed, as Playwright does (241a66e)
  • reporter: link a failed test whose retry the run never made (06e2f4c), closes #1016
  • reporter: link a cascade to the failure of its own attempt and project (27760da), closes #1016
  • reporter: name the failed dependency of a test whose project never ran (2f4e83c), closes #1016
  • reporter: send a skipped test the run never reached as skipped (afb8536), closes #1016
  • app: link a skipped test to the blocker of its own project (c5efc7f), closes #1016
  • app: name only a failed execution as a test's blocker (6e084d7), closes #1016
  • reporter: name a failure's source frames with POSIX separators (7411257), closes #1016
  • reporter: keep the error of a test that throws a value that is not an Error (18a9f85)
  • reporter: cut a run error's text once, its marker within the limit (2bcb39e)
  • reporter: keep a character whole when a test's output splits its bytes (eaa5273)
  • app: fail the gate on a test that failed in one Playwright project (70df390)
  • ui: re-run a test whose later --repeat-each repetition failed (3d59107)
  • reporter: tell a CI job as detectCi does before pausing or inspecting (0868917)

Counts, rates and health

  • app: rate a run, a test and analytics on the tests and runs that passed or failed (882ef92, 118d37c, 1af79f2), closes #1017
  • app: divide a test's flaky rate by its runs that passed or failed (24b49e5)
  • ide: count a test's pass rate over the runs that passed or failed, and give none to a test with no such run (0921141, 66e6da0)
  • app: count a test's runs as one result per run, project and repetition (c4a4d78), closes #1017
  • app: count a test's failures on its page as its catalog row does (640802f), closes #1017
  • app: count a test's timed-out executions as failed on its page (19383bf), closes #1017
  • app: count a test's recent passes on retry in its details (357e75c)
  • app: count a catalog test over the period the catalog shows (8d657b9), closes #1017
  • app: read a project's health from its finished runs only (d15d4f7), closes #1017
  • app: leave skipped tests out of the slowest tests' durations (4c47f96), closes #1017
  • app: leave skipped tests out of the timeout opportunities (f025be4), closes #1017
  • app: list a project page's runs within its filters on the server (c06bfaf), closes #1017
  • ui: apply home's environment filter to failing now and the pass rate (1c6951e), closes #1017
  • ui: count every run of the last 24 hours in home's runs today (ac249ef), closes #1017
  • ui: count runs, not attempts, in the execution page's failing streak (fe054e7), closes #1017

Interrupted tests

  • app: leave interrupted tests out of failure clusters (deaced4)
  • app: pass over an interrupted or cancelled run in a project's health (dcfc946)
  • app: count a whole-suite run stopped early as not seen only when it ran the tests (830e625)
  • ui: draw an interrupted test in no outcome, and name the gap it leaves in run bars, the trend chart and the sidebar badge (a3505a7, 114638a), closes #1017 #1013 #1020
  • notifications: name a run's interrupted tests in its outcome bar (2e89799), closes #1017 #1013 #1020
  • ui: name interrupted tests in the copied run summary (9c32d6e)
  • ui: edge an interrupted run in its slate on Home's recent activity (8e4ff0c)
  • notifications: send run.failed for a run stopped by the global timeout (4bf7389), closes #1017

Failure clusters and triage

  • app: mask more volatile text and tell generic failures apart by file (21cc81a), closes #1018
  • app: carry merges and moved tests through a fingerprint version bump (ec18b80), closes #1018
  • app: keep a moved test's routes on its own file at a fingerprint upgrade (ae013bd)
  • db: keep the sample each failure-cluster alias was fingerprinted from (6d7b835), closes #1018
  • ai: embed failure clusters again after the fingerprint's new masks, the resolved clusters Fixed compares against included (3631e7b, 1705428)
  • app: recompute both clusters' first and last seen runs when tests move (5b5e0cc)
  • app: keep a live failure open, and its history, when clusters merge (2a3589f), closes #1018
  • app: keep a note or an assignee written to a cluster while it merges (adbd191)
  • app: keep a triaged cluster's time when its occurrences are recounted (25274f1), closes #1018
  • app: keep a person's triage when Piwi resolves or reopens a cluster (028f578)
  • app: reopen a cluster resolved by hand when it fails again (c3ad64c), closes #1018
  • app: give an incident's cluster its own inbox row once it fails again (e4f5bd6)
  • app: count a cluster's occurrences from runs that can make it recur (51e6406)
  • app: count only the runs that ran a cluster's tests without its failure (8cbf24a)
  • app: count only the runs that could show a failure on its state line (0d9aba8)
  • app: judge whether a failure goes on by the runs that could show it (5ca33e1)
  • app: flag new regressions against a complete run, per Playwright project (b44212d), closes #1018
  • app: append the applied triage line on the server (1b35ef2)
  • app: log an agent's cluster triage only on the clusters it changed (2614183)
  • app: send a cluster's status only when the person changed it (9090121)
  • app: answer 400 to a triage note that is not a string (70fdb65)
  • app: read each project's default branch in the failure inbox (bce551f)
  • app: match the Mine queue on name, username and email everywhere (1844638)
  • app: order fix verification by the runs' start times (ed0d466)

Quarantine

  • app: store a quarantine as proposed only for a current candidate (d0256a2)
  • app: bring a dismissed quarantine candidate back only after a run the candidates read (2069dfe)
  • app: quarantine a test two requests add at once without an error (08e75ed)
  • app: cap the reason of a cluster quarantine at 500 characters (fbd26e9)
  • app: count a quarantined test's failures once in the commit status (c02286a)
  • app: count as still failing only a quarantined test whose latest run failed it (5d0ca41)
  • app: count the release streak once per run, over runs that started after the quarantine (96e16ca)
  • app: read the release streaks of any number of quarantined tests (82676a8)
  • app: leave a dismissed release out of the inbox's quarantine ready and the quarantine debt's ready count (935c925, fdfec21)
  • app: withdraw a verified fix's release proposal once the test fails again (c65a9f3)
  • ui: mark a quarantined flaky test as quarantined instead of offering Quarantine, and say the button shows until it is (f72cb3c, 5bafb1a)
  • ui: quarantine every test of a cluster from its page, past the 50 it lists (4e64ff4)
  • ui: name the tests the inbox quarantined, not the cluster's tests (dd2d15a)
  • ui: say a one-test cluster's only test is quarantined (d81588c)

Imports, traces and stored files

  • app: import a blob report's errors outside its tests and each attempt's output (6b82e51)
  • app: count imported tests once and keep the attachments of pre-1.53 blob reports (f0811f0)
  • app: count an imported blob report's results as its stored rows are (e960046)
  • app: keep an imported trace passed when its test caught an action's error (0ac8622), closes #1021
  • app: fail an import that cannot store its files instead of reporting it imported (b8843fa), closes #1021
  • app: remove the files a failed import stored when its run is discarded (58f14cf), closes #1021
  • app: refuse an import archive of 2 GiB or more before it is uploaded (5eebb81), closes #1021
  • app: fail a trace request whose manifest cannot be read instead of caching it incomplete (3689a3b), closes #1021
  • app: place a trace's console entries on the wall clock through its own anchor (bbeda3b), closes #1021
  • app: stream stored files and answer a Range request with 206 (9fe6e5e), closes #1021
  • app: serve a stored name holding two dots, refusing only a .. segment (efa79f1), closes #1021
  • reporter: store an attachment named with its extension under that name once (da63951), closes #1021
  • app: report the keys S3 refuses to delete instead of taking the folder as gone (e80a0b0), closes #1021
  • app: page a retention purge through its runs instead of loading every execution (b55b87d), closes #1021
  • app: delete a project's bug-report screenshots with the project (ff0356a), closes #1021

Screenshots and the failure page

  • app: compare a step screenshot with the same step in the visual diff (7b36e89, 3003ac5)
  • app: don't mark a passing test's filmstrip step as failed (1489e80, bf7a231)
  • app: don't show a passing test's only screenshot or its trace screenshots as "At the failure" (0b81355, 63820f0, 731f7b8), closes #1027
  • mcp: don't flag a passing execution's only screenshot as atFailure (8a42b96, 8361790), closes #1028
  • app: detect the capture fixtures by the page state they record (762ff04), closes #1020

Sign-in, hosts and request limits

  • app: answer only local hosts and the site URL when authentication is off (338b23d)
  • app: answer a name with no dot only when PIWI_ALLOWED_HOSTS lists it (b171f5a)
  • app: judge a write by its origin only while authentication is off (983eb7c)
  • app: judge a write without sec-fetch-site by its origin header (082223e)
  • app: compare an origin's host alone with the host header in the write guard (1517b4e)
  • app: let only named hosts, not the wildcard, vouch for a write's origin (6568cc9)
  • app: classify every private IPv6 form in the outbound URL guard (74aef9c)
  • ai: read a provider address without a scheme as leaving the network, and a private one with the one private-host rule (c359d78, 6e33df7)
  • auth: authenticate before reading the body of the link and issue routes (d92986d)
  • auth: cap every body read before a credential, and the body of the routes open to anyone, at 64 KiB (56fb7ed, 5250656)
  • auth: cap usernames at 200 characters at sign-in and account creation (4838547)
  • auth: check a password only against a hash within the cost Piwi writes (885cac5)
  • auth: run at most two password hashes at once, and hold each client to a share of the queue (00ac1c4, 866a11c)
  • auth: keep wrong passwords from elsewhere from locking an account's owner out (ab0fdde)
  • auth: limit the password change's checks per account and address (23e920f)
  • auth: give a reset token back when its password could not be hashed (cb0d042)
  • auth: use up a password reset token before setting the password (0641b4a)
  • auth: let a setup claim succeed only while no administrator exists (df1ab3a)
  • auth: refuse to start with a PIWI_AUTH_SECRET under 32 characters (673bcfc)
  • auth: require a signed-in session to change credentials or create keys (e3f1751)
  • auth: check a route's permission on the path its router dispatches (0b44d6c)
  • app: close a share link once its creator can no longer read it (12efe44)
  • app: keep no share link token in the records of a filed issue (6aed5ad)
  • app: sweep ended windows out of the rate-limit store, and remove a key once every slot it held is given back (24a6c0c, 317bdc7)
  • app: read every numeric route param as a plain positive integer (85e5ab1)
  • app: refuse a route id above PostgreSQL's serial range with 400 (125001f)
  • app: read a saved dashboard's id as a route reads one (524e808)
  • app: answer 404 for the latest run of a project that does not exist (7ed56c9)
  • app: compile a selection's file globs once and cap their size (d8edc85)
  • app: hold an analytics scope's file globs to the selection limits (4347f62)
  • app: match globs exactly as the regular expressions they stand for (fd1e4e6)
  • app: match saved globs without backtracking regular expressions (f4a29cf)
  • app: match declared route templates without a backtracking regular expression (9273e8e)
  • reporter: match probe plan routes without a backtracking regular expression (3deb75a)
  • ui: escape every value in copied failure HTML and link only http URLs (1a04c41)

Secrets in errors and output

  • reporter: hide credential shapes in a test's error text (58911ad)
  • app: hide credentials in the hook errors a run stores (a249fe0)
  • app: hide credential shapes in the errors stored before ingest hid them (6e6156e)
  • reporter: hide named values, Piwi's own keys and colored keys in test output (d7e9d68)

Reporter setup and piwi init

  • reporter: find a workspace package's package manager at its workspace root (edc6869), closes #1015
  • reporter: record the reporter in package.json with init --no-install (549c7c2), closes #1015
  • reporter: finish the env step of piwi init when the key is set in the environment (1393c6d)
  • reporter: recognize an exported PIWI_API_KEY in .env when piwi init records keys (eedb0e9)
  • reporter: keep piwi init from writing the API key into a .env git tracks, or one git cannot say it tracks (dad2b9c, c931a8d)
  • reporter: write no API key through a .env that is a link (9337700)
  • reporter: let PIWI_DASHBOARD_URL override the server URL init writes (9cb1a7b)
  • reporter: leave the reporter off for a serverUrl that is not an http(s) URL (045ea8e), closes #1015
  • reporter: keep the default of a number variable that holds no number (c7a9135), closes #1015
  • reporter: take only Piwi's own reporter entry for Piwi's (0f6465d), closes #1015
  • reporter: forward Playwright's config metadata once, git diff included (c2b8d15), closes #1015
  • reporter: report the run when its unrun tests or resources cannot be read (3e31059), closes #1015
  • reporter: keep the reporter's temp files owner-only and refuse planted ones (380b0f5)
  • reporter: keep the private temp files in a per-user folder on Windows (c0e72a7)
  • reporter: check a temp file's path before appending to it, on every platform (15a53ad)
  • reporter: check the crash-recovery file as the other temp files are checked (f697171)
  • reporter: print the dashboard's own reason for a 403, from piwi bug too, instead of the API key advice (179d200, c4829bb)
  • reporter: print the gate's run link on the dashboard URL it called (d7766ae)

Notifications

  • notifications: announce a cluster from the first run that sends notifications (a948bd4), closes #1018
  • notifications: announce a cluster once when two runs overlap (eb25a01)
  • notifications: announce as new only a cluster no one triaged or heard of (8772454)
  • notifications: claim a cluster's cluster.new in one stored write (325e9cf)
  • notifications: roll a cluster.new claim back when its read fails (23e6152)
  • notifications: release the cluster.new claims no run made at the upgrade (089e2da)
  • notifications: keep the startup claim release apart from the notifications (155fb6a)
  • notifications: send cluster.new once when the run it deferred to ends cancelled (b3d7a76)
  • notifications: measure perf.regression and looks-fixed against eligible runs only (8d8073a), closes #1018
  • app: send fix and regression events only for runs that notify (43fe536)
  • notifications: count an outbox attempt when it is claimed, so a crashing row is given up (d4ac68b), closes #1019
  • notifications: fail only the digest row that cannot be drawn, not its whole batch (2de369a), closes #1019
  • notifications: give up on an SMTP server that does not answer in 30 seconds (bab6c98), closes #1019
  • notifications: report a delivery that failed to queue instead of taking it for a duplicate (c86fb38), closes #1019
  • notifications: send a run's notifications without an enrichment that fails to load (d4ca34c), closes #1019
  • notifications: refuse a digest time that is no time of day and cap subscription filters (54f8367), closes #1019
  • notifications: cache compiled name patterns and cap a subscription's total (c57e4dd)
  • notifications: match branch and environment patterns in linear time (dfec675)
  • notifications: check a personal channel's owner before queuing and sending (1b16fdb)
  • notifications: check every queued delivery against its subscription and recipient when sent (f613afb)
  • notifications: drop a queued delivery its recipient can no longer read (13c431a)

Source control, pull requests and AI

  • app: read source-control diffs correctly for the diagnosis evidence and MCP (d3249e5, e31efc0)
  • app: keep partial SCM answers out of the cache and flag every cut in the evidence (4d53b02)
  • app: read source on an SSH host alias and from a clone on any host (4d2b42f)
  • app: match PR feedback posts of a pull request whatever form the repository was stored in (fe37ce5, d5866bc)
  • app: name the flakiness score in a pull request comment's flaky mark (5f08305)
  • app: give the pr-comment scene's flake on main a flakiness score (e890e14)
  • app: name the real fix for a host Piwi reads no provider for (ef62f31)

Desktop app

  • app: allow Tauri's IPC in the desktop CSP, parse zod without eval (its jitless mode in the browser), and link every local run (d0c028c, 9b26e5c, f2d4921)
  • app: spawn a desktop local run once its Piwi run baseline is known (be33608)
  • app: offer pause and watch on every run of a desktop entry, and keep it through a refused pause (ea2b8b1)
  • ui: show share links only where enabled and never in the desktop app (0dc92e3)

Other

  • app: run the tests CI skipped and fix the bugs their tests locked in (4ee16ee)
  • reporter: keep every function's code on a line and the cap for functions (a01e243)
Dashboard UI fixes — toasts, sorting, filters, live streams and the inbox
  • ui: answer N/A for a relative time of an invalid date (5868f69), closes #1020
  • ui: change a cluster's status without resending its note (8a210d9)
  • ui: clear the inbox's "snoozed, back" badge once it has been seen (8f29693)
  • ui: compare two runs in the order they started (7606815), closes #1020
  • ui: copy a run's duration in human units in its summary (be805f2), closes #1020
  • ui: count only this queue's selection in the inbox's bulk bar (86371de)
  • ui: drop a stale answer in the Changes tab and the roles modal (b004e39), closes #1020
  • ui: keep a project's filter cookie only while its filters are set (650b081), closes #1020
  • ui: keep the failure headlines of a live run after its stream connects (2759844)
  • ui: keep the inbox's keyboard on the cluster it highlights (616f24a)
  • ui: match a live test's rows on its project, not its browser JSON (8dda555), closes #1020
  • ui: offer "Assign to me" only to a signed-in user (96eb0de)
  • ui: offer to merge or dismiss a suggestion only to who may decide it (f0942c7)
  • ui: refresh the Failures tab's lists on run events, as its counts (12d4ad7), closes #1020
  • ui: reopen the shared live streams after an error answer (87c70ef), closes #1020
  • ui: say nothing in the history strip about an execution it does not show (497921c)
  • ui: show the execution facts line's link to the failing frame (81c5411), closes #1020
  • ui: show the server's reason in the account settings' and the remaining error toasts (e7da548, 4c43d88), closes #1020
  • ui: sort every run of a project's runs table, not the page on screen (36aad53), closes #1020
  • ui: sort the projects list by its latest run's date, duration and status (d83dc89)
  • ui: stop the run page's report reads and frame when it is left (7adb73b), closes #1020
Demo parity fixes — bringing the in-browser demo and its run simulator up to the real server's behavior
  • demo: address the review of the simulator's runs and finish (661fead)
  • demo: check issue entities and replay stored executions as the server does (15e5ea4)
  • demo: count a sharded run's results once, as the server does (5dfabda)
  • demo: draft and file a bug report's issue, store the notification channels added, and replay a streaming run's running tests to a page opened mid-run, as the server does (9fd3c4b, c5fd62c, 3b7bff2, cf346c6)
  • demo: end simulated in-flight tests interrupted and send the max-failures error (3adf03d)
  • demo: keep the fixme annotation off failing executions (4b3b051)
  • demo: leave out a streamed result whose fields have the wrong type (5e74be7)
  • demo: list the coverage gaps and hide the AI extract the demo cannot answer (49f5fb6)
  • demo: list the quarantine candidates in the demo (a68c040)
  • demo: name Playwright in the live demo's title (d540f33)
  • demo: seed no occurrence for the cluster an editor run created (230257e)
  • demo: send no run-finished in the catch-up of a run still initializing (0ac2419)

Performance Improvements

  • app: bound the executions the alias sample backfill reads per cluster (2bdea41)
  • app: read a quarantined test's release streak from the runs after its quarantine (977aa00)
  • app: read a row again in the recluster only when its fingerprint changed (5166a28), closes #1018
  • db: store whether each execution is its result's final attempt (0a33f4b)
  • app: read a test's runs from the stored final-attempt flag (32a6ed8)
  • reporter: link a serial cascade's skipped tests without re-reading every case (97dd94a)