Skip to content

feat(frontend): add the knowledge base and file copies to the migration page - #15622

Merged
ogabrielluiz merged 3 commits into
feat/migration-page-copy-databasefrom
feat/migration-page-copy-stores
Oct 11, 2026
Merged

ogabrielluiz merged 3 commits into
feat/migration-page-copy-databasefrom
feat/migration-page-copy-stores

Conversation

@ogabrielluiz

@ogabrielluiz ogabrielluiz commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on the PR below it, which adds the database copy and the panel this one reuses. Settings > Migration gets its seventh and eighth steps, "Copy knowledge bases" and "Copy files". It needs the two copies and their test runs from the API PRs further down the stack.

What it adds

Both steps can be tried first. "Test run" asks the server what a copy would do and copies nothing, and a test run never completes its step. A step whose copy is done offers no test run, because a test run would take the copy's place in the record. While a start is on its way both buttons are disabled. After a test run or a copy the step shows three counts: copied (or to copy), already copied, and not copied. The counts stand in the same live region as the progress line, so a screen reader hears what a copy or a test run found.

Each knowledge base or file that was not copied is listed by name and owner, with the page's line for its code and the command's own words under Details. The record keeps the first hundred of them, and the step says so when more failed. When one of them is what stops the step, the step's own line points at the list.

Progress follows the commands: the entries of the knowledge base being copied, and the files with how much of them was copied so far.

On an instance that already runs on PostgreSQL, the knowledge base copy changes this instance's own rows. The step says so before the copy starts.

A step whose copy is done shows how many were copied, out of how many, in its row.

A copy the server no longer counts shows none of what it found, and the step says the copy has to be made again. That is a copy made before changes were last turned back on, or a knowledge base copy made before the database was copied again.

The two steps after the copies are not built yet. Once the copies are done the server holds them back, and their rows read "Coming soon".

Try it

Finish the first six steps as in the PRs below, on an instance that has a knowledge base and an uploaded file. The destination database needs the vector extension (CREATE EXTENSION vector;). Click "Test run" on "Copy knowledge bases", read the counts, then copy. Do the same for the files.

To see the list of what was not copied, delete an uploaded file from the instance's disk before the first step. The check reports it, and you accept that finding there. The file copy then lists the file with its reason.

How it was tested

Jest has 16 new tests. They cover the test run and what it sends, the counts of a test run and of a copy, each line of the list for knowledge bases and for files, a list longer than the record keeps, two chat messages that miss the same file, a copy that is out of date, a run that ended without a report, the note for PostgreSQL, the done rows, the row of a step the server holds back, one start at a time, the counts read out where the progress was, and no test run on a done step. Jest sends no request. I planted 41 one-line defects in this PR's code, one at a time, and a Jest test fails for each. The whole Jest suite of the frontend passes with this PR.

tests/core/features/migration-copy.spec.ts gains a walk through both steps in a browser, against a real backend, a real PostgreSQL database with pgvector and a real S3 bucket: a test run and then the copy, for each step, and the focus moving to the files once the knowledge bases are done. On an instance with no knowledge base on its server the walk checks the "Not needed" line for that step. It skips unless MIGRATION_E2E_DATABASE_URL and MIGRATION_E2E_S3_BUCKET are set, so it does not run in CI. A copy needs changes paused, which refuses every change to the instance, so the walk cannot share the CI backend with other specs.

I ran it on an instance with one knowledge base of 12 entries, made through the app's own services, and two uploaded files. Afterwards the destination's knowledge_base row said postgres and its vector table held 12 rows. This instance's own row still said sqlite, and the bucket held both files.

By hand against the real API, I copied the database and the knowledge bases, then copied the database again. The knowledge base step waited again, said its copy was out of date and showed no counts from it. With every copy made, the rows of "Start the new instance" and "Check the new instance" read "Coming soon".

npm run check:i18n passes with the 23 new strings in all 8 locales. Biome is clean on the touched files, and the type check shows no new error.

