@playpilot/tpi 4.0.0-beta.1 → 4.0.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 +10 -9
- package/eslint.config.js +15 -0
- package/package.json +3 -2
- package/release.js +31 -0
- package/src/lib/enums/TrackingEvent.ts +4 -0
- package/src/lib/linkInjection.ts +7 -5
- package/src/lib/scss/global.scss +18 -6
- package/src/lib/tracking.ts +1 -1
- package/src/lib/types/playlink.d.ts +2 -0
- package/src/routes/+page.svelte +43 -31
- package/src/routes/components/ContextMenu.svelte +1 -2
- package/src/routes/components/Editorial/AIIndicator.svelte +6 -6
- package/src/routes/components/Editorial/Alert.svelte +12 -2
- package/src/routes/components/Editorial/Editor.svelte +3 -2
- package/src/routes/components/Editorial/EditorItem.svelte +23 -2
- package/src/routes/components/Editorial/ManualInjection.svelte +1 -1
- package/src/routes/components/Editorial/ReportIssueModal.svelte +156 -0
- package/src/routes/components/Modal.svelte +5 -2
- package/src/routes/components/Playlinks.svelte +24 -5
- package/src/routes/components/Popover.svelte +2 -1
- package/src/routes/components/Title.svelte +1 -1
- package/src/routes/components/TitlePopover.svelte +1 -1
- package/src/tests/lib/auth.test.js +1 -1
- package/src/tests/lib/linkInjection.test.js +1 -1
- package/src/tests/routes/+page.test.js +31 -2
- package/src/tests/routes/components/Editorial/AiIndicator.test.js +7 -0
- package/src/tests/routes/components/Editorial/Alert.test.js +12 -0
- package/src/tests/routes/components/Editorial/EditorItem.test.js +13 -4
- package/src/tests/routes/components/Editorial/ReportIssueModal.test.js +63 -0
- package/src/tests/routes/components/Playlinks.test.js +23 -3
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
}
|
|
37
37
|
</script>
|
|
38
38
|
|
|
39
|
-
<div class="heading" use:heading={
|
|
39
|
+
<div class="heading" use:heading={3}>{t('Where To Stream Online')}</div>
|
|
40
40
|
|
|
41
41
|
<div class="playlinks" class:list>
|
|
42
|
-
{#each mergedPlaylink as { name, url, logo_url, extra_info: { category } }}
|
|
43
|
-
<a href={url} target="_blank" class="playlink" onclick={() => onclick(name)} data-playlink={name} rel="sponsored">
|
|
42
|
+
{#each mergedPlaylink as { name, url, logo_url, highlighted, cta_text, extra_info: { category } }}
|
|
43
|
+
<a href={url} target="_blank" class="playlink" class:highlighted={highlighted && cta_text} onclick={() => onclick(name)} data-playlink={name} rel="sponsored">
|
|
44
44
|
<img src={removeImageUrlPrefix(logo_url)} alt="" height="32" width="32" />
|
|
45
45
|
|
|
46
46
|
<div>
|
|
47
47
|
<span class="name">{name}</span>
|
|
48
|
-
<div class="category">{categoryStrings[category] || t('Stream')}</div>
|
|
48
|
+
<div class="category">{cta_text || categoryStrings[category] || t('Stream')}</div>
|
|
49
49
|
</div>
|
|
50
50
|
|
|
51
51
|
{#if list}
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
.playlink {
|
|
115
|
+
position: relative;
|
|
115
116
|
display: flex;
|
|
116
117
|
align-items: center;
|
|
117
118
|
gap: margin(0.75);
|
|
@@ -121,7 +122,7 @@
|
|
|
121
122
|
border-radius: var(--playpilot-playlink-border-radius, margin(0.5));
|
|
122
123
|
color: var(--playpilot-playlink-text-color, var(--playpilot-text-color-alt)) !important;
|
|
123
124
|
font-weight: var(--playpilot-playlink-font-weight, inherit);
|
|
124
|
-
font-style: var(--playpilot-playlink-font-style, normal);
|
|
125
|
+
font-style: var(--playpilot-playlink-font-style, normal) !important;
|
|
125
126
|
text-decoration: none !important;
|
|
126
127
|
white-space: nowrap;
|
|
127
128
|
font-size: var(--playpilot-playlinks-font-size, margin(0.75));
|
|
@@ -134,6 +135,23 @@
|
|
|
134
135
|
text-decoration: none !important;
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
&.highlighted {
|
|
139
|
+
&::before {
|
|
140
|
+
content: "";
|
|
141
|
+
z-index: 1;
|
|
142
|
+
display: block;
|
|
143
|
+
position: absolute;
|
|
144
|
+
top: 0;
|
|
145
|
+
right: 0;
|
|
146
|
+
bottom: 0;
|
|
147
|
+
left: 0;
|
|
148
|
+
border-radius: inherit;
|
|
149
|
+
box-shadow: inset 0 0 0 2px currentColor;
|
|
150
|
+
opacity: 0.35;
|
|
151
|
+
pointer-events: none;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
137
155
|
img {
|
|
138
156
|
margin: 0;
|
|
139
157
|
}
|
|
@@ -163,6 +181,7 @@
|
|
|
163
181
|
}
|
|
164
182
|
|
|
165
183
|
.arrow {
|
|
184
|
+
display: flex;
|
|
166
185
|
margin-left: auto;
|
|
167
186
|
padding: 0 margin(0.5);
|
|
168
187
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount, setContext, tick, type Snippet } from 'svelte'
|
|
3
|
+
import { prefersReducedMotion } from 'svelte/motion'
|
|
3
4
|
import { fly } from 'svelte/transition'
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
</script>
|
|
60
61
|
|
|
61
62
|
<div class="popover" class:flip bind:this={element} style:--max-height={maxHeight ? maxHeight + 'px' : null} tabindex="-1" aria-hidden="true">
|
|
62
|
-
<div class="dialog" transition:fly|global={{ duration: 100, y: 10 }} data-view-transition-old>
|
|
63
|
+
<div class="dialog" transition:fly|global={{ duration: prefersReducedMotion.current ? 0 : 100, y: 10 }} data-view-transition-old>
|
|
63
64
|
{@render children()}
|
|
64
65
|
</div>
|
|
65
66
|
</div>
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
}
|
|
43
43
|
</script>
|
|
44
44
|
|
|
45
|
-
<div class="title-popover" bind:this={element} data-playpilot-title-popover>
|
|
45
|
+
<div class="title-popover" bind:this={element} data-playpilot-title-popover role="region" aria-labelledby="title">
|
|
46
46
|
<Popover bind:maxHeight>
|
|
47
47
|
<Title {title} small compact={!!maxHeight && maxHeight < 250} />
|
|
48
48
|
</Popover>
|
|
@@ -70,7 +70,7 @@ describe('$lib/auth', () => {
|
|
|
70
70
|
|
|
71
71
|
it('Should not authorize is fetch response was negative', async () => {
|
|
72
72
|
fakeFetch({ response: '', ok: false, status: 403 })
|
|
73
|
-
|
|
73
|
+
const authorized = await authorize('https://example.com/some-path?articleReplacementEditToken=some-token')
|
|
74
74
|
|
|
75
75
|
expect(authorized).not.toBeTruthy()
|
|
76
76
|
expect(track).toHaveBeenCalled()
|
|
@@ -850,7 +850,7 @@ describe('linkInjection.js', () => {
|
|
|
850
850
|
const result = getLinkInjectionElements(parent, '[data-exclude]')
|
|
851
851
|
expect(result).toHaveLength(1)
|
|
852
852
|
expect(result[0].innerText).toBe('I am a regular element')
|
|
853
|
-
})
|
|
853
|
+
})
|
|
854
854
|
|
|
855
855
|
it('Should return paragraphs fully even if they contain no direct text nodes, skipping empty paragraphs', () => {
|
|
856
856
|
document.body.innerHTML = `<section>
|
|
@@ -9,6 +9,7 @@ import { authorize, getAuthToken, removeAuthCookie } from '$lib/auth'
|
|
|
9
9
|
import { generateInjection } from '../helpers'
|
|
10
10
|
import { injectLinksInDocument } from '$lib/linkInjection'
|
|
11
11
|
import { isCrawler } from '$lib/crawler'
|
|
12
|
+
import { getFullUrlPath } from '$lib/url'
|
|
12
13
|
|
|
13
14
|
vi.mock('$lib/api', () => ({
|
|
14
15
|
fetchLinkInjections: vi.fn(() => {}),
|
|
@@ -53,7 +54,7 @@ vi.mock('$lib/crawler', () => ({
|
|
|
53
54
|
}))
|
|
54
55
|
|
|
55
56
|
vi.mock('$lib/url', () => ({
|
|
56
|
-
getFullUrlPath: ()
|
|
57
|
+
getFullUrlPath: vi.fn(),
|
|
57
58
|
}))
|
|
58
59
|
|
|
59
60
|
describe('$routes/+page.svelte', () => {
|
|
@@ -61,6 +62,7 @@ describe('$routes/+page.svelte', () => {
|
|
|
61
62
|
document.body.innerHTML = ''
|
|
62
63
|
vi.resetAllMocks()
|
|
63
64
|
vi.mocked(injectLinksInDocument).mockReturnValue([])
|
|
65
|
+
vi.mocked(getFullUrlPath).mockReturnValue('/test')
|
|
64
66
|
})
|
|
65
67
|
|
|
66
68
|
afterEach(() => {
|
|
@@ -340,6 +342,22 @@ describe('$routes/+page.svelte', () => {
|
|
|
340
342
|
expect(pollLinkInjections).not.toHaveBeenCalled()
|
|
341
343
|
})
|
|
342
344
|
|
|
345
|
+
it('Should log error if error occurs during injection', async () => {
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
vi.mocked(pollLinkInjections).mockResolvedValueOnce({ ai_injections: [], link_injections: [] })
|
|
348
|
+
vi.mocked(injectLinksInDocument).mockImplementationOnce(() => {
|
|
349
|
+
throw new Error('Some error')
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
render(page)
|
|
353
|
+
|
|
354
|
+
await new Promise(res => setTimeout(res)) // Await potential fetches
|
|
355
|
+
|
|
356
|
+
await waitFor(() => {
|
|
357
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionError, null, { message: 'Some error' })
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
343
361
|
describe('Config', () => {
|
|
344
362
|
describe('exclude_urls_pattern', () => {
|
|
345
363
|
it('Should not inject if config exclude_urls_pattern matches current url', async () => {
|
|
@@ -351,7 +369,7 @@ describe('$routes/+page.svelte', () => {
|
|
|
351
369
|
expect(pollLinkInjections).not.toHaveBeenCalled()
|
|
352
370
|
})
|
|
353
371
|
|
|
354
|
-
it('Should not inject if config exclude_urls_pattern matches current url with
|
|
372
|
+
it('Should not inject if config exclude_urls_pattern matches current url with regex pattern', async () => {
|
|
355
373
|
vi.mocked(fetchConfig).mockResolvedValueOnce({ exclude_urls_pattern: '^/test$' })
|
|
356
374
|
|
|
357
375
|
render(page)
|
|
@@ -360,6 +378,17 @@ describe('$routes/+page.svelte', () => {
|
|
|
360
378
|
expect(pollLinkInjections).not.toHaveBeenCalled()
|
|
361
379
|
})
|
|
362
380
|
|
|
381
|
+
// Real example from DigitalSpy
|
|
382
|
+
it('Should not inject if config exclude_urls_pattern matches current url with more complex regex pattern', async () => {
|
|
383
|
+
vi.mocked(getFullUrlPath).mockReturnValueOnce('https://www.digitalspy.com/soaps/coronation-street/a65476444/coronation-street-james-bailey-exit-dee-dee')
|
|
384
|
+
vi.mocked(fetchConfig).mockResolvedValueOnce({ exclude_urls_pattern: 'preview/|^(?!.*/(movies|tv)/).*' })
|
|
385
|
+
|
|
386
|
+
render(page)
|
|
387
|
+
|
|
388
|
+
await waitFor(() => expect(fetchConfig).toHaveBeenCalled())
|
|
389
|
+
expect(pollLinkInjections).not.toHaveBeenCalled()
|
|
390
|
+
})
|
|
391
|
+
|
|
363
392
|
it('Should not inject if config returns an error', async () => {
|
|
364
393
|
vi.mocked(fetchConfig).mockRejectedValueOnce('null')
|
|
365
394
|
|
|
@@ -38,6 +38,13 @@ describe('AIIndicator.svelte', () => {
|
|
|
38
38
|
expect(getByText('25%')).toBeTruthy()
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
+
it('Should floor the percentage label if a decimal is given', () => {
|
|
42
|
+
const { getByText, getByTestId } = render(AIIndicator, { aiRunning: true, automationEnabled: true, percentage: 25.55 })
|
|
43
|
+
|
|
44
|
+
expect(getByTestId('loading-bar').style.width).toBe('25.55%')
|
|
45
|
+
expect(getByText('25%')).toBeTruthy()
|
|
46
|
+
})
|
|
47
|
+
|
|
41
48
|
it('Should limit progress to minimum value in loading bar style only', () => {
|
|
42
49
|
const { getByText, getByTestId } = render(AIIndicator, { aiRunning: true, automationEnabled: true, percentage: 0 })
|
|
43
50
|
|
|
@@ -21,4 +21,16 @@ describe('Alert.svelte', () => {
|
|
|
21
21
|
|
|
22
22
|
expect(container.querySelector('.alert')?.classList).toContain('warning')
|
|
23
23
|
})
|
|
24
|
+
|
|
25
|
+
it('Should include fixed class if prop is given', () => {
|
|
26
|
+
const { container } = render(Alert, { children, fixed: true })
|
|
27
|
+
|
|
28
|
+
expect(container.querySelector('.alert')?.classList).toContain('fixed')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('Should not include fixed class if prop is not given', () => {
|
|
32
|
+
const { container } = render(Alert, { children })
|
|
33
|
+
|
|
34
|
+
expect(container.querySelector('.alert')?.classList).not.toContain('fixed')
|
|
35
|
+
})
|
|
24
36
|
})
|
|
@@ -165,14 +165,14 @@ describe('EditorItem.svelte', () => {
|
|
|
165
165
|
expect(onremove).toHaveBeenCalled()
|
|
166
166
|
})
|
|
167
167
|
|
|
168
|
-
it('Should display an inactive injection as being so with text and classname',
|
|
168
|
+
it('Should display an inactive injection as being so with text and classname', () => {
|
|
169
169
|
const { getByText, container } = render(EditorItem, { linkInjection: { ...linkInjection, inactive: true } })
|
|
170
170
|
|
|
171
171
|
expect(getByText('Inactive')).toBeTruthy()
|
|
172
172
|
expect(container.querySelector('.inactive')).toBeTruthy()
|
|
173
173
|
})
|
|
174
174
|
|
|
175
|
-
it('Should not display an active injection as being inactive',
|
|
175
|
+
it('Should not display an active injection as being inactive', () => {
|
|
176
176
|
const { queryByText, container } = render(EditorItem, { linkInjection })
|
|
177
177
|
|
|
178
178
|
expect(queryByText('Inactive')).not.toBeTruthy()
|
|
@@ -180,15 +180,24 @@ describe('EditorItem.svelte', () => {
|
|
|
180
180
|
expect(container.querySelector('.inactive')).not.toBeTruthy()
|
|
181
181
|
})
|
|
182
182
|
|
|
183
|
-
it('Should display an icon when playlink types are invalid',
|
|
183
|
+
it('Should display an icon when playlink types are invalid', () => {
|
|
184
184
|
const { getByLabelText } = render(EditorItem, { linkInjection: { ...linkInjection, in_text: false } })
|
|
185
185
|
|
|
186
186
|
expect(getByLabelText('Invalid playlink settings')).toBeTruthy()
|
|
187
187
|
})
|
|
188
188
|
|
|
189
|
-
it('Should not display an icon when playlink types are valid',
|
|
189
|
+
it('Should not display an icon when playlink types are valid', () => {
|
|
190
190
|
const { queryByLabelText } = render(EditorItem, { linkInjection: { ...linkInjection, in_text: true } })
|
|
191
191
|
|
|
192
192
|
expect(queryByLabelText('Invalid playlink settings')).not.toBeTruthy()
|
|
193
193
|
})
|
|
194
|
+
|
|
195
|
+
it('Should mount component when clicking report issue button', async () => {
|
|
196
|
+
const { getByLabelText, getByText } = render(EditorItem, { linkInjection })
|
|
197
|
+
|
|
198
|
+
await fireEvent.click(getByLabelText('More options'))
|
|
199
|
+
await fireEvent.click(getByText('Report issue'))
|
|
200
|
+
|
|
201
|
+
expect(getByText('What would you like to report?')).toBeTruthy()
|
|
202
|
+
})
|
|
194
203
|
})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { fireEvent, render } from '@testing-library/svelte'
|
|
2
|
+
import { describe, expect, it, vi, beforeEach } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import ReportIssueModal from '../../../../routes/components/Editorial/ReportIssueModal.svelte'
|
|
5
|
+
import { track } from '$lib/tracking'
|
|
6
|
+
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
7
|
+
import { generateInjection } from '../../../helpers'
|
|
8
|
+
|
|
9
|
+
vi.mock('$lib/tracking', () => ({
|
|
10
|
+
track: vi.fn(),
|
|
11
|
+
}))
|
|
12
|
+
|
|
13
|
+
describe('ReportIssueModal.svelte', () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
vi.resetAllMocks()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const onclose = vi.fn()
|
|
19
|
+
const linkInjection = generateInjection('a word', 'Some sentence with a word')
|
|
20
|
+
|
|
21
|
+
it('Should enable button after selecting issue', async () => {
|
|
22
|
+
const { getByRole, getAllByRole, getByText } = render(ReportIssueModal, { onclose, linkInjection })
|
|
23
|
+
|
|
24
|
+
expect(/** @type {HTMLButtonElement } */ (getByText('Send report')).disabled).toBeTruthy()
|
|
25
|
+
|
|
26
|
+
await fireEvent.click(getByRole('combobox'))
|
|
27
|
+
await fireEvent.click(getAllByRole('option')[1])
|
|
28
|
+
|
|
29
|
+
expect(/** @type {HTMLButtonElement } */ (getByText('Send report')).disabled).not.toBeTruthy()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('Should submit form when clicked', async () => {
|
|
33
|
+
const { getByRole, getAllByRole, getByText } = render(ReportIssueModal, { onclose, linkInjection })
|
|
34
|
+
|
|
35
|
+
await fireEvent.click(getByRole('combobox'))
|
|
36
|
+
await fireEvent.click(getAllByRole('option')[1])
|
|
37
|
+
await fireEvent.click(getByText('Send report'))
|
|
38
|
+
|
|
39
|
+
expect(track).toHaveBeenCalledWith(
|
|
40
|
+
TrackingEvent.ManualReport,
|
|
41
|
+
linkInjection.title_details,
|
|
42
|
+
{
|
|
43
|
+
report_reason: /** @type {HTMLOptionElement} */ (getAllByRole('option')[1]).value,
|
|
44
|
+
sid: linkInjection.sid,
|
|
45
|
+
title: linkInjection.title,
|
|
46
|
+
sentence: linkInjection.sentence,
|
|
47
|
+
failed: linkInjection.failed?.toString(),
|
|
48
|
+
failed_message: linkInjection.failed_message,
|
|
49
|
+
manual: linkInjection.manual?.toString(),
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
expect(getByText('Report has been sent', { exact: false }))
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('Should not submit form when no reason is selected', async () => {
|
|
57
|
+
const { getByText } = render(ReportIssueModal, { onclose, linkInjection })
|
|
58
|
+
|
|
59
|
+
await fireEvent.click(getByText('Send report'))
|
|
60
|
+
|
|
61
|
+
expect(track).not.toHaveBeenCalled()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -22,6 +22,7 @@ describe('Playlinks.svelte', () => {
|
|
|
22
22
|
{ name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
23
23
|
{ name: 'Some other playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
24
24
|
]
|
|
25
|
+
// @ts-ignore
|
|
25
26
|
const { getByText } = render(Playlinks, { playlinks, title })
|
|
26
27
|
|
|
27
28
|
expect(getByText('Some playlink')).toBeTruthy()
|
|
@@ -29,7 +30,7 @@ describe('Playlinks.svelte', () => {
|
|
|
29
30
|
})
|
|
30
31
|
|
|
31
32
|
it('Should show empty state when no playlinks were given', () => {
|
|
32
|
-
/** @type {PlaylinkData[]} */
|
|
33
|
+
/** @type {import('$lib/types/playlink').PlaylinkData[]} */
|
|
33
34
|
const playlinks = []
|
|
34
35
|
const { container } = render(Playlinks, { playlinks, title })
|
|
35
36
|
|
|
@@ -43,6 +44,7 @@ describe('Playlinks.svelte', () => {
|
|
|
43
44
|
{ name: 'Some rent playlink', logo_url: 'logo', extra_info: { category: 'RENT' } },
|
|
44
45
|
{ name: 'Some other playlink', logo_url: 'logo', extra_info: { category: 'other' } },
|
|
45
46
|
]
|
|
47
|
+
// @ts-ignore
|
|
46
48
|
const { getByText, getAllByText } = render(Playlinks, { playlinks, title })
|
|
47
49
|
|
|
48
50
|
expect(getAllByText('Stream')).toHaveLength(2)
|
|
@@ -55,6 +57,7 @@ describe('Playlinks.svelte', () => {
|
|
|
55
57
|
{ name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
56
58
|
{ name: 'Some other playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
57
59
|
]
|
|
60
|
+
// @ts-ignore
|
|
58
61
|
const { getByText } = render(Playlinks, { playlinks, title })
|
|
59
62
|
|
|
60
63
|
await fireEvent.click(getByText(playlinks[0].name))
|
|
@@ -68,6 +71,7 @@ describe('Playlinks.svelte', () => {
|
|
|
68
71
|
const playlinks = [
|
|
69
72
|
{ name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
70
73
|
]
|
|
74
|
+
// @ts-ignore
|
|
71
75
|
const { getByText } = render(Playlinks, { playlinks, title })
|
|
72
76
|
|
|
73
77
|
await fireEvent.click(getByText(playlinks[0].name))
|
|
@@ -82,20 +86,36 @@ describe('Playlinks.svelte', () => {
|
|
|
82
86
|
{ name: 'Some playlink', logo_url: '', extra_info: { category: 'RENT' } },
|
|
83
87
|
{ name: 'Some playlink', logo_url: null, extra_info: { category: 'other' } },
|
|
84
88
|
]
|
|
89
|
+
// @ts-ignore
|
|
85
90
|
const { getAllByText } = render(Playlinks, { playlinks, title })
|
|
86
91
|
|
|
87
92
|
expect(getAllByText('Some playlink')).toHaveLength(1)
|
|
88
93
|
})
|
|
89
94
|
|
|
90
|
-
it('Should not have list class by default',
|
|
95
|
+
it('Should not have list class by default', () => {
|
|
91
96
|
const { container } = render(Playlinks, { playlinks: [], title })
|
|
92
97
|
|
|
93
98
|
expect(container.querySelector('.list')).not.toBeTruthy()
|
|
94
99
|
})
|
|
95
100
|
|
|
96
|
-
it('Should have list class when prop is given',
|
|
101
|
+
it('Should have list class when prop is given', () => {
|
|
97
102
|
const { container } = render(Playlinks, { playlinks: [], title, list: true })
|
|
98
103
|
|
|
99
104
|
expect(container.querySelector('.list')).toBeTruthy()
|
|
100
105
|
})
|
|
106
|
+
|
|
107
|
+
it('Should highlight and replace category text for playlinks that have highlighted as true', () => {
|
|
108
|
+
const playlinks = [
|
|
109
|
+
{ name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
110
|
+
{ name: 'Some other playlink', logo_url: 'logo', highlighted: true, cta_text: '', extra_info: { category: 'BUY' } },
|
|
111
|
+
{ name: 'Some highlighted playlink', logo_url: 'logo', highlighted: true, cta_text: 'Some CTA', extra_info: { category: 'BUY' } },
|
|
112
|
+
]
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
const { getByText } = render(Playlinks, { playlinks, title })
|
|
115
|
+
|
|
116
|
+
expect(getByText('Some playlink').closest('.playlink')?.classList).not.toContain('highlighted')
|
|
117
|
+
expect(getByText('Some other playlink').closest('.playlink')?.classList).not.toContain('highlighted')
|
|
118
|
+
expect(getByText('Some highlighted playlink').closest('.playlink')?.classList).toContain('highlighted')
|
|
119
|
+
expect(getByText('Some CTA')).toBeTruthy()
|
|
120
|
+
})
|
|
101
121
|
})
|