|
| 1 | +# Stabilize Browser Suite Parallelism |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Make the browser acceptance suites deterministic under the higher in-suite parallelism the repo already allows, then prove the fix with full local baseline runs and the replacement GitHub Actions run on `main`. |
| 6 | + |
| 7 | +## Scope |
| 8 | + |
| 9 | +In scope: |
| 10 | +- `tests/PrompterOne.Web.UITests/Infrastructure/*` and `tests/PrompterOne.Web.UITests/Support/*` shared browser harness helpers |
| 11 | +- `tests/PrompterOne.Web.UITests.Shell/**/*` |
| 12 | +- `tests/PrompterOne.Web.UITests.Studio/**/*` |
| 13 | +- `tests/PrompterOne.Web.UITests.Reader/**/*` |
| 14 | +- `tests/PrompterOne.Web.UITests.Editor/**/*` where the shared-harness fix or route-wait fix changes expectations |
| 15 | +- Push to `main` and watch the replacement Actions run |
| 16 | + |
| 17 | +Out of scope: |
| 18 | +- Lowering CI parallelism back to `2` |
| 19 | +- Timeout-only “fixes” |
| 20 | +- Unrelated product behavior changes outside what is required for test determinism |
| 21 | + |
| 22 | +## Constraints And Risks |
| 23 | + |
| 24 | +- Keep one browser-suite `dotnet test` process at a time locally. |
| 25 | +- Do not revert the user’s requested higher CI concurrency posture. |
| 26 | +- Prefer harness isolation and stable route contracts over weaker assertions. |
| 27 | +- Shared-context tests that intentionally validate storage/session propagation must stay shared. |
| 28 | +- Preserve production-owned `data-test` hooks and route contracts. |
| 29 | + |
| 30 | +## Testing Methodology |
| 31 | + |
| 32 | +- Establish the failing baseline from the real browser suites and GitHub Actions logs first. |
| 33 | +- Fix one failure class at a time: shared `BrowserContext` teardown interference, then SPA route-wait flakiness. |
| 34 | +- Verify by layers: |
| 35 | + - targeted previously failing suites |
| 36 | + - all changed browser suites |
| 37 | + - full `dotnet test --solution ./PrompterOne.slnx --max-parallel-test-modules 1` |
| 38 | +- After local green, run `dotnet format`, push `main`, and monitor the new Actions run until green or a concrete external blocker remains. |
| 39 | + |
| 40 | +## Baseline And Failing Tests |
| 41 | + |
| 42 | +- [x] Baseline local browser-suite failures reproduced and correlated with the user-reported red tests. |
| 43 | +- [x] Previous failed GitHub Actions run inspected. |
| 44 | + Result: |
| 45 | + - Shell, Studio, and Reader had widespread first-screen visibility failures under parallel load. |
| 46 | + - Solution-level rerun exposed an additional SPA-route timing failure in `GoLiveFlowTests.SettingsPage_LinksIntoGoLiveRoutingAndGoLiveLinksBackToSettings`. |
| 47 | + |
| 48 | +Tracked failures: |
| 49 | +- [x] `EditorAiAvailabilityTests.EditorScreen_AiButtonsAreEnabled_WhenAProviderIsConfigured` |
| 50 | + Symptom: `editor-page` not found. |
| 51 | + Root-cause note: direct editor tests reused shared contexts and then closed them from sibling tests. |
| 52 | + Intended fix path: force isolated contexts for direct page-based editor tests. |
| 53 | +- [x] `EditorCueRenderingFlowTests.EditorScreen_RendersMonacoCueStylesImmediatelyAfterImport` |
| 54 | + Symptom: `editor-page` / `editor-source-stage` not found. |
| 55 | + Root-cause note: same shared-context teardown interference. |
| 56 | + Intended fix path: isolate direct editor tests. |
| 57 | +- [x] `EditorFindFlowTests.EditorScreen_FindBar_UsesStyledChrome` |
| 58 | + Symptom: `editor-source-stage` not found. |
| 59 | + Root-cause note: same shared-context teardown interference. |
| 60 | + Intended fix path: isolate direct editor tests. |
| 61 | +- [x] `LibraryScreen_OpenScriptImportsLocalFileAndNavigatesIntoEditor` |
| 62 | + Symptom: wrong imported title shown in header. |
| 63 | + Root-cause note: already fixed in prior import-title pass; kept under regression watch here. |
| 64 | + Intended fix path: no new action unless the broader stabilization regresses it. |
| 65 | +- [x] `LibraryScreen_OpenScriptCanImportASecondFile_AfterPickerResets` |
| 66 | + Symptom: wrong imported title shown in header. |
| 67 | + Root-cause note: already fixed in prior import-title pass; kept under regression watch here. |
| 68 | + Intended fix path: no new action unless the broader stabilization regresses it. |
| 69 | +- [x] `GoLiveFlowTests.SettingsPage_LinksIntoGoLiveRoutingAndGoLiveLinksBackToSettings` |
| 70 | + Symptom: route wait timed out on `**/settings` during SPA navigation. |
| 71 | + Root-cause note: `WaitForURLAsync` depended on navigation/load semantics that were race-prone for in-app route changes under suite load. |
| 72 | + Intended fix path: replace navigation-event waits with an assertion-based SPA route helper. |
| 73 | + |
| 74 | +## Ordered Plan |
| 75 | + |
| 76 | +- [x] Step 1. Inspect the shared browser harness and identify which tests intentionally share contexts versus accidentally reuse them. |
| 77 | + Verification: |
| 78 | + - Confirmed `StandaloneAppFixture.NewPageAsync()` defaults to shared contexts keyed by caller member name. |
| 79 | + - Confirmed many direct page-based tests in Editor, Shell, Studio, and Reader were not intended to share contexts. |
| 80 | + |
| 81 | +- [x] Step 2. Establish the red baseline locally and from CI logs. |
| 82 | + Verification: |
| 83 | + - Reproduced local editor and browser-suite failures. |
| 84 | + - Pulled CI job logs for the failed `main` run and mapped the failure pattern. |
| 85 | + |
| 86 | +- [x] Step 3. Isolate direct page-based tests that were closing shared contexts. |
| 87 | + Actions: |
| 88 | + - Converted direct `NewPageAsync()` callers in the affected suites to `NewPageAsync(additionalContext: true)`. |
| 89 | + - Preserved the intentionally shared tests in `DynamicHostPortTests` and the existing `NewSharedPagesAsync(...)` cases. |
| 90 | + Verification: |
| 91 | + - `PrompterOne.Web.UITests.Editor` passed under `--maximum-parallel-tests 8`. |
| 92 | + - Shell, Studio, and Reader targeted reruns cleared the widespread first-screen visibility failures. |
| 93 | + |
| 94 | +- [x] Step 4. Replace brittle SPA route waits with a deterministic helper. |
| 95 | + Actions: |
| 96 | + - Added `tests/PrompterOne.Web.UITests/Support/BrowserRouteDriver.cs`. |
| 97 | + - Swapped `WaitForURLAsync(BrowserTestConstants.Routes.Pattern(...))` for `BrowserRouteDriver.WaitForRouteAsync(...)` across the affected browser suites, leaving the one variable-pattern onboarding wait unchanged. |
| 98 | + Verification: |
| 99 | + - The previously failing `GoLiveFlowTests.SettingsPage_LinksIntoGoLiveRoutingAndGoLiveLinksBackToSettings` now passes. |
| 100 | + - Updated Shell, Studio, Reader, and Editor suites build and run successfully. |
| 101 | + |
| 102 | +- [x] Step 5. Run changed-suite verification. |
| 103 | + Verification: |
| 104 | + - `dotnet build ./PrompterOne.slnx -warnaserror` passed. |
| 105 | + - `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Studio/PrompterOne.Web.UITests.Studio.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` passed. |
| 106 | + - `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Shell/PrompterOne.Web.UITests.Shell.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` passed. |
| 107 | + - `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Reader/PrompterOne.Web.UITests.Reader.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` passed. |
| 108 | + - `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Editor/PrompterOne.Web.UITests.Editor.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` passed. |
| 109 | + |
| 110 | +- [x] Step 6. Run the required full-solution baseline. |
| 111 | + Command: |
| 112 | + - `dotnet test @./tests/dotnet-test-progress.rsp --solution ./PrompterOne.slnx --max-parallel-test-modules 1` |
| 113 | + Verification: |
| 114 | + - Full solution passes after the shared-harness and route-wait fixes. |
| 115 | + - Repeated after `dotnet format` and a fresh `dotnet build ./PrompterOne.slnx -warnaserror`; both full-solution reruns finished green at `1152/1152`. |
| 116 | + |
| 117 | +- [ ] Step 7. Run formatting and publish the fix. |
| 118 | + Actions: |
| 119 | + - Run `dotnet format ./PrompterOne.slnx`. |
| 120 | + - Stage only task-relevant files. |
| 121 | + - Commit on `main`. |
| 122 | + - Push `main`. |
| 123 | + Verification: |
| 124 | + - Local tree is clean except for expected plan artifacts. |
| 125 | + |
| 126 | +- [ ] Step 8. Monitor the replacement GitHub Actions run. |
| 127 | + Verification: |
| 128 | + - The new `main` run finishes green or any remaining blocker is documented with the specific failing job/test. |
| 129 | + |
| 130 | +## Final Validation Skills And Commands |
| 131 | + |
| 132 | +- `dotnet` |
| 133 | + Reason: repo-standard build and test validation for the changed .NET/browser code. |
| 134 | +- `github:gh-fix-ci` |
| 135 | + Reason: inspect and monitor the replacement GitHub Actions run on `main`. |
| 136 | +- `dotnet build ./PrompterOne.slnx -warnaserror` |
| 137 | + Reason: required repository build gate. |
| 138 | +- `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Studio/PrompterOne.Web.UITests.Studio.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` |
| 139 | + Reason: directly verifies the SPA route-wait fix in the suite that exposed it. |
| 140 | +- `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Shell/PrompterOne.Web.UITests.Shell.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` |
| 141 | + Reason: confirms the broader shell/shared-context fixes stay green. |
| 142 | +- `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Reader/PrompterOne.Web.UITests.Reader.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` |
| 143 | + Reason: confirms the reader suite remains stable after shared-harness changes. |
| 144 | +- `dotnet test @./tests/dotnet-test-progress.rsp --project ./tests/PrompterOne.Web.UITests.Editor/PrompterOne.Web.UITests.Editor.csproj --maximum-parallel-tests 8 --maximum-failed-tests 20` |
| 145 | + Reason: confirms editor stability after the context-isolation fix. |
| 146 | +- `dotnet test @./tests/dotnet-test-progress.rsp --solution ./PrompterOne.slnx --max-parallel-test-modules 1` |
| 147 | + Reason: required full-solution regression gate from root instructions. |
| 148 | +- `dotnet format ./PrompterOne.slnx` |
| 149 | + Reason: required repository formatting gate before finalizing the change. |
0 commit comments