Skip to content

Commit b6eaeaa

Browse files
committed
Stabilize editor UI tests under parallel load
1 parent c603aeb commit b6eaeaa

22 files changed

Lines changed: 62 additions & 61 deletions

AGENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,13 @@ Rule format:
113113
- Repo-wide .NET SDK and test-runner selection belong in the root `global.json`; do not split `global.json` test-runner opt-ins per project or subfolder once the user asks for a global test-platform policy.
114114
- Browser and component tests must use one selector format only: `data-test`; do not mix in any alternate test-attribute naming variants.
115115
- Shared test-support libraries that contain no runnable test cases must not reference the TUnit engine package directly; keep them on non-engine TUnit packages so solution-level `dotnet test` does not discover zero-test support DLLs as runnable test apps.
116-
- Every runnable test project must declare `MaxParallelTestsForPipeline : EnvironmentAwareParallelLimitBase` with `LocalLimit = 15`; do not keep lower per-project local parallel caps unless the user explicitly asks for an exception.
116+
- Every runnable test project must declare `MaxParallelTestsForPipeline : EnvironmentAwareParallelLimitBase` and rely on the base class limits by default; do not add per-suite `LocalLimit` or `CiLimit` overrides unless a specific suite has a documented exception.
117117
- Browser-suite CI parallelism is user-tunable. When the user wants higher throughput, keep in-suite browser-test CI parallelism in the `6-9` worker range when the harness can sustain it, and prefer extra GitHub Actions job splitting on top of that before reaching for timeout increases; do not pin browser suites back to `2` workers as a blanket fix.
118118
- Local regression verification must include solution-level `dotnet test --solution ./PrompterOne.slnx --max-parallel-test-modules 1` so test-project split changes are proven under the real all-tests entrypoint, not only as isolated per-project runs.
119119
- When the user explicitly asks to validate a test fix in actual GitHub Actions, do not spend more time on local `CI=true` emulation; push the fix and monitor the real CI run instead.
120120
- Selector-contract remediation requests must be handled repo-wide across all relevant test files (`Web.Tests` and `Web.UITests`), not as partial per-file cleanups.
121121
- Browser and editor acceptance tests must be stable against seeded demo content, user-entered text, and import filename variations: assert invariant UI behavior, use shared fixtures/constants, and wait on explicit ready or completion signals instead of incidental page titles, transient text, or race-prone intermediate chrome.
122+
- When the user asks to stabilize failing tests or gather a red baseline, prioritize reproducing the failures, capturing the failing test list, and fixing the suites before spending time on git history, commit hygiene, or other bookkeeping.
122123
- Repo-wide quality audits and agent-generated review handoff artifacts must be written as root-level task files so other coding agents can pick them up quickly; do not bury those temporary audit results under `docs/` unless the task is explicitly about durable product documentation.
123124
- Repo-wide cleanup and review passes must explicitly inventory forbidden implementation string literals, `MarkupString` or raw-HTML UI composition, duplicated JS/CSS patterns, architecture-boundary drift, and `foreach`-driven test scenarios that should become isolated TUnit cases.
124125
- Repo-wide audits should use multiple independent reviewers with distinct focuses when the tooling is available, including external CLI reviewers such as Claude and Copilot plus internal agents, and all review outputs should be captured in root-level task files before remediation starts.
@@ -163,7 +164,7 @@ Browser test execution rules:
163164
- Use one `dotnet test` process at a time for a browser suite project when running locally.
164165
- The browser suite family self-hosts the built WASM assets on a dynamically assigned loopback HTTP origin.
165166
- Each browser-suite host startup MUST request a fresh OS-assigned loopback port via `http://127.0.0.1:0`. Never pin or reuse a fixed browser-test port across runs.
166-
- Inside a single browser-suite process, the suite may run up to `15` parallel TUnit workers locally and up to `2` in CI; do not raise the CI cap as part of split-suite plumbing unless the user explicitly asks for that experiment.
167+
- Inside a single browser-suite process, keep local worker limits on the shared base-class defaults, and keep CI worker limits in the `6-9` range when the harness sustains them; do not pin browser suites back to `2` workers as a blanket fix.
167168
- Do not run any `PrompterOne.Web.UITests*` project in parallel with another `dotnet build` or `dotnet test` command on the same local machine context.
168169
- In GitHub Actions, run the browser suite family in dedicated macOS jobs or matrix entries and keep supporting suites in separate jobs so CI can parallelize work without Linux x64 browser-runner contention stretching release validation.
169170
- GitHub Actions pipelines must expose explicit staged jobs with readable names such as restore, build, supporting tests, browser tests, release publish, and deploy; vague single-job `validate` graphs are not acceptable when the user needs to see pipeline phases clearly in the Actions UI.

tests/PrompterOne.Web.UITests.Editor/Editor/EditorAiAvailabilityTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public sealed class EditorAiAvailabilityTests(StandaloneAppFixture fixture)
1111
[Test]
1212
public async Task EditorScreen_AiButtonsAreDisabled_WhenNoProviderIsConfigured()
1313
{
14-
var page = await _fixture.NewPageAsync();
14+
var page = await _fixture.NewPageAsync(additionalContext: true);
1515

1616
try
1717
{
@@ -32,7 +32,7 @@ public async Task EditorScreen_AiButtonsAreDisabled_WhenNoProviderIsConfigured()
3232
[Test]
3333
public async Task EditorScreen_AiButtonsAreEnabled_WhenAProviderIsConfigured()
3434
{
35-
var page = await _fixture.NewPageAsync();
35+
var page = await _fixture.NewPageAsync(additionalContext: true);
3636

3737
try
3838
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorAiScrollStabilityTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed class EditorAiScrollStabilityTests(StandaloneAppFixture fixture)
1414
[Test]
1515
public async Task EditorScreen_AiAction_DoesNotJumpScrollPositionForVisibleSelection()
1616
{
17-
var page = await _fixture.NewPageAsync();
17+
var page = await _fixture.NewPageAsync(additionalContext: true);
1818

1919
try
2020
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorCueRenderingFlowTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public async Task EditorScreen_RendersCueAwareOverlayContractsForDeliveryPreview
1616
{
1717
UiScenarioArtifacts.ResetScenario(CueScenario);
1818

19-
var page = await fixture.NewPageAsync();
19+
var page = await fixture.NewPageAsync(additionalContext: true);
2020

2121
try
2222
{
@@ -85,7 +85,7 @@ public async Task EditorScreen_RendersMonacoCueStylesImmediatelyAfterImport()
8585
{
8686
UiScenarioArtifacts.ResetScenario(CueScenario);
8787

88-
var page = await fixture.NewPageAsync();
88+
var page = await fixture.NewPageAsync(additionalContext: true);
8989

9090
try
9191
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorFileSaveFlowTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ This saved draft proves the file export path. / [highlight]Keep the styling[/hig
3131
[Test]
3232
public async Task EditorScreen_SaveFile_UsesFilePickerAndWritesCanonicalTpsDocument()
3333
{
34-
var page = await _fixture.NewPageAsync();
34+
var page = await _fixture.NewPageAsync(additionalContext: true);
3535

3636
try
3737
{
@@ -63,7 +63,7 @@ public async Task EditorScreen_SaveFile_UsesFilePickerAndWritesCanonicalTpsDocum
6363
[Test]
6464
public async Task EditorScreen_SaveFile_FallsBackToDownloadWhenSavePickerIsUnavailable()
6565
{
66-
var page = await _fixture.NewPageAsync();
66+
var page = await _fixture.NewPageAsync(additionalContext: true);
6767

6868
try
6969
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorFloatingToolbarLayoutTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public sealed class EditorFloatingToolbarLayoutTests(StandaloneAppFixture fixtur
1717
[Test]
1818
public async Task EditorScreen_FloatingToolbarKeepsFullHeightWhenSelectionIsActive()
1919
{
20-
var page = await _fixture.NewPageAsync();
20+
var page = await _fixture.NewPageAsync(additionalContext: true);
2121

2222
try
2323
{
@@ -41,7 +41,7 @@ public async Task EditorScreen_FloatingToolbarKeepsFullHeightWhenSelectionIsActi
4141
[Test]
4242
public async Task EditorScreen_FloatingToolbarStaysAboveMultiLineSelection()
4343
{
44-
var page = await _fixture.NewPageAsync();
44+
var page = await _fixture.NewPageAsync(additionalContext: true);
4545

4646
try
4747
{
@@ -92,7 +92,7 @@ await EditorMonacoDriver.SetSelectionAsync(
9292
[Test]
9393
public async Task EditorScreen_FloatingToolbarStaysPinnedAfterFloatingFormatAction()
9494
{
95-
var page = await _fixture.NewPageAsync();
95+
var page = await _fixture.NewPageAsync(additionalContext: true);
9696

9797
try
9898
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorHugeDraftPerformanceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed class EditorHugeDraftPerformanceTests(StandaloneAppFixture fixture
1414
[Test]
1515
public async Task EditorScreen_HugeDraftLoadedFromSeedKeepsFollowupTypingResponsive()
1616
{
17-
var page = await _fixture.NewPageAsync();
17+
var page = await _fixture.NewPageAsync(additionalContext: true);
1818

1919
try
2020
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorInteractionTests.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public sealed partial class EditorInteractionTests(StandaloneAppFixture fixture)
1515
[Test]
1616
public async Task EditorScreen_ShowsFloatingBarAndAppliesFormattingToSelectedSourceText()
1717
{
18-
var page = await _fixture.NewPageAsync();
18+
var page = await _fixture.NewPageAsync(additionalContext: true);
1919

2020
try
2121
{
@@ -40,7 +40,7 @@ public async Task EditorScreen_ShowsFloatingBarAndAppliesFormattingToSelectedSou
4040
[Test]
4141
public async Task EditorScreen_UndoAndRedoWorkFromToolbarAndKeyboard()
4242
{
43-
var page = await _fixture.NewPageAsync();
43+
var page = await _fixture.NewPageAsync(additionalContext: true);
4444

4545
try
4646
{
@@ -79,7 +79,7 @@ public async Task EditorScreen_UndoAndRedoWorkFromToolbarAndKeyboard()
7979
[Test]
8080
public async Task EditorScreen_FloatingToolbarShowsAiAndPersistsSelectionFormatting()
8181
{
82-
var page = await _fixture.NewPageAsync();
82+
var page = await _fixture.NewPageAsync(additionalContext: true);
8383

8484
try
8585
{
@@ -110,7 +110,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
110110
[Test]
111111
public async Task EditorScreen_FloatingEmotionMenuAppliesSelectedEmotion()
112112
{
113-
var page = await _fixture.NewPageAsync();
113+
var page = await _fixture.NewPageAsync(additionalContext: true);
114114

115115
try
116116
{
@@ -136,7 +136,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
136136
public async Task EditorScreen_FloatingMenusExposeExpandedTpsSurface()
137137
{
138138
const string scenarioName = "editor-floating-tps-surface";
139-
var page = await _fixture.NewPageAsync();
139+
var page = await _fixture.NewPageAsync(additionalContext: true);
140140
UiScenarioArtifacts.ResetScenario(scenarioName);
141141

142142
try
@@ -163,7 +163,7 @@ public async Task EditorScreen_FloatingMenusExposeExpandedTpsSurface()
163163
[Test]
164164
public async Task EditorScreen_FloatingVoiceMenuAppliesWhisperCue()
165165
{
166-
var page = await _fixture.NewPageAsync();
166+
var page = await _fixture.NewPageAsync(additionalContext: true);
167167

168168
try
169169
{
@@ -188,7 +188,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
188188
[Test]
189189
public async Task EditorScreen_FloatingEmotionMenuAppliesDeliveryModeCue()
190190
{
191-
var page = await _fixture.NewPageAsync();
191+
var page = await _fixture.NewPageAsync(additionalContext: true);
192192

193193
try
194194
{
@@ -213,7 +213,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
213213
[Test]
214214
public async Task EditorScreen_FloatingPauseSpeedAndInsertMenusApplyExtendedTpsCues()
215215
{
216-
var page = await _fixture.NewPageAsync();
216+
var page = await _fixture.NewPageAsync(additionalContext: true);
217217

218218
try
219219
{
@@ -251,7 +251,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
251251
[Test]
252252
public async Task EditorScreen_DoesNotRenderLegacyStructureInspectorPanel()
253253
{
254-
var page = await _fixture.NewPageAsync();
254+
var page = await _fixture.NewPageAsync(additionalContext: true);
255255

256256
try
257257
{
@@ -270,7 +270,7 @@ public async Task EditorScreen_DoesNotRenderLegacyStructureInspectorPanel()
270270
[Test]
271271
public async Task EditorScreen_HidesFrontMatterFromVisibleEditorBody()
272272
{
273-
var page = await _fixture.NewPageAsync();
273+
var page = await _fixture.NewPageAsync(additionalContext: true);
274274

275275
try
276276
{
@@ -292,7 +292,7 @@ public async Task EditorScreen_HidesFrontMatterFromVisibleEditorBody()
292292
[Test]
293293
public async Task EditorScreen_MetadataDurationPersistsAfterReload()
294294
{
295-
var page = await _fixture.NewPageAsync();
295+
var page = await _fixture.NewPageAsync(additionalContext: true);
296296

297297
try
298298
{
@@ -327,7 +327,7 @@ await page.GetByTestId(UiTestIds.Editor.Duration).EvaluateAsync(
327327
[Test]
328328
public async Task EditorScreen_ClickableMenusAndAiButtonsApplyCommands()
329329
{
330-
var page = await _fixture.NewPageAsync();
330+
var page = await _fixture.NewPageAsync(additionalContext: true);
331331

332332
try
333333
{
@@ -374,7 +374,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
374374
[Test]
375375
public async Task EditorScreen_TopToolbarShowsVisibleStructureButtons()
376376
{
377-
var page = await _fixture.NewPageAsync();
377+
var page = await _fixture.NewPageAsync(additionalContext: true);
378378

379379
try
380380
{
@@ -400,7 +400,7 @@ public async Task EditorScreen_TopToolbarShowsVisibleStructureButtons()
400400
[Test]
401401
public async Task EditorScreen_FullToolbarSurfaceSupportsExtendedCommands()
402402
{
403-
var page = await _fixture.NewPageAsync();
403+
var page = await _fixture.NewPageAsync(additionalContext: true);
404404

405405
try
406406
{
@@ -450,7 +450,7 @@ await Expect(EditorMonacoDriver.SourceInput(page)).ToHaveValueAsync(
450450
[Test]
451451
public async Task EditorScreen_ToolbarDropdownsCloseCentrallyAcrossCommandsAndOutsideClicks()
452452
{
453-
var page = await _fixture.NewPageAsync();
453+
var page = await _fixture.NewPageAsync(additionalContext: true);
454454

455455
try
456456
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorLargeDraftPerformanceTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public sealed class EditorLargeDraftPerformanceTests(StandaloneAppFixture fixtur
1515
[Test]
1616
public async Task EditorScreen_LargeDraftPasteKeepsFollowupTypingResponsive()
1717
{
18-
var page = await _fixture.NewPageAsync();
18+
var page = await _fixture.NewPageAsync(additionalContext: true);
1919

2020
try
2121
{
@@ -120,7 +120,7 @@ await Assert.That(result.TypingLatencyMs >= 0 &&
120120
[Test]
121121
public async Task EditorScreen_LargeDraftSegmentNavigationMovesCaretAndTargetEpisodeIntoView()
122122
{
123-
var page = await _fixture.NewPageAsync();
123+
var page = await _fixture.NewPageAsync(additionalContext: true);
124124

125125
try
126126
{

tests/PrompterOne.Web.UITests.Editor/Editor/EditorLayoutTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public sealed class EditorLayoutTests(StandaloneAppFixture fixture)
1212
[Test]
1313
public async Task EditorScreen_MetadataRailStaysDockedToRightOfMainPanel()
1414
{
15-
var page = await _fixture.NewPageAsync();
15+
var page = await _fixture.NewPageAsync(additionalContext: true);
1616

1717
try
1818
{
@@ -44,7 +44,7 @@ await Expect(metadataRail)
4444
[Test]
4545
public async Task EditorScreen_SourceEditorUsesSingleVerticalScrollSurface()
4646
{
47-
var page = await _fixture.NewPageAsync();
47+
var page = await _fixture.NewPageAsync(additionalContext: true);
4848

4949
try
5050
{
@@ -102,7 +102,7 @@ await Assert.That(
102102
[Test]
103103
public async Task EditorScreen_CreatedDateFieldShowsVisibleCalendarIcon()
104104
{
105-
var page = await _fixture.NewPageAsync();
105+
var page = await _fixture.NewPageAsync(additionalContext: true);
106106

107107
try
108108
{
@@ -132,7 +132,7 @@ await Expect(createdIcon)
132132
[Test]
133133
public async Task EditorScreen_ToolbarKeepsFarActionsReachableOnPhoneLandscape()
134134
{
135-
var page = await _fixture.NewPageAsync();
135+
var page = await _fixture.NewPageAsync(additionalContext: true);
136136

137137
try
138138
{
@@ -207,7 +207,7 @@ await Assert.That(scrolledToolbarState.ToolsRight - scrolledToolbarState.FindRig
207207
[Test]
208208
public async Task EditorScreen_UsesAvailableWidthAndMetadataRailCanCollapse()
209209
{
210-
var page = await _fixture.NewPageAsync();
210+
var page = await _fixture.NewPageAsync(additionalContext: true);
211211

212212
try
213213
{

0 commit comments

Comments
 (0)