Skip to content

Commit 755459b

Browse files
csharpfritzCopilot
andcommitted
Merge upstream/dev into dev (M6+M7 squash merge sync)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2 parents c9c6f35 + 2ed384b commit 755459b

247 files changed

Lines changed: 10214 additions & 271 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ai-team/agents/colossus/history.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,18 @@ Chart: 8 smoke tests + 11 canvas tests + 19 enhanced visual tests (dimensions, C
1616

1717
Team update (2026-02-23): Milestone 6 Work Plan ratified 54 WIs across P0/P1/P2 tiers decided by Forge
1818
Team update (2026-02-23): UI overhaul requested Colossus assigned integration tests (UI-9) decided by Jeffrey T. Fritz
19+
20+
## Summary: Milestone 7 Integration Tests (2026-02-24)
21+
22+
Added 9 smoke tests and 9 interaction tests for M7 sample pages: GridView Selection/DisplayProperties, TreeView Selection/ExpandCollapse, Menu Selection, DetailsView Styles/Caption, FormView Events/Styles. Menu Selection test skips console error checks (JS interop). FormView tests use DOMContentLoaded (items bound in OnAfterRenderAsync). Build verified green.
23+
24+
## Learnings
25+
26+
- FormView sample pages bind Items in `OnAfterRenderAsync`, so tests must use `WaitUntilState.DOMContentLoaded` + explicit `WaitForSelectorAsync` instead of `NetworkIdle`.
27+
- Menu interaction tests should always skip console error checks — the Menu component's JS interop (`bwfc.Page.AddScriptElement`) produces expected console errors in headless Playwright.
28+
- GridView Selection pages render Select links as `<a>` elements inside `<tbody>` rows — use `tbody tr:first-child a` with `HasTextString = "Select"` to target them.
29+
- DetailsView Caption renders actual `<caption>` HTML elements that can be directly queried.
30+
- **Playwright `text=` locator gotcha:** `page.Locator("text=Label:")` matches the *innermost* element containing that text. When the markup is `<p><strong>Label:</strong> value</p>`, the locator returns the `<strong>`, not the parent `<p>` — so the value portion is excluded from `TextContentAsync()`. Fix: use `page.Locator("p").Filter(new() { HasTextString = "Label:" })` (or the appropriate parent tag) to match the container element that holds both the label and value.
31+
- For `<div>` containers with multiple `<strong>` labels (e.g., TreeView/Menu feedback panels), use `page.Locator("div").Filter(new() { HasTextString = "Target label:" }).Last` to match the specific container div.
32+
- When waiting for FormView to render its item template buttons, use a specific selector like `button:has-text('Edit')` instead of generic `button, input[type='submit']` — the latter matches sidebar/nav buttons that already exist, causing the wait to resolve prematurely before the FormView renders.
33+
- To avoid strict-mode violations when text appears in both rendered output AND code examples, target the specific rendered element (e.g., `page.Locator("td").Filter(new() { HasTextString = "Widget Catalog" }).First`) rather than using bare `text=` locators.

.ai-team/agents/cyclops/history.md

Lines changed: 23 additions & 0 deletions
Large diffs are not rendered by default.

.ai-team/agents/forge/history.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,24 @@ Chart on milestone4 branch substantially complete. Architecture sound: Component
6363

6464
Team update (2026-02-23): P2 features complete all 1,065 tests pass, 0 build errors decided by Squad
6565
Team update (2026-02-23): UI overhaul requested by Jeffrey T. Fritz scope document created decided by Jeffrey T. Fritz
66+
67+
### Summary: Milestone 7 Planning (2026-02-23)
68+
69+
Planned M7: "Control Depth & Navigation Overhaul" — 51 work items targeting ~138 gap closures. Key findings from post-M6 codebase audit:
70+
71+
- **GridView (~55% post-M6):** Has paging, sorting, editing from M6. Still missing selection (SelectedIndex/SelectedRow/SelectedRowStyle), 6 style sub-components, display props (ShowHeader/ShowFooter/Caption/GridLines/EmptyDataTemplate). Selection is the last major functional gap.
72+
- **Menu (~42%):** Only got Orientation in M6. Still missing ~35 props — base style props (needs BaseStyledComponent upgrade), selection tracking, MenuItemClick/MenuItemDataBound events, level styles. JS interop complicates base class change.
73+
- **TreeView (~60%):** Untouched in M6. Has solid core (nodes, data binding, checkboxes, expand/collapse, image sets). Missing node-level styles (TreeNodeStyle objects), functional selection, ExpandAll/CollapseAll, ExpandDepth, FindNode.
74+
- **FormView (~50%):** M6 added header/footer/empty. Still missing style sub-components, paging events (PageIndexChanging/Changed), ModeChanged/ItemCommand events, PagerSettings.
75+
- **DetailsView (~70%):** Has strong event coverage (10 CRUD/mode/paging events). Missing all 10 style sub-components, PagerSettings, Caption.
76+
- **ListView (~42%):** Barely touched. Has excellent templates but missing all 16 CRUD events, editing templates, selection, sorting. Deferred to P2 due to L size.
77+
- **DataGrid (~55%):** Has command events from original impl + style inheritance from M6. Missing style sub-components, paging/sorting events. Also P2.
78+
79+
**Key patterns confirmed:**
80+
- Style sub-components are the single biggest systematic remaining gap across all data controls
81+
- PagerSettings should be a shared type (GridView, FormView, DetailsView all need identical API)
82+
- Validator ControlToValidate string ID is a migration-blocking mismatch — ForwardRef doesn't match the "paste and it works" migration story
83+
- Diminishing returns are real: M6 closed ~345 gaps, M7 targets ~138 because remaining gaps require more work per gap (style sub-components, event pipelines vs. base class inheritance)
84+
- Re-audit must open the milestone — all planning-docs/ files are stale (pre-M6 numbers)
85+
86+
📌 Team update (2026-02-23): Milestone 7 planned — 51 WIs, ~138 gaps, "Control Depth & Navigation Overhaul". P0: GridView completion + re-audit. P1: TreeView, Menu, DetailsView, FormView, Validators. P2: ListView CRUD, DataGrid, Menu levels. — decided by Forge

.ai-team/agents/rogue/history.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,57 @@ Wrote 44 bUnit tests for P0 base class changes: AccessKey (4), ToolTip (8), Imag
3030

3131
📌 Test pattern: BaseListControl.GetItems() applies DataTextFormatString to both static and data-bound items. AppendDataBoundItems=false replaces static items. When Items is null, static items always show. — Rogue
3232

33+
📌 Test pattern: Menu Orientation tests require JSInterop.Mode = JSRuntimeMode.Loose and @using BlazorWebFormsComponents.Enums. Login control tests require AuthenticationStateProvider and NavigationManager mock services. — Rogue
34+
35+
36+
📌 Test pattern: Menu Orientation tests require JSInterop.Mode = JSRuntimeMode.Loose and @using BlazorWebFormsComponents.Enums. Login control tests require AuthenticationStateProvider and NavigationManager mock services. — Rogue
37+
38+
Team update (2026-02-23): BaseDataBoundComponent now inherits BaseStyledComponent removed duplicate IStyle from 11 data controls decided by Cyclops
39+
Team update (2026-02-23): BaseListControl<TItem> introduced as shared base for 5 list controls (DataTextFormatString, AppendDataBoundItems) decided by Cyclops
40+
Team update (2026-02-23): CausesValidation/ValidationGroup added to CheckBox, RadioButton, TextBox decided by Cyclops
41+
Team update (2026-02-23): Label AssociatedControlID switches rendered element (label vs span) decided by Cyclops
42+
Team update (2026-02-23): Milestone 6 Work Plan ratified 54 WIs across P0/P1/P2 tiers decided by Forge
43+
44+
### Milestone 7: GridView Feature Tests — WI-03 + WI-06 + WI-08
45+
46+
Wrote 24 bUnit tests across 3 new test files for GridView features:
47+
48+
**Selection.razor (WI-03, 7 tests):** SelectedIndex with SelectedRowStyle CSS, SelectedIndexChanging event with correct index, cancellation prevents selection, AutoGenerateSelectButton renders Select links, SelectedValue returns DataKeyNames key, SelectedIndex=-1 clears selection, SelectedRow returns correct data item. Used `FindComponent<GridView<T>>().Instance` to verify SelectedRow/SelectedValue properties.
49+
50+
**StyleSubComponents.razor (WI-06, 8 tests):** RowStyle applies to even-indexed data rows, AlternatingRowStyle applies to odd-indexed rows, HeaderStyle on thead tr, FooterStyle on tfoot tr, EmptyDataRowStyle on empty data, PagerStyle on pager row, EditRowStyle on row at EditIndex, style priority chain (Edit > Selected > Alternating > Row).
51+
52+
**DisplayProperties.razor (WI-08, 9 tests):** ShowHeader=false hides thead, ShowFooter=true shows tfoot, Caption renders caption element, CaptionAlign renders correct caption-side/text-align style, EmptyDataTemplate overrides EmptyDataText, GridLines renders rules attribute, UseAccessibleHeader renders th scope="col", CellPadding/CellSpacing render table attributes, ShowHeaderWhenEmpty shows header with no data.
53+
54+
📌 Test pattern: GridView style sub-components use named RenderFragments (`<RowStyleContent>`, etc.) containing `<GridViewRowStyle BackColor="color" />`. The sub-component configures the GridView's TableItemStyle via CascadingParameter "ParentGridView". Styles render as inline `style` attributes on `<tr>` elements. — Rogue
55+
56+
📌 Test pattern: GridView AlternatingRowStyle is always initialized (non-null `new TableItemStyle()`), so `GetRowStyle()` returns it for odd rows even when not configured. RowStyle only applies to even-indexed rows; to style ALL rows, set both RowStyle and AlternatingRowStyle. — Rogue
57+
58+
📌 Test pattern: GridView with `AutoGenerateColumns="false"` renders in two passes: first pass initializes style sub-components (empty table), second pass renders table after BoundField children register via `AddColumn`. bUnit waits for both renders. — Rogue
59+
60+
### Milestone 6: P2 Feature Tests — ListView CRUD, DataGrid Styles+Events, Menu Level Styles, Panel BackImageUrl, Login Orientation
61+
62+
Wrote 41 bUnit tests across 6 new test files for P2 features:
63+
64+
**CrudEvents.razor (ListView, 12 tests):** HandleCommand routes Edit→sets EditIndex+fires ItemEditing, Cancel→clears EditIndex+fires ItemCanceling, Delete→fires ItemDeleting+ItemDeleted, Insert→fires ItemInserting+ItemInserted, Update→fires ItemUpdating+ItemUpdated. Unknown command→fires ItemCommand. EditIndex=-1 shows ItemTemplate for all. EmptyItemTemplate renders when Items empty. InsertItemTemplate at FirstItem/LastItem positions. ItemEditing cancellation prevents EditIndex change. EditItemTemplate rendering verified via HandleCommand (EditIndex set confirmed; template re-evaluation is a known component gap).
65+
66+
**StyleSubComponents.razor (DataGrid, 11 tests):** DataGridItemStyle on data rows, AlternatingItemStyle on odd rows, HeaderStyle on thead, FooterStyle on tfoot, PagerStyle on pager row, SelectedItemStyle at SelectedIndex, EditItemStyle at EditItemIndex. Caption+CaptionAlign render correctly. GridLines→rules attribute. UseAccessibleHeader→th scope=col. CellPadding+CellSpacing on table.
67+
68+
**Events.razor (DataGrid, 3 tests):** PageIndexChanged fires when pager link clicked, SortCommand fires on sortable header click, SelectedIndex default is -1.
69+
70+
**LevelStyles.razor (Menu, 7 tests):** LevelMenuItemStyles applies per-depth CssClass, Level 1 items get index 0 style, Level 2 items get index 1 style, LevelSelectedStyles applies after click, LevelSubMenuStyles applies background-color to submenu ul, Level styles override static/dynamic styles.
71+
72+
**BackImageUrl.razor (Panel, 3 tests):** BackImageUrl renders as background-image in style, not set→no background-image, URL-encoded characters preserved.
73+
74+
**LoginOrientation.razor (Login, 5 tests):** Default Orientation is Vertical (fields in separate rows), Horizontal puts all fields in one row with 4 tds, TextOnLeft labels align right, TextOnTop labels above inputs with colspan, Horizontal+TextOnTop puts both labels in same row.
75+
76+
📌 Test pattern: ListView HandleCommand must be called via `cut.InvokeAsync()` because it calls StateHasChanged() which requires the Blazor Dispatcher context. Direct `await theListView.HandleCommand()` throws InvalidOperationException. — Rogue
77+
78+
📌 Test pattern: DataGrid style sub-components use named RenderFragments (`<ItemStyleContent>`, `<HeaderStyleContent>`, etc.) containing `<DataGridItemStyle BackColor="color" />`. WebColor values must be declared as variables (`WebColor red = "Red";`) then passed as `BackColor="red"` — not string literals. — Rogue
79+
80+
📌 Test pattern: Menu tests that use `FindAll("a")` must use `FindAll("li a")` to exclude the accessibility skip-link `<a>` rendered before the menu. JSInterop.Mode = JSRuntimeMode.Loose required for all Menu tests. — Rogue
81+
82+
📌 Test pattern: Login control tests require AuthenticationStateProvider + NavigationManager mock services. Use `Orientation ori = Orientation.Horizontal;` variable pattern to avoid Razor enum name collision. Login renders 4 layout combos based on Orientation × TextLayout (Vertical/Horizontal × TextOnLeft/TextOnTop). — Rogue
83+
3384
📌 Test pattern: Menu Orientation tests require JSInterop.Mode = JSRuntimeMode.Loose and @using BlazorWebFormsComponents.Enums. Login control tests require AuthenticationStateProvider and NavigationManager mock services. — Rogue
3485

3586
Team update (2026-02-23): BaseDataBoundComponent now inherits BaseStyledComponent removed duplicate IStyle from 11 data controls decided by Cyclops
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Decision: M7 Integration Tests Added (WI-39 + WI-40)
2+
3+
**Author:** Colossus
4+
**Date:** 2026-02-24
5+
**Status:** Done
6+
7+
## Context
8+
9+
Milestone 7 added 9 new sample pages across GridView, TreeView, Menu, DetailsView, and FormView. Each page needed smoke tests (page loads without errors) and, where applicable, interaction tests (behaviors work).
10+
11+
## What Was Added
12+
13+
### Smoke Tests (ControlSampleTests.cs)
14+
15+
Added `[InlineData]` entries to existing `[Theory]` methods:
16+
17+
- **DataControl_Loads_WithoutErrors:**
18+
- `/ControlSamples/GridView/Selection`
19+
- `/ControlSamples/GridView/DisplayProperties`
20+
- `/ControlSamples/FormView/Events`
21+
- `/ControlSamples/FormView/Styles`
22+
- `/ControlSamples/DetailsView/Styles`
23+
- `/ControlSamples/DetailsView/Caption`
24+
25+
- **NavigationControl_Loads_WithoutErrors:**
26+
- `/ControlSamples/TreeView/Selection`
27+
- `/ControlSamples/TreeView/ExpandCollapse`
28+
29+
- **MenuControl_Loads_AndRendersContent:**
30+
- `/ControlSamples/Menu/Selection`
31+
32+
### Interaction Tests (InteractiveComponentTests.cs)
33+
34+
Added 9 new `[Fact]` tests:
35+
36+
| Test | What It Verifies |
37+
|------|-----------------|
38+
| `GridView_Selection_ClickSelect_HighlightsRow` | Click Select link → selected index updates, count increments |
39+
| `GridView_DisplayProperties_RendersCaption` | Caption element, EmptyDataTemplate, ShowHeader/ShowFooter checkboxes |
40+
| `TreeView_Selection_ClickNode_ShowsSelected` | Click node → selection text and count update |
41+
| `TreeView_ExpandCollapse_ButtonsWork` | Expand All / Collapse All buttons, leaf node visibility, NodeIndent slider |
42+
| `Menu_Selection_ClickItem_ShowsFeedback` | Click menu item → click count increments (no console error checks — JS interop) |
43+
| `DetailsView_Styles_RendersStyledTable` | Table renders, "Customer Details" header visible |
44+
| `DetailsView_Caption_RendersCaptionElement` | `<caption>` elements present, "Customer Record" text |
45+
| `FormView_Events_ClickEdit_LogsEvent` | Click Edit → event log entries appear |
46+
| `FormView_Styles_RendersStyledHeader` | "Widget Catalog" header text visible |
47+
48+
## Patterns Used
49+
50+
- Menu Selection test skips console error checks (JS interop produces expected errors)
51+
- FormView tests use `WaitUntilState.DOMContentLoaded` (items bound in `OnAfterRenderAsync`)
52+
- All other tests use `WaitUntilState.NetworkIdle` with 30s timeout
53+
- Console error filtering: ISO 8601 timestamps + "Failed to load resource"
54+
55+
## Build Verification
56+
57+
`dotnet build samples/AfterBlazorServerSide.Tests/ -c Release` — succeeded with no errors.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Decision: Avoid bare `text=` locators in Playwright integration tests
2+
3+
**Author:** Colossus
4+
**Date:** 2025-07-24
5+
**Status:** Proposed
6+
7+
## Context
8+
9+
Five integration tests failed in CI (PR #343) because `page.Locator("text=Label:")` matches the *innermost* element containing the text. When markup uses `<p><strong>Label:</strong> value</p>`, the locator returns the `<strong>`, excluding the sibling value text from `TextContentAsync()`. Additionally, bare `text=` locators cause strict-mode violations when the same text appears in both rendered output and code examples.
10+
11+
## Decision
12+
13+
All Playwright integration tests MUST use container-targeted locators instead of bare `text=` selectors when reading text content that includes a label and a value:
14+
15+
```csharp
16+
// ❌ BAD — matches <strong>, returns only label text
17+
var info = page.Locator("text=Selected index:");
18+
19+
// ✅ GOOD — matches the parent <p>, returns label + value
20+
var info = page.Locator("p").Filter(new() { HasTextString = "Selected index:" });
21+
```
22+
23+
For elements that might appear in multiple places (rendered output + code examples), target the specific rendered element type:
24+
25+
```csharp
26+
// ❌ BAD — strict mode violation if text appears twice
27+
var header = page.Locator("text=Widget Catalog");
28+
29+
// ✅ GOOD — targets only the rendered <td>
30+
var header = page.Locator("td").Filter(new() { HasTextString = "Widget Catalog" }).First;
31+
```
32+
33+
## Consequences
34+
35+
- Existing tests using bare `text=` locators for value extraction should be migrated.
36+
- New tests must follow this pattern from the start.
37+
- WaitForSelectorAsync calls should use specific selectors (e.g., `button:has-text('Edit')`) not generic element type selectors.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# DataGrid Style Sub-Components + Paging/Sorting Events
2+
3+
**By:** Cyclops
4+
**Date:** 2026-02-24
5+
**Work Items:** WI-44, WI-45
6+
7+
## Decision
8+
9+
DataGrid style sub-components follow the exact same `IXxxStyleContainer` + `UiTableItemStyle` + `CascadingParameter` pattern used by GridView, DetailsView, and FormView. Paging and sorting events follow Web Forms DataGrid naming conventions (not GridView conventions).
10+
11+
## Details — WI-44 (Style Sub-Components)
12+
13+
- **Interface:** `IDataGridStyleContainer` with 7 TableItemStyle properties (AlternatingItemStyle, ItemStyle, HeaderStyle, FooterStyle, PagerStyle, SelectedItemStyle, EditItemStyle)
14+
- **CascadingValue name:** `"ParentDataGrid"` (matching GridView's `"ParentGridView"` convention)
15+
- **7 sub-component pairs:** DataGridAlternatingItemStyle, DataGridItemStyle, DataGridHeaderStyle, DataGridFooterStyle, DataGridPagerStyle, DataGridSelectedItemStyle, DataGridEditItemStyle
16+
- **Style priority in GetRowStyle:** EditItemStyle > SelectedItemStyle > AlternatingItemStyle > ItemStyle (matches Web Forms precedence)
17+
- **Display properties added:** Caption, CaptionAlign, CellPadding, CellSpacing, GridLines, UseAccessibleHeader
18+
- **Template enhanced:** Paging UI (page links in tfoot), footer row, caption element, grid lines rules attribute, sortable header links
19+
20+
## Details — WI-45 (Paging + Sorting Events)
21+
22+
- **Events:** PageIndexChanged (DataGridPageChangedEventArgs), SortCommand (DataGridSortCommandEventArgs), ItemCreated (DataGridItemEventArgs), ItemDataBound (DataGridItemEventArgs), SelectedIndexChanged (EventCallback)
23+
- **Event args:** DataGridPageChangedEventArgs (NewPageIndex), DataGridSortCommandEventArgs (SortExpression, CommandSource), DataGridItemEventArgs (Item)
24+
- **Paging:** GoToPage(int) updates CurrentPageIndex and fires PageIndexChanged
25+
- **Sorting:** Sort(string) fires SortCommand when AllowSorting is enabled via header links
26+
27+
## Key Naming Difference: DataGrid vs GridView
28+
29+
DataGrid uses Web Forms DataGrid naming (ItemStyle, AlternatingItemStyle, EditItemIndex, CurrentPageIndex) rather than GridView naming (RowStyle, AlternatingRowStyle, EditIndex, PageIndex). This matches the original ASP.NET Web Forms distinction between the two controls.
30+
31+
## Why
32+
33+
Consistency with existing GridView style pattern ensures predictable API. DataGrid-specific naming preserves Web Forms migration fidelity — developers migrating `<asp:DataGrid>` markup expect `ItemStyle` not `RowStyle`.

0 commit comments

Comments
 (0)