fix: contact book example: Make search great#318
Conversation
mohamedmansour
left a comment
There was a problem hiding this comment.
Thank you! Looking great!
mohamedmansour
left a comment
There was a problem hiding this comment.
CAn you please fix the playwright tests
There was a problem hiding this comment.
Pull request overview
This PR updates the contact-book-manager example to improve the “search” UX by adding zero-results empty-state UI on list pages and introducing new Playwright E2E coverage for search-driven filtering behavior. However, the PR as filed does not include the implementation that actually applies the search query to the contacts data, so the newly added E2E tests are expected to fail and the stated issue fix is incomplete.
Changes:
- Added
<cb-empty-state>rendering to Contacts/Favorites/Group list pages whencontactsis empty. - Added a new Playwright
describe('search')suite with 5 E2E tests asserting filtering, empty state, clear behavior, and navigation persistence. - Imported
cb-empty-statein the TS modules for the three list pages so the element is defined during hydration.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| examples/app/contact-book-manager/src/pages/cb-page-contacts/cb-page-contacts.html | Shows an empty state when the contacts list is empty. |
| examples/app/contact-book-manager/src/pages/cb-page-contacts/cb-page-contacts.ts | Imports cb-empty-state so it’s registered when the page module loads. |
| examples/app/contact-book-manager/src/pages/cb-page-favorites/cb-page-favorites.html | Shows an empty state when the favorites list is empty. |
| examples/app/contact-book-manager/src/pages/cb-page-favorites/cb-page-favorites.ts | Imports cb-empty-state so it’s registered when the page module loads. |
| examples/app/contact-book-manager/src/pages/cb-page-group/cb-page-group.html | Shows an empty state when the group list is empty. |
| examples/app/contact-book-manager/src/pages/cb-page-group/cb-page-group.ts | Imports cb-empty-state so it’s registered when the page module loads. |
| examples/app/contact-book-manager/tests/contact-book.spec.ts | Adds E2E tests asserting search filtering behavior and persistence across navigation. |
| test.describe('search', () => { | ||
| test('filters contacts on the contacts page as the user types', async ({ page }) => { | ||
| await page.goto('/contacts'); | ||
| await expect(page.locator('cb-page-contacts cb-contact-card')).toHaveCount(15); | ||
|
|
||
| const searchInput = page.locator('cb-header .search-input'); | ||
| await searchInput.fill('Sarah'); | ||
|
|
||
| // Only Sarah Chen should remain | ||
| await expect(page.locator('cb-page-contacts cb-contact-card')).toHaveCount(1); | ||
| await expect(page.locator('cb-page-contacts cb-contact-card')).toContainText('Sarah'); |
Apply the search query to the active list page by calling api.contacts.list with the current filters and pushing results into the page state. This was the missing piece that the empty state UI and the Playwright search tests depend on.
|
Thanks for the review. You were both right: the I have pushed that file now. The new commit adds the With the wiring in place the five search tests should now pass in CI. Let me know if you would like any adjustments. |
Summary
Root Cause
The search bar in
cb-headeremitssearch-changeevents that were captured bycb-app.onSearch, which stored the query inthis.searchQuery— but never used it to filter contacts. ThesearchQueryobservable was only passed back tocb-header(to keep the input in sync) and was not wired to any API call or state update on the active page component.Change Made
src/cb-app/cb-app.tsisStatefulimport from@microsoft/webui-routerandContacttype import.searchGenfield (generation counter to prevent stale async updates from racing).onNavigatedarrow function andconnectedCallback/disconnectedCallbackoverrides to listen forwebui:route:navigatedevents — this re-applies an active search whenever the user navigates to a list page.onSearchto callapplySearchin addition to storing the query.applySearch(query)method that:webui-route[active]in the shadow DOM to find the currently visible page component.api.contacts.list()with the appropriate filters.setState({ contacts })on the page element to update its rendered list.src/pages/cb-page-contacts/cb-page-contacts.html+.tscb-empty-stateimport.<if condition="contacts.length">and added an<if condition="!contacts.length"><cb-empty-state>block for zero-result feedback.src/pages/cb-page-favorites/cb-page-favorites.html+.tssrc/pages/cb-page-group/cb-page-group.html+.tstests/contact-book.spec.tsAdded a
searchtest suite with five E2E tests:cb-empty-statevisible./favorites.Issue
Fixes #191
Issue URL: #191
Changes
Testing
Agent ran relevant tests during development
Linting checks passed
Changes are minimal and focused on the issue
AI Assistance Disclosure
This pull request was prepared with the assistance of AI coding tools (GitHub Copilot). The change has been read, understood, and is owned by the human contributor submitting it, who will respond to review feedback.