Summary by CodeRabbit

  • New Features
    • Added test runs for knowledge-base and file migrations, allowing users to preview a copy without transferring data.
    • Migration steps now show copy progress, copied/skipped/failed counts, and details for items that need attention. File-copy progress can also include data size.
    • Added clearer status messages for completed, unavailable, and not-yet-ready steps, plus guidance for partial or interrupted copies.
    • Added migration workflow messages in German, English, Spanish, French, Japanese, Korean, Portuguese, and Simplified Chinese.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: langflow-ai/langflow/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cad2ad06-472e-4764-a874-bc1ae36de221

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: langflow-ai/langflow/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6d5532b6-71c8-4b39-aa4e-14ad7c7cc596


📥 Commits

Reviewing files that changed from the base of the PR and between 06058d1 and e1df335.



📒 Files selected for processing (19)
  • .secrets.baseline
  • src/frontend/src/controllers/API/queries/migration/types.ts
  • src/frontend/src/controllers/API/queries/migration/use-migration.ts
  • src/frontend/src/locales/de.json
  • src/frontend/src/locales/en.json
  • src/frontend/src/locales/es.json
  • src/frontend/src/locales/fr.json
  • src/frontend/src/locales/ja.json
  • src/frontend/src/locales/ko.json
  • src/frontend/src/locales/pt.json
  • src/frontend/src/locales/zh-Hans.json
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/CopyStep.tsx
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/__tests__/catalog.test.ts
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/__tests__/page.test.tsx
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/__tests__/steps.test.tsx
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/catalog.ts
  • src/frontend/src/pages/SettingsPage/pages/MigrationPage/index.tsx
  • src/frontend/tests/core/features/migration-copy.spec.ts
  • src/frontend/tests/utils/migration-walk.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.




Walkthrough

The migration page adds test runs and report details for knowledge-base and file copies. The copy API contract carries dry-run state, status counts, failed-item details, and file byte progress. Localized messages and tests cover the updated workflow.

Changes

Migration copy workflow

Layer / File(s) Summary
Copy report and run contract
src/frontend/src/controllers/API/queries/migration/types.ts, src/frontend/src/controllers/API/queries/migration/use-migration.ts
The migration types add copy report counts, failed-item details, and optional file byte progress. The start mutation accepts a boolean and sends it as dry_run.
Copy controls, reports, and localization
src/frontend/src/pages/SettingsPage/pages/MigrationPage/catalog.ts, src/frontend/src/pages/SettingsPage/pages/MigrationPage/CopyStep.tsx, src/frontend/src/pages/SettingsPage/pages/MigrationPage/index.tsx, src/frontend/src/pages/SettingsPage/pages/MigrationPage/__tests__/*, src/frontend/src/locales/{de,en,es,fr,ja,ko,pt,zh-Hans}.json, .secrets.baseline
The catalog defines copy labels, status mappings, count aggregation, and byte formatting. The migration page adds test-run controls and displays progress, copy counts, and failed-item details. Tests and locale strings cover these updates. The secrets baseline updates recorded line numbers for locale scan results; finding fields remain unchanged.
End-to-end copy validation
src/frontend/tests/core/features/migration-copy.spec.ts, src/frontend/tests/utils/migration-walk.ts
The test helper starts a copy run and waits for its event stream. The integration test exercises knowledge-base and file test runs and copies.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  actor Admin
  participant CopyStep
  participant useStartCopyMutation
  participant MigrationRunsEndpoint
  Admin->>CopyStep: Select test run or regular copy
  CopyStep->>useStartCopyMutation: Start with true or false
  useStartCopyMutation->>MigrationRunsEndpoint: Send dry_run value
Loading

Merge Risk: ⚪ Minimal · up to e1df3

The knowledge-base and file copy steps appear mergeable after normal checks; no unresolved issue was identified that should hold this change.

🚥 Pre-merge checks | ✅ 8 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 10 files. (9 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (8 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Test Coverage For New Implementations Passed The pull request adds relevant frontend unit tests and an end-to-end test for the new knowledge-base and file-copy functionality. The tests cover test-run requests, copy requests, concurrency, progres…
Test Quality And Coverage Passed Tests cover the new knowledge-base and file-copy behavior with Jest and React Testing Library. They verify dry-run and real-copy requests, concurrent-start protection, progress/result announcements, c…
Test File Naming And Structure Passed All changed tests follow the required structure. Frontend unit tests are catalog.test.ts, page.test.tsx, and steps.test.tsx under src/frontend/src, and Jest's testMatch includes these paths.…
Excessive Mock Usage Warning Passed PASS: The pull request does not introduce excessive mock usage. The added component tests use API spies only to prevent real network calls, a pending fetch only to hold an event stream open, and a `…
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: adding knowledge base and file copy steps to the frontend migration page.


Full details: Docstring Coverage

Explanation

Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 10 files. (9 skipped: 9 unsupported.)




✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR



🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR



  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the enhancement New feature or request label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

✅ Test Coverage Advisor

No source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉

Advisory check only — never blocks merge.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 59%
59.63% (98105/164508) 74.14% (15320/20663) 54.87% (2438/4443)

Unit Test Results

Tests Skipped Failures Errors Time
7439 0 💤 0 ❌ 0 🔥 24m 16s ⏱️

@Cristhianzl Cristhianzl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Important (preferably this PR)

I1 — The file-copy progress line can show a literal {{bytes}} to the admin

copyProgress adds bytes to the interpolation values only when the event carries one, but settings.migration.files.progress always contains the {{bytes}} token. i18next's skipOnVariables defaults to true (I checked src/frontend/node_modules/i18next/dist/cjs/i18next.js:1695 and src/frontend/src/i18n.ts:62-64, which overrides only escapeValue), and on a missing value that branch keeps match[0] — the raw {{bytes}} — in the output. So a copy_files progress event in any phase other than checking or preparing_target that has no bytes renders "Files: 1 of 3. Copied so far: {{bytes}}." on the migration screen. The conditional spread is itself the evidence that the author expects bytes to be absent sometimes.

Either default it (bytes: formatFileSize(event.bytes ?? 0)) or pick a bytes-free key when the event has none. If the server in fact always sends bytes on a copying-phase file event, then make bytes required in CopyEvent and drop the condition, so the type carries the guarantee.

// src/frontend/src/pages/SettingsPage/pages/MigrationPage/catalog.ts:268-275
  return [
    `${COPIES[step].slug}.progress`,
    {
      done: count(event.done),
      total: count(event.total),
      ...(event.bytes !== undefined && { bytes: formatFileSize(event.bytes) }),
    },
  ];

I2 — A step blocked on a per-item code reads as "the step stopped with an error" when that item is not in the retained hundred

CopyStep.tsx:141-148 shows copy.attention ("Some were not copied. Each one below says why.") only when the blocking code appears among the items the record kept, and otherwise falls through to line(code), which resolves COPY_CODES[code] ?? "error.crashed". The per-item codes live in ITEM_CODES (catalog.ts:226-242), not in COPY_CODES (catalog.ts:206-220) — only bucket_error is in both. The report keeps the first hundred failures, so if 100+ files fail with no_source_bytes and the one file_conflict that blocks the step is number 120, items.some(...) is false and the admin reads settings.migration.error.crashed — "The step stopped with an error. Run it again. If it happens again, download the migration record." (en.json:763) — for a step that did not crash and that re-running will not fix. The same happens for any blocked step whose run row has no report.

The fix is one line: resolve the blocked code through ITEM_CODES before falling back, or show copy.attention whenever counted.failed > 0 and the code is a known item code.

// src/frontend/src/pages/SettingsPage/pages/MigrationPage/CopyStep.tsx:145-147
            {items.some((item) => item.code === code)
              ? t("settings.migration.copy.attention")
              : line(code)}

I3 — "Test run" stays clickable while the real copy's POST is in flight, and the spinner jumps to it

Both buttons share one mutation and derive their busy state from start.variables, so exactly one of them is ever busy. Button blocks activation only on the button that is itself busy (src/frontend/src/components/ui/button.tsx:132 — blockActivation = Boolean(disabled) || isBusy), so during the copy's POST the "Test run" button is fully live. Clicking it fires a second POST steps/<step>/runs with dry_run: true, flips start.variables to true, and moves the loading indicator off the copy button onto the test button while the copy request is still outstanding. Best case the server refuses it and the admin sees a refusal line under a copy that is actually starting; worst case two runs are started on a one-way migration surface.

Disable both while start.isPending (disabled={start.isPending} on each, keeping loading as the per-button indicator) so the UI cannot issue the second start at all.

I4 — The result of a test run is never announced

The only live region in the component is the progress paragraph inside the run.status === "running" branch (CopyStep.tsx:63), and it unmounts the moment the run ends. The result then mounts in a plain <p> (CopyStep.tsx:129-140) and the per-item list in a plain <ul>, neither of them live. For a real copy that is partly covered, because finishing the step moves focus to the next step's heading (index.tsx:410), and a blocked step gets the role="alert" block. But a test run changes no step state and never completes the step, so a screen-reader user who activates "Test run" is told the button is busy and then told nothing at all — the counts, which are the entire point of a test run, arrive silently.

Make the result region aria-live="polite" (it is the same region in both states, so a single wrapper with the live attribute covers progress and result), or move focus to it when a dry run ends.

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Oct 7, 2026
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.91%. Comparing base (eb5c4cd) to head (4cfc983).

Additional details and impacted files

Impacted file tree graph

@@                          Coverage Diff                          @@
##           feat/migration-page-copy-database   #15622      +/-   ##
=====================================================================
+ Coverage                              68.77%   69.91%   +1.14%     
=====================================================================
  Files                                   2772     2777       +5     
  Lines                                 299091   300584    +1493     
  Branches                               40299    41813    +1514     
=====================================================================
+ Hits                                  205700   210166    +4466     
+ Misses                                 90897    87924    -2973     
  Partials                                2494     2494              
Flag Coverage Δ
frontend 67.42% <100.00%> (+1.98%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...end/src/controllers/API/queries/migration/types.ts 100.00% <100.00%> (ø)
...controllers/API/queries/migration/use-migration.ts 93.44% <100.00%> (+2.70%) ⬆️
...ages/SettingsPage/pages/MigrationPage/CopyStep.tsx 91.47% <100.00%> (ø)
.../pages/SettingsPage/pages/MigrationPage/catalog.ts 98.91% <100.00%> (+4.59%) ⬆️
...c/pages/SettingsPage/pages/MigrationPage/index.tsx 85.91% <100.00%> (+1.53%) ⬆️

... and 287 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 9ca0557 to 53167b8 Compare October 7, 2026 14:57
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 7, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 53167b8 to 6d4d3f9 Compare October 7, 2026 22:46
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 7, 2026

@erichare erichare left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ogabrielluiz Approving with four small fixes pushed on top. Thank you for matching the frontend types so exactly to the commands' --json output: copyCounts sums exactly the status literals both reports emit, and the stale/test-run logic in CopyStep mirrors _copy_step case by case.

Fixes I pushed

  • 753713e has three CopyStep fixes, each with a jest test that fails without it:
    • No "Test run" on a done copy step (L219). admit() puts the dry run in the copy's slot of the record, and _copy_step returns current for any dry run. So a test run on a finished step reopened it, removed its "Copied X of Y" summary and locked the steps after it again. A backend probe showed ('done', None) before the test run and ('current', None) after it.
    • One start at a time (L208, L223). Both buttons now set disabled={start.isPending}, and loading still marks the busy one. Before, a click on the other button sent a second POST, which came back as run_active ("running elsewhere") while your own copy was still starting. This was Cristhianzl's I3.
    • The test run's result is read out (L65, L137). The progress line and the counts are now the same keyed role="status" node. React keeps that node when the run ends, so the counts land in a live region the screen reader already tracks. It stays in the tree while empty, using the same empty:-mt trick as CheckStep. This was Cristhianzl's I4.
  • b8918c3 rewords files.badName in all 8 locales. bad_name comes from Langflow's own name check (_failure_code), and the local backend applies that check too, so the old text was wrong to blame S3. Renaming the file in Langflow also can't fix it, because the rename changes only File.name and not the stored name the copy reads (v2/files.py). The new text says what is true: the stored name has a backslash or .. in it, and Langflow's file storage refuses that name.

#15623 and #15624 need a restack onto the new head.

Non-blocking

  • No decision in DECISIONS covers bad_name (migration_copies.py). A file whose stored name was refused therefore blocks "Copy files", and nothing on the page gets the admin past it. This belongs to the API PR, so I left the copy describing the cause without offering a remedy.

Nits

  • Cristhianzl's I1: the relocate-files command always sends bytes, so a literal {{bytes}} can't appear today. Making bytes required on the file event, or using formatFileSize(event.bytes ?? 0) (catalog.ts#L273), would put that guarantee in the types.
  • runCopy in the e2e walk reads run_id without checking started.ok() (migration-walk.ts#L112). A refused start shows up later as a vague UI timeout instead of failing at the refusal.

Verification

npx jest src/pages/SettingsPage/pages/MigrationPage   -> 4 suites, 90 passed (87 + 3 new)
new tests on the original CopyStep.tsx                 -> 3 failed (as expected)
npx @biomejs/biome check <touched files>               -> clean
npm run check:i18n                                     -> all 7 locales in parity
npx tsc --noEmit (filtered to MigrationPage/locales)   -> no errors

@ogabrielluiz

Copy link
Copy Markdown
Contributor Author

Hey @erichare, thanks for the fixes. Each was on the old head of its PR, so I put them in one line and pushed #15622 to #15633 again. Your commits are all there, still yours.

Two of them changed to sit on each other: 0d9f11fabd here and fbea1d32c9 in #15624.

Your status line from #15621 and the one from this PR are one node now. It shows the progress, and after the run the counts (or the database result for a screen reader). Your tests for both pass as you wrote them.

In #15624 the two gate tests asked for the only status, and with the counts line there are two. They now find the line by its text. Is that what you meant?

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 8, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 9, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from e1df335 to 2083249 Compare October 9, 2026 18:08
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 9, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 2083249 to 1a56945 Compare October 9, 2026 18:38
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 9, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 1a56945 to 67ff094 Compare October 9, 2026 18:46
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 9, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 67ff094 to 4cfc983 Compare October 9, 2026 19:22
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 9, 2026
@ogabrielluiz
ogabrielluiz force-pushed the feat/migration-page-copy-stores branch from 4cfc983 to d3e9609 Compare October 9, 2026 23:22
@github-actions github-actions Bot removed the enhancement New feature or request label Oct 9, 2026
ogabrielluiz and others added 3 commits October 11, 2026 09:56
…on page

"Copy knowledge bases" and "Copy files" use the panel of the database
copy. Both can be tried first: a test run says what a copy would do and
completes nothing. After a run the step shows what was copied, what was
there already and what was not.

Each knowledge base or file that was not copied is listed with the
page's line for its code and the command's own words under Details. The
record keeps the first hundred of them, and the step says so when there
are more.

On an instance that already runs on PostgreSQL the knowledge base copy
changes this instance's own rows, and the step says so before it starts.

A copy that is out of date shows none of what it found. The steps after
the copies are not built yet. Once the copies are done the server holds
them back, and their rows read "Coming soon".
The bad_name line blamed S3 and told the admin to rename the file in
Langflow. The code comes from Langflow's own storage rule, which the
local backend applies too, and a rename changes only the display name,
not the stored name the copy reads, so the advice could not help.
…out its result

- Offer no test run on a done copy step: the server puts the test run in
  the copy's place, so the step waited again and the later steps locked.
- Disable both start buttons while a start is on its way, so a second
  click no longer sends another start that is refused as running elsewhere.
- Keep one live region from a run's progress line to what it found, so a
  screen reader reads out a test run's counts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants