@playpilot/tpi 5.22.0 → 5.23.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/link-injections.js +11 -11
- package/events.md +1 -0
- package/package.json +1 -1
- package/src/lib/api/participants.ts +16 -0
- package/src/lib/api/titles.ts +9 -0
- package/src/lib/data/translations.ts +5 -0
- package/src/lib/enums/TrackingEvent.ts +1 -0
- package/src/routes/components/ListTitle.svelte +4 -4
- package/src/routes/components/Participant.svelte +61 -4
- package/src/routes/components/Rails/ParticipantsRail.svelte +19 -9
- package/src/routes/components/Rails/SimilarRail.svelte +2 -9
- package/src/routes/components/Title.svelte +2 -5
- package/src/routes/components/TitlePoster.svelte +1 -0
- package/src/tests/routes/components/Participant.test.js +76 -0
- package/src/tests/routes/components/ParticipantModal.test.js +4 -0
- package/src/tests/routes/components/Rails/ParticipantsRail.test.js +39 -9
- package/src/tests/routes/components/Rails/SimilarRail.test.js +26 -0
- package/src/tests/routes/components/Title.test.js +17 -0
- package/src/tests/routes/components/TitleModal.test.js +15 -9
- package/src/tests/routes/components/TitlePopover.test.js +8 -0
package/events.md
CHANGED
|
@@ -37,6 +37,7 @@ Event | Action | Info | Payload
|
|
|
37
37
|
`ali_participant_modal_view` | _Fires any time a title modal is viewed_ | The title modal opens when viewing a participant modal both on desktop and mobile | `participant` (name of the participant)
|
|
38
38
|
`ali_participant_modal_close` | _Fires any time a title modal is closed_ | | `participant` (name of the participant) `time_spent` (time between modal_view and modal_close milliseconds)
|
|
39
39
|
'ali_similar_title_click' | _Fires any time a similar titles rail item is clicked_ | Title | `title_source` (original name of the title the rail item was clicked in)
|
|
40
|
+
'ali_participant_click' | _Fires any time a participants rail item is clicked_ | null | `title_source` (original name of the title the rail item was clicked in), `participant` (name of the clicked participant)
|
|
40
41
|
|
|
41
42
|
### Popover
|
|
42
43
|
Event | Action | Info | Payload
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getApiToken } from '$lib/token'
|
|
2
|
+
import type { ParticipantData } from '$lib/types/participant'
|
|
3
|
+
import type { TitleData } from '../types/title'
|
|
4
|
+
import { api } from './api'
|
|
5
|
+
|
|
6
|
+
export async function fetchTitlesForParticipant(participant: ParticipantData, { page = 1 }: { page?: number } = {}): Promise<TitleData[]> {
|
|
7
|
+
const response = await api<{ results: TitleData[] }>(`/titles/browse?api-token=${getApiToken()}&participant_sid=${participant.sid}&page=${page}`)
|
|
8
|
+
|
|
9
|
+
return response.results
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function fetchParticipantsForTitle(title: TitleData): Promise<ParticipantData[]> {
|
|
13
|
+
const response = await api<{ results: ParticipantData[] }>(`/participants/browse?api-token=${getApiToken()}&title_sid=${title.sid}`)
|
|
14
|
+
|
|
15
|
+
return response.results
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { getApiToken } from '$lib/token'
|
|
2
|
+
import type { TitleData } from '../types/title'
|
|
3
|
+
import { api } from './api'
|
|
4
|
+
|
|
5
|
+
export async function fetchSimilarTitles(title: TitleData): Promise<TitleData[]> {
|
|
6
|
+
const response = await api<{ results: TitleData[] }>(`/titles/browse?api-token=${getApiToken()}&related_to_sid=${title.sid}`)
|
|
7
|
+
|
|
8
|
+
return response.results
|
|
9
|
+
}
|
|
@@ -101,6 +101,11 @@ export const translations = {
|
|
|
101
101
|
[Language.Swedish]: 'Få',
|
|
102
102
|
[Language.Danish]: 'Få',
|
|
103
103
|
},
|
|
104
|
+
'Show More': {
|
|
105
|
+
[Language.English]: 'Show more',
|
|
106
|
+
[Language.Swedish]: 'Visa mer',
|
|
107
|
+
[Language.Danish]: 'Vis mere',
|
|
108
|
+
},
|
|
104
109
|
|
|
105
110
|
// Genres
|
|
106
111
|
'All': {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
}
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
|
-
<a class="title" href={titleUrl(title)} {onclick}>
|
|
32
|
+
<a class="title" href={titleUrl(title)} {onclick} data-testid="title">
|
|
33
33
|
<div class="poster">
|
|
34
34
|
<TitlePoster {title} width={30} height={43} />
|
|
35
35
|
</div>
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
display: flex;
|
|
90
90
|
align-items: center;
|
|
91
91
|
width: 100%;
|
|
92
|
-
background: var(--playpilot-list-item-background, var(--playpilot-lighter));
|
|
92
|
+
background: var(--playpilot-list-item-background, var(--playpilot-playlink-background, var(--playpilot-lighter)));
|
|
93
93
|
padding: margin(0.5);
|
|
94
94
|
border: 0;
|
|
95
95
|
border-radius: var(--playpilot-list-item-border-radius, margin(0.5));
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
font-style: normal !important;
|
|
98
98
|
|
|
99
99
|
&:hover {
|
|
100
|
-
|
|
100
|
+
filter: var(--playpilot-list-item-hover-filter, var(--playpilot-playlink-hover-filter, brightness(1.1)));
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
&:last-child {
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
width: margin(4.125);
|
|
113
113
|
aspect-ratio: 2/3;
|
|
114
114
|
border-radius: var(--playpilot-detail-image-border-radius, margin(0.5));
|
|
115
|
-
background: var(--playpilot-detail-image-background, var(--playpilot-content));
|
|
115
|
+
background: var(--playpilot-detail-image-background, var(--playpilot-genre-background, var(--playpilot-content)));
|
|
116
116
|
overflow: hidden;
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte'
|
|
2
3
|
import { heading } from '$lib/actions/heading'
|
|
4
|
+
import { fetchTitlesForParticipant } from '$lib/api/participants'
|
|
3
5
|
import { SplitTest } from '$lib/enums/SplitTest'
|
|
4
6
|
import { openModal } from '$lib/modal'
|
|
5
7
|
import { trackSplitTestView } from '$lib/splitTest'
|
|
6
8
|
import type { ParticipantData } from '$lib/types/participant'
|
|
9
|
+
import type { TitleData } from '$lib/types/title'
|
|
7
10
|
import ListTitle from './ListTitle.svelte'
|
|
11
|
+
import { t } from '$lib/localization'
|
|
8
12
|
|
|
9
13
|
interface Props {
|
|
10
14
|
participant: ParticipantData
|
|
@@ -14,12 +18,37 @@
|
|
|
14
18
|
|
|
15
19
|
const { name, birth_date, death_date } = $derived(participant)
|
|
16
20
|
|
|
21
|
+
const pageSize = 30
|
|
22
|
+
|
|
17
23
|
trackSplitTestView(SplitTest.ParticipantPlaylinkFormat)
|
|
18
24
|
|
|
25
|
+
let titles: TitleData[] = $state([])
|
|
26
|
+
let page = $state(1)
|
|
27
|
+
let hasMorePages = $state(true)
|
|
28
|
+
let loading = $state(true)
|
|
29
|
+
|
|
30
|
+
onMount(loadMore)
|
|
31
|
+
|
|
19
32
|
function formatDate(dateString: string): string {
|
|
20
33
|
const date = new Date(dateString)
|
|
21
34
|
return date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
|
|
22
35
|
}
|
|
36
|
+
|
|
37
|
+
async function loadMore() {
|
|
38
|
+
loading = true
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const results = await fetchTitlesForParticipant(participant, { page })
|
|
42
|
+
|
|
43
|
+
titles = [...titles, ...results]
|
|
44
|
+
hasMorePages = results?.length >= pageSize
|
|
45
|
+
} catch {
|
|
46
|
+
hasMorePages = false
|
|
47
|
+
} finally {
|
|
48
|
+
loading = false
|
|
49
|
+
page += 1
|
|
50
|
+
}
|
|
51
|
+
}
|
|
23
52
|
</script>
|
|
24
53
|
|
|
25
54
|
<div class="header">
|
|
@@ -36,11 +65,17 @@
|
|
|
36
65
|
<div class="heading small" use:heading={3} id="credits">Credits</div>
|
|
37
66
|
|
|
38
67
|
<div class="list">
|
|
39
|
-
{#each
|
|
40
|
-
{
|
|
41
|
-
<ListTitle {title} onclick={(event) => openModal({ event, data: title })} />
|
|
42
|
-
{/if}
|
|
68
|
+
{#each titles as title}
|
|
69
|
+
<ListTitle {title} onclick={(event) => openModal({ event, data: title })} />
|
|
43
70
|
{/each}
|
|
71
|
+
|
|
72
|
+
{#if loading}
|
|
73
|
+
{#each { length: 6 }}
|
|
74
|
+
<div class="skeleton" data-testid="skeleton"></div>
|
|
75
|
+
{/each}
|
|
76
|
+
{:else if hasMorePages}
|
|
77
|
+
<button class="more" onclick={loadMore}>{t('Show More')}</button>
|
|
78
|
+
{/if}
|
|
44
79
|
</div>
|
|
45
80
|
</div>
|
|
46
81
|
|
|
@@ -89,4 +124,26 @@
|
|
|
89
124
|
flex-direction: column;
|
|
90
125
|
gap: margin(0.5);
|
|
91
126
|
}
|
|
127
|
+
|
|
128
|
+
.skeleton {
|
|
129
|
+
min-height: margin(7.25);
|
|
130
|
+
border-radius: var(--playpilot-playlink-border-radius, margin(0.5));
|
|
131
|
+
background: var(--playpilot-list-item-background, var(--playpilot-lighter));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.more {
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
appearance: none;
|
|
137
|
+
padding: margin(0.5) margin(1);
|
|
138
|
+
border: 0;
|
|
139
|
+
border-radius: var(--playpilot-participants-load-more-border-radius, var(--playpilot-list-item-border-radius, margin(0.5)));
|
|
140
|
+
background: var(--playpilot-participants-load-more-background, var(--playpilot-button-background, var(--playpilot-content)));
|
|
141
|
+
color: inherit;
|
|
142
|
+
font-size: inherit;
|
|
143
|
+
font-family: inherit;
|
|
144
|
+
|
|
145
|
+
&:hover {
|
|
146
|
+
filter: brightness(1.2);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
92
149
|
</style>
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { fetchParticipantsForTitle } from '$lib/api/participants'
|
|
3
|
+
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
3
4
|
import { openModal } from '$lib/modal'
|
|
5
|
+
import { track } from '$lib/tracking'
|
|
4
6
|
import type { ParticipantData } from '$lib/types/participant'
|
|
7
|
+
import type { TitleData } from '$lib/types/title'
|
|
5
8
|
import Rail from './Rail.svelte'
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
interface Props {
|
|
11
|
+
title: TitleData
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { title }: Props = $props()
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
function onclick(event: MouseEvent, participant: ParticipantData): void {
|
|
17
|
+
openModal({ event, type: 'participant', data: participant })
|
|
18
|
+
track(TrackingEvent.ParticipantClick, null, { title_source: title.original_title, participant: participant.name })
|
|
12
19
|
}
|
|
13
20
|
</script>
|
|
14
21
|
|
|
15
|
-
{#await
|
|
22
|
+
{#await fetchParticipantsForTitle(title)}
|
|
16
23
|
<Rail heading="Cast">
|
|
17
24
|
{#each { length: 5 }}
|
|
18
25
|
<div class="participant"></div>
|
|
@@ -22,10 +29,12 @@
|
|
|
22
29
|
{#if participants?.length}
|
|
23
30
|
<Rail heading="Cast">
|
|
24
31
|
{#each participants.slice(0, 15) as participant}
|
|
25
|
-
<button class="participant" data-testid="participant" onclick={event =>
|
|
32
|
+
<button class="participant" data-testid="participant" onclick={event => onclick(event, participant)}>
|
|
26
33
|
<span class="truncate">{participant.name}</span>
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
{#if participant.character}
|
|
36
|
+
<div class="character truncate">{participant.character}</div>
|
|
37
|
+
{/if}
|
|
29
38
|
</button>
|
|
30
39
|
{/each}
|
|
31
40
|
</Rail>
|
|
@@ -34,7 +43,8 @@
|
|
|
34
43
|
|
|
35
44
|
<style lang="scss">
|
|
36
45
|
.participant {
|
|
37
|
-
display:
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
38
48
|
flex: 0 0 10rem;
|
|
39
49
|
width: 10rem;
|
|
40
50
|
min-height: margin(3.375); // Matches 54 pixels, the height of a card with both name and character
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { fetchSimilarTitles } from '$lib/api/titles'
|
|
2
3
|
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
3
4
|
import { track } from '$lib/tracking'
|
|
4
5
|
import type { TitleData } from '$lib/types/title'
|
|
@@ -10,15 +11,7 @@
|
|
|
10
11
|
|
|
11
12
|
const { title }: Props = $props()
|
|
12
13
|
|
|
13
|
-
const titles =
|
|
14
|
-
|
|
15
|
-
async function fetchTitles(): Promise<TitleData[]> {
|
|
16
|
-
// This is just a fake loading state for now
|
|
17
|
-
await new Promise(res => setTimeout(res, 500))
|
|
18
|
-
|
|
19
|
-
// Imagine this being a fetch request that returns titles instead.
|
|
20
|
-
return (window.PlayPilotLinkInjections?.evaluated_link_injections?.map(i => i.title_details) || []) as TitleData[]
|
|
21
|
-
}
|
|
14
|
+
const titles = fetchSimilarTitles(title)
|
|
22
15
|
</script>
|
|
23
16
|
|
|
24
17
|
<TitlesRail {titles} heading="Similar movies & shows" onclick={(targetTitle) => track(TrackingEvent.SimilarTitleClick, targetTitle, { title_source: title.original_title })} />
|
|
@@ -55,11 +55,8 @@
|
|
|
55
55
|
<Description text={title.description} blurb={title.blurb} />
|
|
56
56
|
{/if}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
<ParticipantsRail />
|
|
61
|
-
<SimilarRail {title} />
|
|
62
|
-
{/if}
|
|
58
|
+
<ParticipantsRail {title} />
|
|
59
|
+
<SimilarRail {title} />
|
|
63
60
|
</div>
|
|
64
61
|
</div>
|
|
65
62
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { fireEvent, render, waitFor } from '@testing-library/svelte'
|
|
2
|
+
import { describe, expect, it, vi, beforeEach } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import Participant from '../../../routes/components/Participant.svelte'
|
|
5
|
+
import { participants, title } from '$lib/fakeData'
|
|
6
|
+
import { fetchTitlesForParticipant } from '$lib/api/participants'
|
|
7
|
+
|
|
8
|
+
vi.mock('$lib/tracking', () => ({
|
|
9
|
+
track: vi.fn(),
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
vi.mock('$lib/api/participants', () => ({
|
|
13
|
+
fetchTitlesForParticipant: vi.fn(),
|
|
14
|
+
}))
|
|
15
|
+
|
|
16
|
+
describe('Participant.svelte', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
vi.resetAllMocks()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('Should call fetchTitlesForParticipant on mount', () => {
|
|
22
|
+
render(Participant, { participant: participants[0] })
|
|
23
|
+
|
|
24
|
+
expect(fetchTitlesForParticipant).toHaveBeenCalledWith(participants[0], { page: 1 })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('Should render fetched titles after showing skeletons', async () => {
|
|
28
|
+
vi.mocked(fetchTitlesForParticipant).mockResolvedValueOnce([title, title])
|
|
29
|
+
|
|
30
|
+
const { getAllByTestId } = render(Participant, { participant: participants[0] })
|
|
31
|
+
|
|
32
|
+
expect(getAllByTestId('skeleton')).toHaveLength(6)
|
|
33
|
+
|
|
34
|
+
await waitFor(() => {
|
|
35
|
+
expect(getAllByTestId('title')).toHaveLength(2)
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('Should not show load more button while loading and when fewer than page size of titles are fetched', async () => {
|
|
40
|
+
vi.mocked(fetchTitlesForParticipant).mockResolvedValueOnce([title, title])
|
|
41
|
+
|
|
42
|
+
const { queryByText, getAllByTestId } = render(Participant, { participant: participants[0] })
|
|
43
|
+
|
|
44
|
+
expect(queryByText('Show More')).not.toBeTruthy()
|
|
45
|
+
|
|
46
|
+
await waitFor(() => {
|
|
47
|
+
expect(getAllByTestId('title')).toHaveLength(2)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
expect(queryByText('Show More')).not.toBeTruthy()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('Should show load more button after loading and if more than page size of titles are fetched', async () => {
|
|
54
|
+
const resolved = Array(30).fill(title)
|
|
55
|
+
vi.mocked(fetchTitlesForParticipant).mockResolvedValueOnce(resolved)
|
|
56
|
+
|
|
57
|
+
const { getByText } = render(Participant, { participant: participants[0] })
|
|
58
|
+
|
|
59
|
+
await waitFor(() => {
|
|
60
|
+
expect(getByText('Show more')).toBeTruthy()
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('Should fetch more titles when load more button is clicked', async () => {
|
|
65
|
+
const resolved = Array(30).fill(title)
|
|
66
|
+
vi.mocked(fetchTitlesForParticipant).mockResolvedValueOnce(resolved)
|
|
67
|
+
|
|
68
|
+
const { getByText } = render(Participant, { participant: participants[0] })
|
|
69
|
+
|
|
70
|
+
await waitFor(() => getByText('Show more'))
|
|
71
|
+
|
|
72
|
+
await fireEvent.click(getByText('Show more'))
|
|
73
|
+
|
|
74
|
+
expect(fetchTitlesForParticipant).toHaveBeenCalledWith(participants[0], { page: 2 })
|
|
75
|
+
})
|
|
76
|
+
})
|
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
import { fireEvent, render, waitFor } from '@testing-library/svelte'
|
|
2
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
3
|
|
|
4
4
|
import ParticipantsRail from '../../../../routes/components/Rails/ParticipantsRail.svelte'
|
|
5
5
|
import { openModal } from '$lib/modal'
|
|
6
|
-
import { participants } from '$lib/fakeData'
|
|
6
|
+
import { participants, title } from '$lib/fakeData'
|
|
7
|
+
import { track } from '$lib/tracking'
|
|
8
|
+
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
9
|
+
import { fetchParticipantsForTitle } from '$lib/api/participants'
|
|
7
10
|
|
|
8
11
|
vi.mock('$lib/modal', () => ({
|
|
9
12
|
openModal: vi.fn(),
|
|
10
13
|
}))
|
|
11
14
|
|
|
15
|
+
vi.mock('$lib/tracking', () => ({
|
|
16
|
+
track: vi.fn(),
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
vi.mock('$lib/api/participants', () => ({
|
|
20
|
+
fetchParticipantsForTitle: vi.fn(),
|
|
21
|
+
}))
|
|
22
|
+
|
|
12
23
|
describe('ParticipantsRail.svelte', () => {
|
|
13
24
|
it('Should render each given participant', async () => {
|
|
25
|
+
vi.mocked(fetchParticipantsForTitle).mockResolvedValueOnce(participants)
|
|
26
|
+
|
|
14
27
|
// @ts-ignore
|
|
15
|
-
const { getByText } = render(ParticipantsRail)
|
|
28
|
+
const { getByText } = render(ParticipantsRail, { title })
|
|
16
29
|
|
|
17
30
|
await waitFor(() => {
|
|
18
31
|
expect(getByText(participants[0].name)).toBeTruthy()
|
|
@@ -20,15 +33,20 @@ describe('ParticipantsRail.svelte', () => {
|
|
|
20
33
|
})
|
|
21
34
|
})
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// const { container } = render(ParticipantsRail)
|
|
36
|
+
it('Should not render when no participants are returned', async () => {
|
|
37
|
+
vi.mocked(fetchParticipantsForTitle).mockResolvedValueOnce([])
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
const { container } = render(ParticipantsRail)
|
|
40
|
+
|
|
41
|
+
await waitFor(() => {
|
|
42
|
+
expect(container.querySelectorAll('.participant').length).toBe(0)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
29
45
|
|
|
30
46
|
it('Should open modal on click of participant', async () => {
|
|
31
|
-
|
|
47
|
+
vi.mocked(fetchParticipantsForTitle).mockResolvedValueOnce(participants)
|
|
48
|
+
|
|
49
|
+
const { getAllByTestId } = render(ParticipantsRail, { title })
|
|
32
50
|
|
|
33
51
|
await waitFor(async () => {
|
|
34
52
|
await fireEvent.click(getAllByTestId('participant')[0])
|
|
@@ -36,4 +54,16 @@ describe('ParticipantsRail.svelte', () => {
|
|
|
36
54
|
|
|
37
55
|
expect(openModal).toHaveBeenCalledWith({ event: expect.any(Object), type: 'participant', data: participants[0] })
|
|
38
56
|
})
|
|
57
|
+
|
|
58
|
+
it('Should fire track event on click of participant', async () => {
|
|
59
|
+
vi.mocked(fetchParticipantsForTitle).mockResolvedValueOnce(participants)
|
|
60
|
+
|
|
61
|
+
const { getAllByTestId } = render(ParticipantsRail, { title })
|
|
62
|
+
|
|
63
|
+
await waitFor(async () => {
|
|
64
|
+
await fireEvent.click(getAllByTestId('participant')[0])
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.ParticipantClick, null, { title_source: title.original_title, participant: participants[0].name })
|
|
68
|
+
})
|
|
39
69
|
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { render } from '@testing-library/svelte'
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { title } from '$lib/fakeData'
|
|
5
|
+
import SimilarRail from '../../../../routes/components/Rails/SimilarRail.svelte'
|
|
6
|
+
import { fetchSimilarTitles } from '$lib/api/titles'
|
|
7
|
+
|
|
8
|
+
vi.mock('$lib/modal', () => ({
|
|
9
|
+
openModal: vi.fn(),
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
vi.mock('$lib/tracking', () => ({
|
|
13
|
+
track: vi.fn(),
|
|
14
|
+
}))
|
|
15
|
+
|
|
16
|
+
vi.mock('$lib/api/titles', () => ({
|
|
17
|
+
fetchSimilarTitles: vi.fn(),
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
describe('ParticipantsRail.svelte', () => {
|
|
21
|
+
it('Should fetch titles', async () => {
|
|
22
|
+
render(SimilarRail, { title })
|
|
23
|
+
|
|
24
|
+
expect(fetchSimilarTitles).toHaveBeenCalledWith(title)
|
|
25
|
+
})
|
|
26
|
+
})
|
|
@@ -3,11 +3,21 @@ import { describe, expect, it, vi, beforeEach } from 'vitest'
|
|
|
3
3
|
|
|
4
4
|
import Title from '../../../routes/components/Title.svelte'
|
|
5
5
|
import { title } from '$lib/fakeData'
|
|
6
|
+
import { fetchParticipantsForTitle } from '$lib/api/participants'
|
|
7
|
+
import { fetchSimilarTitles } from '$lib/api/titles'
|
|
6
8
|
|
|
7
9
|
vi.mock('$lib/tracking', () => ({
|
|
8
10
|
track: vi.fn(),
|
|
9
11
|
}))
|
|
10
12
|
|
|
13
|
+
vi.mock('$lib/api/participants', () => ({
|
|
14
|
+
fetchParticipantsForTitle: vi.fn(),
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
vi.mock('$lib/api/titles', () => ({
|
|
18
|
+
fetchSimilarTitles: vi.fn(),
|
|
19
|
+
}))
|
|
20
|
+
|
|
11
21
|
vi.mock('svelte', async (importActual) => ({
|
|
12
22
|
...(await importActual()),
|
|
13
23
|
getContext: vi.fn(),
|
|
@@ -74,4 +84,11 @@ describe('Title.svelte', () => {
|
|
|
74
84
|
|
|
75
85
|
expect(container.querySelector('.paragraph')).not.toBeTruthy()
|
|
76
86
|
})
|
|
87
|
+
|
|
88
|
+
it('Should call fetches for participants and similar titles', () => {
|
|
89
|
+
render(Title, { title })
|
|
90
|
+
|
|
91
|
+
expect(fetchParticipantsForTitle).toHaveBeenCalled()
|
|
92
|
+
expect(fetchSimilarTitles).toHaveBeenCalled()
|
|
93
|
+
})
|
|
77
94
|
})
|
|
@@ -15,6 +15,14 @@ vi.mock('$lib/tracking', () => ({
|
|
|
15
15
|
track: vi.fn(),
|
|
16
16
|
}))
|
|
17
17
|
|
|
18
|
+
vi.mock('$lib/api/participants', () => ({
|
|
19
|
+
fetchParticipantsForTitle: vi.fn(),
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
vi.mock('$lib/api/titles', () => ({
|
|
23
|
+
fetchSimilarTitles: vi.fn(),
|
|
24
|
+
}))
|
|
25
|
+
|
|
18
26
|
describe('TitleModal.svelte', () => {
|
|
19
27
|
beforeEach(() => {
|
|
20
28
|
vi.resetAllMocks()
|
|
@@ -25,16 +33,14 @@ describe('TitleModal.svelte', () => {
|
|
|
25
33
|
vi.useRealTimers()
|
|
26
34
|
})
|
|
27
35
|
|
|
28
|
-
const onclose = vi.fn()
|
|
29
|
-
|
|
30
36
|
it('Should call track function when rendered', () => {
|
|
31
|
-
render(TitleModal, {
|
|
37
|
+
render(TitleModal, { title })
|
|
32
38
|
|
|
33
39
|
expect(track).toHaveBeenCalledWith(TrackingEvent.TitleModalView, title)
|
|
34
40
|
})
|
|
35
41
|
|
|
36
42
|
it('Should call track function when scrolled', async () => {
|
|
37
|
-
const { getByRole } = render(TitleModal, {
|
|
43
|
+
const { getByRole } = render(TitleModal, { title })
|
|
38
44
|
|
|
39
45
|
await fireEvent.scroll(getByRole('dialog'))
|
|
40
46
|
|
|
@@ -44,7 +50,7 @@ describe('TitleModal.svelte', () => {
|
|
|
44
50
|
it('Should call track function with time_spent when destroyed', async () => {
|
|
45
51
|
vi.useFakeTimers()
|
|
46
52
|
|
|
47
|
-
const { unmount } = render(TitleModal, {
|
|
53
|
+
const { unmount } = render(TitleModal, { title })
|
|
48
54
|
|
|
49
55
|
vi.advanceTimersByTime(200)
|
|
50
56
|
unmount()
|
|
@@ -56,7 +62,7 @@ describe('TitleModal.svelte', () => {
|
|
|
56
62
|
// @ts-ignore
|
|
57
63
|
window.PlayPilotLinkInjections = { ads: [{ campaign_format: 'top_scroll', content: {}, cta: {} }] }
|
|
58
64
|
|
|
59
|
-
const { container } = render(TitleModal, {
|
|
65
|
+
const { container } = render(TitleModal, { title })
|
|
60
66
|
|
|
61
67
|
expect(container.querySelector('.top-scroll')).toBeTruthy()
|
|
62
68
|
})
|
|
@@ -65,7 +71,7 @@ describe('TitleModal.svelte', () => {
|
|
|
65
71
|
// @ts-ignore
|
|
66
72
|
window.PlayPilotLinkInjections = { ads: null }
|
|
67
73
|
|
|
68
|
-
const { container } = render(TitleModal, {
|
|
74
|
+
const { container } = render(TitleModal, { title })
|
|
69
75
|
|
|
70
76
|
expect(container.querySelector('.top-scroll')).not.toBeTruthy()
|
|
71
77
|
})
|
|
@@ -74,7 +80,7 @@ describe('TitleModal.svelte', () => {
|
|
|
74
80
|
// @ts-ignore
|
|
75
81
|
window.PlayPilotLinkInjections = { ads: [{ campaign_format: 'card', content: {}, cta: {} }] }
|
|
76
82
|
|
|
77
|
-
const { container } = render(TitleModal, {
|
|
83
|
+
const { container } = render(TitleModal, { title })
|
|
78
84
|
|
|
79
85
|
expect(container.querySelector('.display')).toBeTruthy()
|
|
80
86
|
})
|
|
@@ -83,7 +89,7 @@ describe('TitleModal.svelte', () => {
|
|
|
83
89
|
// @ts-ignore
|
|
84
90
|
window.PlayPilotLinkInjections = { ads: null }
|
|
85
91
|
|
|
86
|
-
const { container } = render(TitleModal, {
|
|
92
|
+
const { container } = render(TitleModal, { title })
|
|
87
93
|
|
|
88
94
|
expect(container.querySelector('.display')).not.toBeTruthy()
|
|
89
95
|
})
|
|
@@ -15,6 +15,14 @@ vi.mock('$lib/tracking', () => ({
|
|
|
15
15
|
track: vi.fn(),
|
|
16
16
|
}))
|
|
17
17
|
|
|
18
|
+
vi.mock('$lib/api/participants', () => ({
|
|
19
|
+
fetchParticipantsForTitle: vi.fn(),
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
vi.mock('$lib/api/titles', () => ({
|
|
23
|
+
fetchSimilarTitles: vi.fn(),
|
|
24
|
+
}))
|
|
25
|
+
|
|
18
26
|
describe('TitlePopover.svelte', () => {
|
|
19
27
|
beforeEach(() => {
|
|
20
28
|
vi.resetAllMocks()
|