Skip to content

Add tests for ListBox selection synchronization (item→SelectedIndex and SelectedIndex→IsSelected)#163

Merged
tedd merged 2 commits into
forge-listbox-parity-5850515012165907113from
copilot/sub-pr-148-again
Mar 11, 2026
Merged

Add tests for ListBox selection synchronization (item→SelectedIndex and SelectedIndex→IsSelected)#163
tedd merged 2 commits into
forge-listbox-parity-5850515012165907113from
copilot/sub-pr-148-again

Conversation

Copilot AI commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

The OnItemSelected handler (bubbled SelectedEventSelectedIndex) and OnSelectionChanged override (container IsSelected sync) had no test coverage.

New tests in ListBoxTests

  • ItemIsSelected_ViaIsSelectedProperty_UpdatesListBoxSelectedIndex — sets container.IsSelected = true, asserts the SelectedEvent bubbles to ListBox and updates SelectedIndex
  • ItemSelectedEvent_RaisedOnContainer_UpdatesListBoxSelectedIndex — raises SelectedEvent directly on a container, asserts OnItemSelected resolves the correct panel index
  • SelectedIndex_Change_Updates_ContainersIsSelected — sets SelectedIndex, asserts exactly that container has IsSelected = true, all others false
  • SelectedIndex_Change_Deselects_PreviousContainer — moves selection between indices, asserts old container deselects and new one selects
  • SelectedIndex_MinusOne_Deselects_AllContainers — clears selection, asserts all containers deselected
// Example: item-driven path
var listBox = new ListBox();
listBox.Items.Add("A"); listBox.Items.Add("B"); listBox.Items.Add("C");
var container = (ListBoxItem)listBox.ItemsPanelRoot!.Children[1];
container.IsSelected = true;         // raises SelectedEvent → bubbles to ListBox
Assert.Equal(1, listBox.SelectedIndex);

// Example: index-driven path
listBox.SelectedIndex = 2;           // triggers OnSelectionChanged → syncs IsSelected
Assert.True(((ListBoxItem)listBox.ItemsPanelRoot.Children[2]).IsSelected);
Assert.False(((ListBoxItem)listBox.ItemsPanelRoot.Children[0]).IsSelected);

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

…ex and SelectedIndex→IsSelected paths

Co-authored-by: tedd <493224+tedd@users.noreply.github.com>
Copilot AI changed the title [WIP] Address feedback on ListBox parity integration Add tests for ListBox selection synchronization (item→SelectedIndex and SelectedIndex→IsSelected) Mar 11, 2026
Copilot finished work on behalf of tedd March 11, 2026 13:12
@tedd
tedd marked this pull request as ready for review March 11, 2026 13:17
Copilot AI review requested due to automatic review settings March 11, 2026 13:17
@tedd
tedd merged commit 77795f0 into forge-listbox-parity-5850515012165907113 Mar 11, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds unit test coverage around ListBox selection synchronization (between SelectedIndex on the ListBox and IsSelected / routed selection events on ListBoxItem containers), helping ensure correct selector behavior as the TUI control set evolves.

Changes:

  • Add tests verifying ListBoxItem.IsSelected = true (and SelectedEvent) updates ListBox.SelectedIndex.
  • Add tests verifying ListBox.SelectedIndex changes update/deselect the corresponding ListBoxItem.IsSelected states, including clearing selection with -1.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +113 to +115
// ItemsPanelRoot is populated after items are added (via OnItemsCollectionChanged → PopulatePanel)
Assert.NotNull(listBox.ItemsPanelRoot);
var container1 = listBox.ItemsPanelRoot!.Children[1] as ListBoxItem;

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

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

The comment implies ItemsPanelRoot is created/populated only after items are added. In the current implementation, ListBox applies its Template in the constructor (via Control.Template DP), and ItemsPresenter.OnTemplatedParentChanged() creates ItemsPanelRoot immediately; adding items just repopulates it. Updating this comment (or explicitly calling listBox.ApplyTemplate() in the test) would make the test intent clearer and less coupled to the current initialization order.

Copilot uses AI. Check for mistakes.
Assert.NotNull(container2);

// Act: raise SelectedEvent directly on the third container
container2!.RaiseEvent(new RoutedEventArgs(ListBoxItem.SelectedEvent, container2));

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

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

RaiseEvent always overwrites RoutedEventArgs.Source with this, so passing container2 into the RoutedEventArgs(routedEvent, source) constructor here is redundant and can be misleading. Consider using the single-argument RoutedEventArgs(ListBoxItem.SelectedEvent) constructor for clarity.

Suggested change
container2!.RaiseEvent(new RoutedEventArgs(ListBoxItem.SelectedEvent, container2));
container2!.RaiseEvent(new RoutedEventArgs(ListBoxItem.SelectedEvent));

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants