@playpilot/tpi 8.10.0 → 8.10.2
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/.env +1 -1
- package/dist/editorial.mount.js +9 -9
- package/dist/link-injections.js +1 -1
- package/dist/mount.js +6 -6
- package/package.json +1 -1
- package/src/lib/api/youtubeAvailability.ts +3 -4
- package/src/lib/enums/TrackingEvent.ts +4 -4
- package/src/lib/fakeData.ts +44 -32
- package/src/lib/injection.ts +10 -17
- package/src/lib/modal.ts +3 -1
- package/src/lib/popover.ts +13 -12
- package/src/lib/types/injection.d.ts +5 -0
- package/src/routes/components/Editorial/Editor.svelte +2 -3
- package/src/routes/components/Editorial/EditorItem.svelte +23 -9
- package/src/routes/components/Editorial/ManualInjection.svelte +1 -0
- package/src/routes/components/{TitlePopover.svelte → InjectionPopover.svelte} +26 -9
- package/src/routes/components/ListTitle.svelte +27 -6
- package/src/routes/components/Participant.svelte +18 -6
- package/src/routes/components/Playlinks/Playlinks.svelte +2 -1
- package/src/routes/components/Title.svelte +1 -1
- package/src/routes/components/TrackAnyClick.svelte +15 -2
- package/src/routes/components/YouTubeEmbed.svelte +1 -1
- package/src/routes/elements/+page.svelte +3 -3
- package/src/tests/helpers.js +1 -0
- package/src/tests/lib/api/youtubeAvailability.test.js +3 -3
- package/src/tests/lib/injection.test.js +44 -3
- package/src/tests/lib/popover.test.js +7 -7
- package/src/tests/routes/components/Editorial/EditorItem.test.js +10 -0
- package/src/tests/routes/components/Editorial/ManualInjection.test.js +4 -0
- package/src/tests/routes/components/Editorial/PlaylinkTypeSelect.test.js +2 -0
- package/src/tests/routes/components/InjectionPopover.test.js +117 -0
- package/src/tests/routes/components/ListTitle.test.js +7 -0
- package/src/tests/routes/components/Participant.test.js +7 -0
- package/src/tests/routes/components/Playlinks/AfterArticlePlaylinks.test.js +4 -0
- package/src/tests/routes/components/Playlinks/Playlinks.test.js +1 -1
- package/src/tests/routes/components/TrackAnyClick.test.js +137 -1
- package/src/tests/routes/components/TitlePopover.test.js +0 -78
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<TitlePoster {title} onload={() => posterLoaded = true} lazy={false} />
|
|
56
56
|
</div>
|
|
57
57
|
|
|
58
|
-
<div class="heading" use:heading={2} class:truncate={small} id="
|
|
58
|
+
<div class="heading" use:heading={2} class:truncate={small} id="heading">{title.title}</div>
|
|
59
59
|
|
|
60
60
|
<div class="info">
|
|
61
61
|
<div class="imdb">
|
|
@@ -18,8 +18,17 @@
|
|
|
18
18
|
const targetSelector = `${target?.nodeName.toLowerCase()}${getClasslistAsString(target)}`
|
|
19
19
|
const selector = `${parentSelector} > ${targetSelector}`
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
const
|
|
21
|
+
const closestButtonOrLink = target.closest('a, button')
|
|
22
|
+
const directTextNode =
|
|
23
|
+
elementHasDirectTextContent(target) ||
|
|
24
|
+
elementHasDirectTextContent(parent) ||
|
|
25
|
+
(closestButtonOrLink && elementHasDirectTextContent(closestButtonOrLink))
|
|
26
|
+
|
|
27
|
+
const textContent = directTextNode ? directTextNode.textContent?.slice(0, 30) : ''
|
|
28
|
+
const label = target.getAttribute('aria-label') || closestButtonOrLink?.getAttribute('aria-label') || parent?.getAttribute('aria-label')
|
|
29
|
+
const placeholder = (target as HTMLInputElement).placeholder
|
|
30
|
+
const alt = (target as HTMLImageElement).alt
|
|
31
|
+
const text = (textContent || label || placeholder || alt || '').trim()
|
|
23
32
|
|
|
24
33
|
track(trackingEvent, null, { selector, text })
|
|
25
34
|
}
|
|
@@ -33,6 +42,10 @@
|
|
|
33
42
|
|
|
34
43
|
return '.' + classnames.join('.')
|
|
35
44
|
}
|
|
45
|
+
|
|
46
|
+
function elementHasDirectTextContent(element: Element): Node | undefined {
|
|
47
|
+
return Array.from(element.childNodes).find(node => node.nodeName === '#text' && !!node.textContent?.trim())
|
|
48
|
+
}
|
|
36
49
|
</script>
|
|
37
50
|
|
|
38
51
|
<svelte:window {onclick} />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import RoundButton from '../components/RoundButton.svelte'
|
|
17
17
|
import SkeletonText from '../components/SkeletonText.svelte'
|
|
18
18
|
import Title from '../components/Title.svelte'
|
|
19
|
-
import
|
|
19
|
+
import InjectionPopover from '../components/InjectionPopover.svelte'
|
|
20
20
|
import Tooltip from '../components/Tooltip.svelte'
|
|
21
21
|
import ExploreRouter from '../components/Explore/ExploreRouter.svelte'
|
|
22
22
|
import TitlesRail from '../components/Rails/TitlesRail.svelte'
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
</div>
|
|
70
70
|
|
|
71
71
|
<div>
|
|
72
|
-
<h3>
|
|
72
|
+
<h3>InjectionPopover.svelte</h3>
|
|
73
73
|
<div class="item">
|
|
74
74
|
<div style:height="500px"></div>
|
|
75
|
-
<
|
|
75
|
+
<InjectionPopover data={title} event={{} as MouseEvent} />
|
|
76
76
|
</div>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
package/src/tests/helpers.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
import { isYouTubeVideoAvailableInRegion } from '$lib/api/youtubeAvailability'
|
|
3
3
|
import { fakeFetch } from '../../helpers'
|
|
4
|
-
import { track } from '$lib/tracking'
|
|
5
|
-
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
6
4
|
|
|
7
5
|
vi.mock('$lib/tracking', () => ({
|
|
8
6
|
track: vi.fn(),
|
|
@@ -64,7 +62,9 @@ describe('youtubeAvailability', () => {
|
|
|
64
62
|
fakeFetch({ ok: false, status: 500 })
|
|
65
63
|
|
|
66
64
|
expect(await isYouTubeVideoAvailableInRegion('video-id')).toBe(false)
|
|
67
|
-
|
|
65
|
+
|
|
66
|
+
// For now it's silently failing on purpose
|
|
67
|
+
// expect(track).toHaveBeenCalledWith(TrackingEvent.YouTubeAvailabilityRequestFailed, null, { message: expect.any(String) })
|
|
68
68
|
})
|
|
69
69
|
})
|
|
70
70
|
})
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { fireEvent } from '@testing-library/svelte'
|
|
2
2
|
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
|
|
3
3
|
|
|
4
|
-
import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType, removePlayPilotTitleLinks } from '$lib/injection'
|
|
4
|
+
import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType, removePlayPilotTitleLinks, hasValidTypeData } from '$lib/injection'
|
|
5
5
|
import { mount, unmount } from 'svelte'
|
|
6
6
|
import { fakeFetch, generateInjection } from '../helpers'
|
|
7
7
|
import { openModalForInjectedLink } from '$lib/modal'
|
|
8
8
|
import { getLinkInjectionElements } from '$lib/injectionElements'
|
|
9
|
+
import { participants } from '$lib/fakeData'
|
|
9
10
|
|
|
10
11
|
vi.mock('svelte', () => ({
|
|
11
12
|
mount: vi.fn(),
|
|
@@ -568,7 +569,7 @@ describe('injection.ts', () => {
|
|
|
568
569
|
})
|
|
569
570
|
|
|
570
571
|
it('Should remove all popovers that may not have been removed properly in previous destroy attempts', async () => {
|
|
571
|
-
document.body.innerHTML = '<div data-playpilot-
|
|
572
|
+
document.body.innerHTML = '<div data-playpilot-injection-popover></div> <p>This is a sentence with an injection.</p>'
|
|
572
573
|
|
|
573
574
|
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
574
575
|
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
@@ -583,7 +584,7 @@ describe('injection.ts', () => {
|
|
|
583
584
|
await fireEvent.mouseMove(document.body)
|
|
584
585
|
vi.advanceTimersByTime(200)
|
|
585
586
|
|
|
586
|
-
expect(document.querySelectorAll('[data-playpilot-
|
|
587
|
+
expect(document.querySelectorAll('[data-playpilot-injection-popover]')).toHaveLength(0)
|
|
587
588
|
})
|
|
588
589
|
|
|
589
590
|
it('Should inject links of the same phrase when multiple are present', () => {
|
|
@@ -946,6 +947,20 @@ describe('injection.ts', () => {
|
|
|
946
947
|
|
|
947
948
|
expect(document.querySelector('a')?.closest('[data-playpilot-injection-key]')).toBeTruthy()
|
|
948
949
|
})
|
|
950
|
+
|
|
951
|
+
describe('Participants', () => {
|
|
952
|
+
it('Should inject participants just as a title', () => {
|
|
953
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
954
|
+
|
|
955
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
956
|
+
const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: participants[0] }
|
|
957
|
+
|
|
958
|
+
// @ts-ignore
|
|
959
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
960
|
+
|
|
961
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
962
|
+
})
|
|
963
|
+
})
|
|
949
964
|
})
|
|
950
965
|
|
|
951
966
|
describe('clearLinkInjections', () => {
|
|
@@ -1127,6 +1142,32 @@ describe('injection.ts', () => {
|
|
|
1127
1142
|
})
|
|
1128
1143
|
})
|
|
1129
1144
|
|
|
1145
|
+
describe('hasValidTypeData', () => {
|
|
1146
|
+
it('Should return true if injection has type title and has title_details', () => {
|
|
1147
|
+
// @ts-ignore
|
|
1148
|
+
expect(hasValidTypeData({ type: 'title', title_details: {} })).toBe(true)
|
|
1149
|
+
})
|
|
1150
|
+
|
|
1151
|
+
it('Should return true if injection has type participant and has participant_details', () => {
|
|
1152
|
+
// @ts-ignore
|
|
1153
|
+
expect(hasValidTypeData({ type: 'participant', participant_details: {} })).toBe(true)
|
|
1154
|
+
})
|
|
1155
|
+
|
|
1156
|
+
it('Should return false if injection has type title but has no title_details', () => {
|
|
1157
|
+
// @ts-ignore
|
|
1158
|
+
expect(hasValidTypeData({ type: 'title', title_details: null })).toBe(false)
|
|
1159
|
+
// @ts-ignore
|
|
1160
|
+
expect(hasValidTypeData({ type: 'title' })).toBe(false)
|
|
1161
|
+
})
|
|
1162
|
+
|
|
1163
|
+
it('Should return false if injection has type participant but has no participant_details', () => {
|
|
1164
|
+
// @ts-ignore
|
|
1165
|
+
expect(hasValidTypeData({ type: 'participant', participant_details: null })).toBe(false)
|
|
1166
|
+
// @ts-ignore
|
|
1167
|
+
expect(hasValidTypeData({ type: 'participant' })).toBe(false)
|
|
1168
|
+
})
|
|
1169
|
+
})
|
|
1170
|
+
|
|
1130
1171
|
describe('removePlayPilotTitleLinks', () => {
|
|
1131
1172
|
it('Should remove existing title links', () => {
|
|
1132
1173
|
document.body.innerHTML = `
|
|
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
|
2
2
|
import { linkInjections } from '$lib/fakeData'
|
|
3
3
|
import { mount, unmount } from 'svelte'
|
|
4
4
|
import { clearCurrentlyHoveredInjection, currentlyHoveredInjection, destroyLinkPopover, isPopoverActive, openPopoverForInjectedLink } from '$lib/popover'
|
|
5
|
-
import
|
|
5
|
+
import InjectionPopover from '../../routes/components/InjectionPopover.svelte'
|
|
6
6
|
import { waitFor } from '@testing-library/svelte'
|
|
7
7
|
|
|
8
8
|
vi.mock('svelte', () => ({
|
|
@@ -22,17 +22,17 @@ describe('popover.js', () => {
|
|
|
22
22
|
describe('openPopoverForInjectedLink', () => {
|
|
23
23
|
it('Should mount popover', async () => {
|
|
24
24
|
// @ts-ignore
|
|
25
|
-
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections)
|
|
25
|
+
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections[0])
|
|
26
26
|
|
|
27
27
|
await waitFor(() => {
|
|
28
|
-
expect(mount).toHaveBeenCalledWith(
|
|
28
|
+
expect(mount).toHaveBeenCalledWith(InjectionPopover, expect.any(Object))
|
|
29
29
|
expect(currentlyHoveredInjection).toBeTruthy()
|
|
30
30
|
})
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
it('Should not mount popover if user is no longer hovering after delay', async () => {
|
|
34
34
|
// @ts-ignore
|
|
35
|
-
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections)
|
|
35
|
+
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections[0])
|
|
36
36
|
|
|
37
37
|
await new Promise(res => setTimeout(res, 50))
|
|
38
38
|
|
|
@@ -46,19 +46,19 @@ describe('popover.js', () => {
|
|
|
46
46
|
|
|
47
47
|
describe('destroyLinkPopover', () => {
|
|
48
48
|
it('Should not call unmount but still remove potential popover elements if no active popover is set', async () => {
|
|
49
|
-
document.body.innerHTML = '<div data-playpilot-
|
|
49
|
+
document.body.innerHTML = '<div data-playpilot-injection-popover></div> <div data-playpilot-injection-popover></div>'
|
|
50
50
|
|
|
51
51
|
destroyLinkPopover()
|
|
52
52
|
|
|
53
53
|
expect(unmount).not.toHaveBeenCalled()
|
|
54
|
-
expect(document.querySelectorAll('[data-playpilot-
|
|
54
|
+
expect(document.querySelectorAll('[data-playpilot-injection-popover]')).toHaveLength(0)
|
|
55
55
|
})
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
describe('clearCurrentlyHoveredInjection', () => {
|
|
59
59
|
it('Should clear currentlyHoveredInjection', async () => {
|
|
60
60
|
// @ts-ignore
|
|
61
|
-
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections)
|
|
61
|
+
openPopoverForInjectedLink({ currentTarget: document.querySelector('a') }, linkInjections[0])
|
|
62
62
|
|
|
63
63
|
await waitFor(() => expect(currentlyHoveredInjection).toBeTruthy())
|
|
64
64
|
|
|
@@ -6,6 +6,7 @@ import { injectLinksInDocument } from '$lib/injection'
|
|
|
6
6
|
import { track } from '$lib/tracking'
|
|
7
7
|
import { generateInjection } from '../../../helpers'
|
|
8
8
|
import { removeImageUrlPrefix } from '$lib/image'
|
|
9
|
+
import { linkInjections as fakeLinkInjections } from '$lib/fakeData'
|
|
9
10
|
|
|
10
11
|
vi.mock('$lib/tracking', () => ({
|
|
11
12
|
track: vi.fn(),
|
|
@@ -200,4 +201,13 @@ describe('EditorItem.svelte', () => {
|
|
|
200
201
|
|
|
201
202
|
expect(getByText('What would you like to report?')).toBeTruthy()
|
|
202
203
|
})
|
|
204
|
+
|
|
205
|
+
it('Should render as participant when type is participant', () => {
|
|
206
|
+
const { container, queryByLabelText, getByText } = render(EditorItem, { linkInjection: fakeLinkInjections[4] })
|
|
207
|
+
|
|
208
|
+
expect(queryByLabelText('Expand')).not.toBeTruthy()
|
|
209
|
+
expect(getByText(fakeLinkInjections[4].participant_details?.name || '-')).toBeTruthy()
|
|
210
|
+
expect(container.querySelector('.poster')).not.toBeTruthy()
|
|
211
|
+
expect(container.querySelector('.placeholder-image')).toBeTruthy()
|
|
212
|
+
})
|
|
203
213
|
})
|
|
@@ -99,6 +99,7 @@ describe('ManualInjection.svelte', () => {
|
|
|
99
99
|
manual: true,
|
|
100
100
|
phrase_before: 'Some',
|
|
101
101
|
phrase_after: 'in a',
|
|
102
|
+
type: 'title',
|
|
102
103
|
})
|
|
103
104
|
})
|
|
104
105
|
|
|
@@ -141,6 +142,7 @@ describe('ManualInjection.svelte', () => {
|
|
|
141
142
|
manual: true,
|
|
142
143
|
phrase_before: '',
|
|
143
144
|
phrase_after: '',
|
|
145
|
+
type: 'title',
|
|
144
146
|
})
|
|
145
147
|
})
|
|
146
148
|
|
|
@@ -183,6 +185,7 @@ describe('ManualInjection.svelte', () => {
|
|
|
183
185
|
manual: true,
|
|
184
186
|
phrase_before: expect.any(String),
|
|
185
187
|
phrase_after: expect.any(String),
|
|
188
|
+
type: 'title',
|
|
186
189
|
})
|
|
187
190
|
})
|
|
188
191
|
|
|
@@ -225,6 +228,7 @@ describe('ManualInjection.svelte', () => {
|
|
|
225
228
|
manual: true,
|
|
226
229
|
phrase_before: expect.any(String),
|
|
227
230
|
phrase_after: expect.any(String),
|
|
231
|
+
type: 'title',
|
|
228
232
|
})
|
|
229
233
|
})
|
|
230
234
|
|
|
@@ -11,6 +11,8 @@ describe('PlaylinkTypeSelect.svelte', () => {
|
|
|
11
11
|
sentence: 'Some sentence',
|
|
12
12
|
playpilot_url: 'https://playpilot.com/movie/example-3/',
|
|
13
13
|
key: 'some-key',
|
|
14
|
+
/** @type {import('$lib/types/injection').LinkInjectionDataType} */
|
|
15
|
+
type: 'title',
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
beforeEach(() => {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { render } from '@testing-library/svelte'
|
|
2
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import InjectionPopover from '../../../routes/components/InjectionPopover.svelte'
|
|
5
|
+
import { participants, title } from '$lib/fakeData'
|
|
6
|
+
import { track } from '$lib/tracking'
|
|
7
|
+
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
8
|
+
import { hasConsentedTo } from '$lib/consent'
|
|
9
|
+
|
|
10
|
+
vi.mock('$lib/consent', () => ({
|
|
11
|
+
hasConsentedTo: vi.fn(() => true),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
vi.mock('$lib/tracking', () => ({
|
|
15
|
+
track: vi.fn(),
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
vi.mock('$lib/pixel', () => ({
|
|
19
|
+
isPixelAllowed: vi.fn(),
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
vi.mock('$lib/api/participants', () => ({
|
|
23
|
+
fetchParticipantsForTitle: vi.fn(),
|
|
24
|
+
}))
|
|
25
|
+
|
|
26
|
+
vi.mock('$lib/api/titles', () => ({
|
|
27
|
+
fetchSimilarTitles: vi.fn(),
|
|
28
|
+
}))
|
|
29
|
+
|
|
30
|
+
describe('InjectionPopover.svelte', () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.resetAllMocks()
|
|
33
|
+
vi.mocked(hasConsentedTo).mockImplementation(() => true)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
vi.useRealTimers()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('Should render top scroll ad when given', () => {
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
window.PlayPilotLinkInjections = { ads: [{ campaign_format: 'top_scroll', content: {}, cta: {} }] }
|
|
43
|
+
|
|
44
|
+
const event = new MouseEvent('mouseenter')
|
|
45
|
+
const { container } = render(InjectionPopover, { event, type: 'title', data: title })
|
|
46
|
+
|
|
47
|
+
expect(container.querySelector('.top-scroll')).toBeTruthy()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('Should not render top scroll ad when not given', () => {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
window.PlayPilotLinkInjections = { ads: null }
|
|
53
|
+
|
|
54
|
+
const event = new MouseEvent('mouseenter')
|
|
55
|
+
const { container } = render(InjectionPopover, { event, type: 'title', data: title })
|
|
56
|
+
|
|
57
|
+
expect(container.querySelector('.top-scroll')).not.toBeTruthy()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('Title type', () => {
|
|
61
|
+
it('Should render the given title', () => {
|
|
62
|
+
const event = new MouseEvent('mouseenter')
|
|
63
|
+
const { getByText } = render(InjectionPopover, { event, type: 'title', data: title })
|
|
64
|
+
|
|
65
|
+
expect(getByText(title.title)).toBeTruthy()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('Should call track function when rendered', () => {
|
|
69
|
+
const event = new MouseEvent('mouseenter')
|
|
70
|
+
render(InjectionPopover, { event, type: 'title', data: title })
|
|
71
|
+
|
|
72
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionPopoverView, title, { type: 'title' })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('Should call track function with time_spent when destroyed', async () => {
|
|
76
|
+
vi.useFakeTimers()
|
|
77
|
+
|
|
78
|
+
const event = new MouseEvent('mouseenter')
|
|
79
|
+
const { unmount } = render(InjectionPopover, { event, type: 'title', data: title })
|
|
80
|
+
|
|
81
|
+
vi.advanceTimersByTime(200)
|
|
82
|
+
unmount()
|
|
83
|
+
|
|
84
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionPopoverClose, title, expect.objectContaining({ time_spent: 200, type: 'title' }))
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
describe('Participant type', () => {
|
|
89
|
+
const participant = participants[0]
|
|
90
|
+
|
|
91
|
+
it('Should render the given participant', () => {
|
|
92
|
+
const event = new MouseEvent('mouseenter')
|
|
93
|
+
const { getByText } = render(InjectionPopover, { event, type: 'participant', data: participant })
|
|
94
|
+
|
|
95
|
+
expect(getByText(participant.name)).toBeTruthy()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('Should call track function when rendered', () => {
|
|
99
|
+
const event = new MouseEvent('mouseenter')
|
|
100
|
+
render(InjectionPopover, { event, type: 'participant', data: participant })
|
|
101
|
+
|
|
102
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionPopoverView, null, { type: 'participant', participant: participant.name })
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('Should call track function with time_spent when destroyed', async () => {
|
|
106
|
+
vi.useFakeTimers()
|
|
107
|
+
|
|
108
|
+
const event = new MouseEvent('mouseenter')
|
|
109
|
+
const { unmount } = render(InjectionPopover, { event, type: 'participant', data: participant })
|
|
110
|
+
|
|
111
|
+
vi.advanceTimersByTime(200)
|
|
112
|
+
unmount()
|
|
113
|
+
|
|
114
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionPopoverClose, null, expect.objectContaining({ type: 'participant', time_spent: 200, participant: participant.name }))
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -50,6 +50,13 @@ describe('ListTitle.svelte', () => {
|
|
|
50
50
|
expect(onclick).toHaveBeenCalled()
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
+
it('Should render as small variant when given', () => {
|
|
54
|
+
const { container } = render(ListTitle, { title, compact: true })
|
|
55
|
+
|
|
56
|
+
expect(container.querySelector('.compact')).toBeTruthy()
|
|
57
|
+
expect(container.querySelector('.description')).not.toBeTruthy()
|
|
58
|
+
})
|
|
59
|
+
|
|
53
60
|
describe('Playlinks', () => {
|
|
54
61
|
const playlinks = [
|
|
55
62
|
{ name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } },
|
|
@@ -73,4 +73,11 @@ describe('Participant.svelte', () => {
|
|
|
73
73
|
|
|
74
74
|
expect(fetchTitlesForParticipant).toHaveBeenCalledWith(participants[0], { page: 2 })
|
|
75
75
|
})
|
|
76
|
+
|
|
77
|
+
it('Should render as small variant when given', () => {
|
|
78
|
+
const { container, queryByText } = render(Participant, { participant: participants[0], small: true })
|
|
79
|
+
|
|
80
|
+
expect(queryByText('Credits')).not.toBeTruthy()
|
|
81
|
+
expect(container.querySelector('.small')).toBeTruthy()
|
|
82
|
+
})
|
|
76
83
|
})
|
|
@@ -23,6 +23,8 @@ const linkInjections = [{
|
|
|
23
23
|
poster: 'some-poster',
|
|
24
24
|
key: 'some-key-1',
|
|
25
25
|
title_details: title,
|
|
26
|
+
/** @type {import('$lib/types/injection').LinkInjectionDataType} */
|
|
27
|
+
type: 'title',
|
|
26
28
|
}, {
|
|
27
29
|
sid: '2',
|
|
28
30
|
title: 'a sentence',
|
|
@@ -31,6 +33,8 @@ const linkInjections = [{
|
|
|
31
33
|
poster: 'some-poster',
|
|
32
34
|
key: 'some-key-1',
|
|
33
35
|
title_details: title,
|
|
36
|
+
/** @type {import('$lib/types/injection').LinkInjectionDataType} */
|
|
37
|
+
type: 'title',
|
|
34
38
|
}]
|
|
35
39
|
|
|
36
40
|
describe('AfterArticlePlaylinks.svelte', () => {
|
|
@@ -85,7 +85,7 @@ describe('Playlinks.svelte', () => {
|
|
|
85
85
|
|
|
86
86
|
await fireEvent.click(getByText(playlinks[0].name))
|
|
87
87
|
|
|
88
|
-
expect(track).toHaveBeenCalledWith(TrackingEvent.
|
|
88
|
+
expect(track).toHaveBeenCalledWith(TrackingEvent.InjectionPopoverPlaylinkClick, title, { playlink: playlinks[0].name })
|
|
89
89
|
})
|
|
90
90
|
|
|
91
91
|
it('Should call track function for modal when clicked inside of modal scope', async () => {
|
|
@@ -42,7 +42,7 @@ describe('TrackAnyClick.svelte', () => {
|
|
|
42
42
|
TrackingEvent.ExploreAnyClick,
|
|
43
43
|
null,
|
|
44
44
|
expect.objectContaining({
|
|
45
|
-
text: 'This is a very long text that
|
|
45
|
+
text: 'This is a very long text that',
|
|
46
46
|
}),
|
|
47
47
|
)
|
|
48
48
|
})
|
|
@@ -104,4 +104,140 @@ describe('TrackAnyClick.svelte', () => {
|
|
|
104
104
|
|
|
105
105
|
expect(track).toHaveBeenCalledWith(TrackingEvent.ExploreAnyClick, null, expect.objectContaining({ selector: 'section > p' }))
|
|
106
106
|
})
|
|
107
|
+
|
|
108
|
+
it('Should select text of closest button', async () => {
|
|
109
|
+
document.body.innerHTML = '<button>Some text <span><em></em></span></button>'
|
|
110
|
+
|
|
111
|
+
render(ClickTracking)
|
|
112
|
+
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
await fireEvent.click(document.querySelector('em'))
|
|
115
|
+
|
|
116
|
+
expect(track).toHaveBeenCalledWith(
|
|
117
|
+
TrackingEvent.ExploreAnyClick,
|
|
118
|
+
null,
|
|
119
|
+
expect.objectContaining({
|
|
120
|
+
text: 'Some text',
|
|
121
|
+
}),
|
|
122
|
+
)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('Should select text of closest link', async () => {
|
|
126
|
+
document.body.innerHTML = '<a href="/">Some text <span><em></em></span></a>'
|
|
127
|
+
|
|
128
|
+
render(ClickTracking)
|
|
129
|
+
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
await fireEvent.click(document.querySelector('em'))
|
|
132
|
+
|
|
133
|
+
expect(track).toHaveBeenCalledWith(
|
|
134
|
+
TrackingEvent.ExploreAnyClick,
|
|
135
|
+
null,
|
|
136
|
+
expect.objectContaining({
|
|
137
|
+
text: 'Some text',
|
|
138
|
+
}),
|
|
139
|
+
)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('Should use placeholder text', async () => {
|
|
143
|
+
document.body.innerHTML = '<input placeholder="Some placeholder" />'
|
|
144
|
+
|
|
145
|
+
render(ClickTracking)
|
|
146
|
+
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
await fireEvent.click(document.querySelector('input'))
|
|
149
|
+
|
|
150
|
+
expect(track).toHaveBeenCalledWith(
|
|
151
|
+
TrackingEvent.ExploreAnyClick,
|
|
152
|
+
null,
|
|
153
|
+
expect.objectContaining({
|
|
154
|
+
text: 'Some placeholder',
|
|
155
|
+
}),
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('Should use alt text', async () => {
|
|
160
|
+
document.body.innerHTML = '<img alt="Some alt text" />'
|
|
161
|
+
|
|
162
|
+
render(ClickTracking)
|
|
163
|
+
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
await fireEvent.click(document.querySelector('img'))
|
|
166
|
+
|
|
167
|
+
expect(track).toHaveBeenCalledWith(
|
|
168
|
+
TrackingEvent.ExploreAnyClick,
|
|
169
|
+
null,
|
|
170
|
+
expect.objectContaining({
|
|
171
|
+
text: 'Some alt text',
|
|
172
|
+
}),
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('Should use aria label', async () => {
|
|
177
|
+
document.body.innerHTML = '<button aria-label="Some aria label"></button>'
|
|
178
|
+
|
|
179
|
+
render(ClickTracking)
|
|
180
|
+
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
await fireEvent.click(document.querySelector('button'))
|
|
183
|
+
|
|
184
|
+
expect(track).toHaveBeenCalledWith(
|
|
185
|
+
TrackingEvent.ExploreAnyClick,
|
|
186
|
+
null,
|
|
187
|
+
expect.objectContaining({
|
|
188
|
+
text: 'Some aria label',
|
|
189
|
+
}),
|
|
190
|
+
)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('Should use parent aria label', async () => {
|
|
194
|
+
document.body.innerHTML = '<button aria-label="Some aria label"><img /></button>'
|
|
195
|
+
|
|
196
|
+
render(ClickTracking)
|
|
197
|
+
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
await fireEvent.click(document.querySelector('img'))
|
|
200
|
+
|
|
201
|
+
expect(track).toHaveBeenCalledWith(
|
|
202
|
+
TrackingEvent.ExploreAnyClick,
|
|
203
|
+
null,
|
|
204
|
+
expect.objectContaining({
|
|
205
|
+
text: 'Some aria label',
|
|
206
|
+
}),
|
|
207
|
+
)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('Should prefer aria label over placeholder and alt text', async () => {
|
|
211
|
+
document.body.innerHTML = '<button aria-label="Some aria label"><img placeholder="Some placeholder" alt="Some alt text" /></button>'
|
|
212
|
+
|
|
213
|
+
render(ClickTracking)
|
|
214
|
+
|
|
215
|
+
// @ts-ignore
|
|
216
|
+
await fireEvent.click(document.querySelector('img'))
|
|
217
|
+
|
|
218
|
+
expect(track).toHaveBeenCalledWith(
|
|
219
|
+
TrackingEvent.ExploreAnyClick,
|
|
220
|
+
null,
|
|
221
|
+
expect.objectContaining({
|
|
222
|
+
text: 'Some aria label',
|
|
223
|
+
}),
|
|
224
|
+
)
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
it('Should prefer text content over aria label, placeholder and alt text', async () => {
|
|
228
|
+
document.body.innerHTML = '<button aria-label="Some aria label">Some text <img placeholder="Some placeholder" alt="Some alt text" /></button>'
|
|
229
|
+
|
|
230
|
+
render(ClickTracking)
|
|
231
|
+
|
|
232
|
+
// @ts-ignore
|
|
233
|
+
await fireEvent.click(document.querySelector('img'))
|
|
234
|
+
|
|
235
|
+
expect(track).toHaveBeenCalledWith(
|
|
236
|
+
TrackingEvent.ExploreAnyClick,
|
|
237
|
+
null,
|
|
238
|
+
expect.objectContaining({
|
|
239
|
+
text: 'Some text',
|
|
240
|
+
}),
|
|
241
|
+
)
|
|
242
|
+
})
|
|
107
243
|
})
|