Skip to content
This repository was archived by the owner on Feb 28, 2026. It is now read-only.

Commit a65d038

Browse files
committed
Dashboard entity search test
1 parent e60fefa commit a65d038

File tree

2 files changed

+98
-43
lines changed

2 files changed

+98
-43
lines changed

packages/player/src/views/Dashboard/Dashboard.test-wrapper.tsx

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { QueryClient } from '@tanstack/react-query';
12
import { createMemoryHistory, createRouter } from '@tanstack/react-router';
23
import { render, RenderResult, screen, within } from '@testing-library/react';
4+
import userEvent from '@testing-library/user-event';
35

46
import App from '../../App';
57
import { routeTree } from '../../routeTree.gen';
@@ -14,6 +16,19 @@ import {
1416
} from '../../test/fixtures/dashboard';
1517
import { resetInMemoryTauriStore } from '../../test/utils/inMemoryTauriStore';
1618

19+
type MountResult = RenderResult & {
20+
router: ReturnType<typeof createRouter<typeof routeTree>>;
21+
};
22+
23+
const findCard = (section: HTMLElement, text: string, label: string) => {
24+
const cards = within(section).getAllByTestId('card');
25+
const card = cards.find((card) => within(card).queryByText(text));
26+
if (!card) {
27+
throw new Error(`${label} "${text}" not found`);
28+
}
29+
return card;
30+
};
31+
1732
export const DashboardWrapper = {
1833
reset() {
1934
providersHost.clear();
@@ -24,12 +39,17 @@ export const DashboardWrapper = {
2439
providersHost.register(builder.build());
2540
},
2641

27-
async mount(): Promise<RenderResult> {
42+
async mount(): Promise<MountResult> {
2843
const history = createMemoryHistory({ initialEntries: ['/dashboard'] });
2944
const router = createRouter({ routeTree, history });
30-
const component = render(<App routerProp={router} />);
45+
const queryClient = new QueryClient({
46+
defaultOptions: { queries: { retry: false } },
47+
});
48+
const component = render(
49+
<App routerProp={router} queryClientProp={queryClient} />,
50+
);
3151
await screen.findByTestId('dashboard-view');
32-
return component;
52+
return { ...component, router };
3353
},
3454

3555
get emptyState() {
@@ -43,13 +63,6 @@ export const DashboardWrapper = {
4363
get table() {
4464
return screen.queryByTestId('dashboard-top-tracks');
4565
},
46-
async findTable() {
47-
return screen.findByTestId('dashboard-top-tracks');
48-
},
49-
track(title: string) {
50-
const table = screen.getByTestId('dashboard-top-tracks');
51-
return within(table).queryByText(title);
52-
},
5366
async findTrack(title: string) {
5467
const table = await screen.findByTestId('dashboard-top-tracks');
5568
return within(table).findByText(title);
@@ -61,53 +74,74 @@ export const DashboardWrapper = {
6174
return screen.queryByRole('heading', { name: /top artists/i });
6275
},
6376
artist(name: string) {
64-
const section = screen.getByTestId('dashboard-top-artists');
65-
return within(section).queryByText(name);
66-
},
67-
async findArtist(name: string) {
68-
const section = await screen.findByTestId('dashboard-top-artists');
69-
return within(section).findByText(name);
77+
return {
78+
async find() {
79+
const section = await screen.findByTestId('dashboard-top-artists');
80+
return within(section).findByText(name);
81+
},
82+
async click() {
83+
const section = await screen.findByTestId('dashboard-top-artists');
84+
await userEvent.click(findCard(section, name, 'Artist card'));
85+
},
86+
};
7087
},
7188
},
7289

7390
topAlbums: {
74-
get section() {
75-
return screen.queryByTestId('dashboard-top-albums');
76-
},
7791
get heading() {
7892
return screen.queryByRole('heading', { name: /top albums/i });
7993
},
80-
async findAlbum(title: string) {
81-
const section = await screen.findByTestId('dashboard-top-albums');
82-
return within(section).findByText(title);
94+
album(title: string) {
95+
return {
96+
async find() {
97+
const section = await screen.findByTestId('dashboard-top-albums');
98+
return within(section).findByText(title);
99+
},
100+
async click() {
101+
const section = await screen.findByTestId('dashboard-top-albums');
102+
await userEvent.click(findCard(section, title, 'Album card'));
103+
},
104+
};
83105
},
84106
},
85107

86108
editorialPlaylists: {
87-
get section() {
88-
return screen.queryByTestId('dashboard-editorial-playlists');
89-
},
90109
get heading() {
91110
return screen.queryByRole('heading', { name: /top playlists/i });
92111
},
93-
async findPlaylist(name: string) {
94-
const section = await screen.findByTestId(
95-
'dashboard-editorial-playlists',
96-
);
97-
return within(section).findByText(name);
112+
playlist(name: string) {
113+
return {
114+
async find() {
115+
const section = await screen.findByTestId(
116+
'dashboard-editorial-playlists',
117+
);
118+
return within(section).findByText(name);
119+
},
120+
async click() {
121+
const section = await screen.findByTestId(
122+
'dashboard-editorial-playlists',
123+
);
124+
await userEvent.click(findCard(section, name, 'Playlist card'));
125+
},
126+
};
98127
},
99128
},
100129

101130
newReleases: {
102-
get section() {
103-
return screen.queryByTestId('dashboard-new-releases');
104-
},
105131
get heading() {
106132
return screen.queryByRole('heading', { name: /new releases/i });
107133
},
108-
async findRelease(title: string) {
109-
const section = await screen.findByTestId('dashboard-new-releases');
110-
return within(section).findByText(title);
134+
release(title: string) {
135+
return {
136+
async find() {
137+
const section = await screen.findByTestId('dashboard-new-releases');
138+
return within(section).findByText(title);
139+
},
140+
async click() {
141+
const section = await screen.findByTestId('dashboard-new-releases');
142+
await userEvent.click(findCard(section, title, 'Release card'));
143+
},
144+
};
111145
},
112146
},
113147

@@ -148,5 +182,13 @@ export const DashboardWrapper = {
148182
.withCapabilities('newReleases')
149183
.withFetchNewReleases(async () => NEW_RELEASES_DASHBOARD);
150184
},
185+
topArtistsProviderWithoutMetadata() {
186+
return new DashboardProviderBuilder()
187+
.withId('discovery-dashboard')
188+
.withName('Discovery')
189+
.withMetadataProviderId(undefined)
190+
.withCapabilities('topArtists')
191+
.withFetchTopArtists(async () => TOP_ARTISTS_DASHBOARD);
192+
},
151193
},
152194
};

packages/player/src/views/Dashboard/Dashboard.test.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ describe('Dashboard view', () => {
4949

5050
expect(DashboardWrapper.topArtists.heading).toBeInTheDocument();
5151
expect(
52-
await DashboardWrapper.topArtists.findArtist('Radiohead'),
52+
await DashboardWrapper.topArtists.artist('Radiohead').find(),
5353
).toBeInTheDocument();
5454
expect(
55-
await DashboardWrapper.topArtists.findArtist('Björk'),
55+
await DashboardWrapper.topArtists.artist('Björk').find(),
5656
).toBeInTheDocument();
5757
});
5858

@@ -64,7 +64,7 @@ describe('Dashboard view', () => {
6464
await DashboardWrapper.mount();
6565

6666
expect(
67-
await DashboardWrapper.topAlbums.findAlbum('Kid A'),
67+
await DashboardWrapper.topAlbums.album('Kid A').find(),
6868
).toBeInTheDocument();
6969
expect(DashboardWrapper.topAlbums.heading).toBeInTheDocument();
7070
});
@@ -77,9 +77,9 @@ describe('Dashboard view', () => {
7777
await DashboardWrapper.mount();
7878

7979
expect(
80-
await DashboardWrapper.editorialPlaylists.findPlaylist(
81-
'Art Rock Essentials',
82-
),
80+
await DashboardWrapper.editorialPlaylists
81+
.playlist('Art Rock Essentials')
82+
.find(),
8383
).toBeInTheDocument();
8484
expect(DashboardWrapper.editorialPlaylists.heading).toBeInTheDocument();
8585
});
@@ -92,11 +92,24 @@ describe('Dashboard view', () => {
9292
await DashboardWrapper.mount();
9393

9494
expect(
95-
await DashboardWrapper.newReleases.findRelease('In Rainbows'),
95+
await DashboardWrapper.newReleases.release('In Rainbows').find(),
9696
).toBeInTheDocument();
9797
expect(DashboardWrapper.newReleases.heading).toBeInTheDocument();
9898
});
9999

100+
it('navigates to search when clicking an artist card without metadataProviderId', async () => {
101+
DashboardWrapper.seedProvider(
102+
DashboardWrapper.fixtures.topArtistsProviderWithoutMetadata(),
103+
);
104+
105+
const { router } = await DashboardWrapper.mount();
106+
107+
await DashboardWrapper.topArtists.artist('Radiohead').click();
108+
109+
expect(router.state.location.pathname).toBe('/search');
110+
expect(router.state.location.search).toEqual({ q: 'Radiohead' });
111+
});
112+
100113
it('shows tracks from multiple providers', async () => {
101114
DashboardWrapper.seedProvider(
102115
new DashboardProviderBuilder()

0 commit comments

Comments
 (0)