@playpilot/tpi 6.3.0-beta.5 → 6.4.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 +10 -10
- package/package.json +1 -1
- package/src/lib/enums/SplitTest.ts +5 -0
- package/src/routes/+page.svelte +3 -3
- package/src/routes/components/Explore/Explore.svelte +6 -1
- package/src/routes/components/Explore/Filter/Search.svelte +4 -2
- package/src/routes/components/Modal.svelte +37 -25
- package/src/routes/components/PostersScrollReveal.svelte +29 -2
- package/src/routes/components/SwipeHandle.svelte +17 -8
- package/src/tests/routes/components/Explore/Explore.test.js +22 -1
- package/src/tests/routes/components/PostersScrollReveal.test.js +43 -1
package/package.json
CHANGED
package/src/routes/+page.svelte
CHANGED
|
@@ -73,12 +73,12 @@
|
|
|
73
73
|
|
|
74
74
|
window.PlayPilotLinkInjections.config = config
|
|
75
75
|
|
|
76
|
-
isUrlExcluded = !!(config?.exclude_urls_pattern && url.match(new RegExp(config.exclude_urls_pattern)))
|
|
77
|
-
if (isUrlExcluded) return
|
|
78
|
-
|
|
79
76
|
if (config?.custom_style) insertCustomStyle(config.custom_style || '')
|
|
80
77
|
if (config?.explore_navigation_selector) insertExploreIntoNavigation()
|
|
81
78
|
|
|
79
|
+
isUrlExcluded = !!(config?.exclude_urls_pattern && url.match(new RegExp(config.exclude_urls_pattern)))
|
|
80
|
+
if (isUrlExcluded) return
|
|
81
|
+
|
|
82
82
|
setElements(config?.html_selector || '', config?.exclude_elements_selector || '')
|
|
83
83
|
} catch(error) {
|
|
84
84
|
// We return if the config did not get fetched properly, as we can't determine what should and should
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { heading } from '$lib/actions/heading'
|
|
3
|
+
import { fetchAds } from '$lib/api/ads'
|
|
3
4
|
import { fetchTitles } from '$lib/api/titles'
|
|
4
5
|
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
5
6
|
import { exploreParentSelector } from '$lib/explore'
|
|
@@ -46,7 +47,11 @@
|
|
|
46
47
|
height = element?.closest<HTMLElement>(exploreParentSelector)?.style.height || null
|
|
47
48
|
})
|
|
48
49
|
|
|
49
|
-
onMount(() =>
|
|
50
|
+
onMount(async () => {
|
|
51
|
+
track(TrackingEvent.ExplorePageView)
|
|
52
|
+
|
|
53
|
+
if (!window.PlayPilotLinkInjections.ads?.length) window.PlayPilotLinkInjections.ads = await fetchAds()
|
|
54
|
+
})
|
|
50
55
|
|
|
51
56
|
async function getTitlesForFilter(): Promise<APIPaginatedResult<TitleData>> {
|
|
52
57
|
latestRequestId += 1
|
|
@@ -41,12 +41,14 @@
|
|
|
41
41
|
border: theme(explore-search-border, 0);
|
|
42
42
|
border-radius: theme(exlore-search-border-radius, border-radius);
|
|
43
43
|
background: theme(explore-search-background, content);
|
|
44
|
+
transition: none;
|
|
44
45
|
color: theme(text-color-alt);
|
|
45
|
-
font-size: theme(font-size-
|
|
46
|
+
font-size: theme(font-size-large);
|
|
46
47
|
font-family: theme(font-family);
|
|
47
48
|
|
|
48
49
|
&:focus {
|
|
49
|
-
outline: 1px solid white;
|
|
50
|
+
outline: theme(explore-search-focus-outline, 1px solid white);
|
|
51
|
+
outline-offset: 0;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
&::placeholder {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
let windowWidth = $state(0)
|
|
42
42
|
let modalElement: HTMLElement | null = $state(null)
|
|
43
43
|
let dialogElement: HTMLElement | null = $state(null)
|
|
44
|
+
let closeElement: HTMLElement | null = $state(null)
|
|
44
45
|
let dialogOffset: number = $state(0)
|
|
45
46
|
let hasPreviousModal = $state(false)
|
|
46
|
-
let isTransitioningIn = $state(false)
|
|
47
47
|
|
|
48
48
|
const isMobile = $derived(windowWidth < mobileBreakpoint)
|
|
49
49
|
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
scrollableElement?.scrollTo(0, initialScrollPosition)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
function scaleOrFly(node: Element
|
|
82
|
+
function scaleOrFly(node: Element): TransitionConfig {
|
|
83
83
|
if (prefersReducedMotion.current) return fade(node, { duration: 0 })
|
|
84
84
|
|
|
85
|
-
if (isMobile) return fly(node, { duration: 250,
|
|
85
|
+
if (isMobile) return fly(node, { duration: 250, y: window.innerHeight, opacity: 1 })
|
|
86
86
|
return scale(node, { duration: 150, start: 0.85 })
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -103,6 +103,14 @@
|
|
|
103
103
|
onhashchange={close}
|
|
104
104
|
bind:innerWidth={windowWidth} />
|
|
105
105
|
|
|
106
|
+
{#snippet closeButton()}
|
|
107
|
+
<div class="close {closeButtonStyle}" transition:scaleOrFly|global bind:this={closeElement}>
|
|
108
|
+
<RoundButton onclick={close} aria-label="Close">
|
|
109
|
+
<IconClose />
|
|
110
|
+
</RoundButton>
|
|
111
|
+
</div>
|
|
112
|
+
{/snippet}
|
|
113
|
+
|
|
106
114
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
107
115
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
108
116
|
<div
|
|
@@ -114,38 +122,38 @@
|
|
|
114
122
|
style:--dialog-offset="{dialogOffset}px"
|
|
115
123
|
onclick={closeOnBackdropClick}
|
|
116
124
|
data-testid="modal"
|
|
117
|
-
|
|
125
|
+
in:fade|global={{ duration: 150 }}
|
|
126
|
+
out:fade|global={{ duration: 150, delay: 100 }}
|
|
118
127
|
bind:this={modalElement}
|
|
119
128
|
use:focustrap>
|
|
120
129
|
{#if prepend}
|
|
121
|
-
<div class="prepend" transition:scaleOrFly|global
|
|
130
|
+
<div class="prepend" transition:scaleOrFly|global data-view-transition-new="playpilot-title-extra">
|
|
122
131
|
{@render prepend()}
|
|
123
132
|
</div>
|
|
124
133
|
{/if}
|
|
125
134
|
|
|
126
135
|
{#if bubble}
|
|
127
|
-
<div class="bubble" transition:scaleOrFly|global
|
|
136
|
+
<div class="bubble" transition:scaleOrFly|global data-view-transition-new="playpilot-title-extra">
|
|
128
137
|
{@render bubble()}
|
|
129
138
|
</div>
|
|
130
139
|
{/if}
|
|
131
140
|
|
|
132
141
|
{#if isMobile}
|
|
133
142
|
<div class="swipe-handle" transition:scaleOrFly|global>
|
|
134
|
-
|
|
143
|
+
{#if dialogElement && closeElement}
|
|
144
|
+
<SwipeHandle targets={[dialogElement, closeElement]} onpassed={close} />
|
|
145
|
+
{/if}
|
|
135
146
|
</div>
|
|
136
147
|
{/if}
|
|
137
148
|
|
|
138
149
|
<div
|
|
139
150
|
class="dialog"
|
|
140
|
-
class:transitioning={isTransitioningIn}
|
|
141
151
|
{onscroll}
|
|
142
152
|
bind:this={dialogElement}
|
|
143
153
|
role="dialog"
|
|
144
154
|
aria-labelledby="title"
|
|
145
155
|
data-view-transition-new="playpilot-title-content"
|
|
146
|
-
|
|
147
|
-
onintroend={() => isTransitioningIn = false}
|
|
148
|
-
transition:scaleOrFly|global={{ y: window.innerHeight }}>
|
|
156
|
+
transition:scaleOrFly|global>
|
|
149
157
|
{#if hasPreviousModal}
|
|
150
158
|
<div class="close back {closeButtonStyle}">
|
|
151
159
|
<RoundButton onclick={() => goBackToPreviousModal()} aria-label="Back">
|
|
@@ -154,14 +162,16 @@
|
|
|
154
162
|
</div>
|
|
155
163
|
{/if}
|
|
156
164
|
|
|
157
|
-
<div class="close {closeButtonStyle}">
|
|
158
|
-
<RoundButton onclick={close} aria-label="Close">
|
|
159
|
-
<IconClose />
|
|
160
|
-
</RoundButton>
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
165
|
{@render children()}
|
|
166
|
+
|
|
167
|
+
{#if !isMobile}
|
|
168
|
+
{@render closeButton()}
|
|
169
|
+
{/if}
|
|
164
170
|
</div>
|
|
171
|
+
|
|
172
|
+
{#if isMobile}
|
|
173
|
+
{@render closeButton()}
|
|
174
|
+
{/if}
|
|
165
175
|
</div>
|
|
166
176
|
|
|
167
177
|
<style lang="scss">
|
|
@@ -174,7 +184,6 @@
|
|
|
174
184
|
flex-direction: column;
|
|
175
185
|
justify-content: flex-start;
|
|
176
186
|
align-items: center;
|
|
177
|
-
overflow: auto;
|
|
178
187
|
top: 0;
|
|
179
188
|
right: 0;
|
|
180
189
|
bottom: 0;
|
|
@@ -182,6 +191,8 @@
|
|
|
182
191
|
background: theme(detail-backdrop, rgba(0, 0, 0, 0.65));
|
|
183
192
|
|
|
184
193
|
@include desktop() {
|
|
194
|
+
overflow: auto;
|
|
195
|
+
overscroll-behavior: contain;
|
|
185
196
|
padding: margin(2) 0;
|
|
186
197
|
}
|
|
187
198
|
|
|
@@ -208,9 +219,11 @@
|
|
|
208
219
|
margin-top: auto;
|
|
209
220
|
padding-bottom: env(safe-area-inset-bottom);
|
|
210
221
|
overflow: auto;
|
|
222
|
+
overscroll-behavior: contain;
|
|
211
223
|
border-radius: theme(detail-border-radius, margin(1) margin(1) 0 0);
|
|
212
224
|
background: theme(detail-background, light);
|
|
213
|
-
|
|
225
|
+
will-change: top;
|
|
226
|
+
transition: top 200ms;
|
|
214
227
|
|
|
215
228
|
@supports (height: 1dvh) {
|
|
216
229
|
height: 80dvh;
|
|
@@ -218,7 +231,7 @@
|
|
|
218
231
|
|
|
219
232
|
@include desktop() {
|
|
220
233
|
height: unset;
|
|
221
|
-
margin
|
|
234
|
+
margin: auto 0;
|
|
222
235
|
padding-bottom: 0;
|
|
223
236
|
overflow: visible;
|
|
224
237
|
border-radius: theme(detail-border-radius, border-radius-large);
|
|
@@ -262,11 +275,14 @@
|
|
|
262
275
|
--playpilot-button-text-color: #{theme(modal-close-button-text-color, text-color-alt)};
|
|
263
276
|
z-index: 5;
|
|
264
277
|
position: fixed;
|
|
265
|
-
top: calc(var(--dialog-offset) + margin(1));
|
|
278
|
+
margin-top: calc(var(--dialog-offset) + margin(1));
|
|
279
|
+
top: 0;
|
|
266
280
|
right: margin(1);
|
|
281
|
+
transition: top 200ms;
|
|
267
282
|
|
|
268
283
|
@include desktop() {
|
|
269
284
|
position: absolute;
|
|
285
|
+
margin-top: 0;
|
|
270
286
|
top: margin(1);
|
|
271
287
|
}
|
|
272
288
|
|
|
@@ -291,10 +307,6 @@
|
|
|
291
307
|
}
|
|
292
308
|
}
|
|
293
309
|
}
|
|
294
|
-
|
|
295
|
-
.transitioning & {
|
|
296
|
-
top: margin(1);
|
|
297
|
-
}
|
|
298
310
|
}
|
|
299
311
|
|
|
300
312
|
.prepend {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { mobileBreakpoint } from '$lib/constants'
|
|
3
|
+
import { SplitTest } from '$lib/enums/SplitTest'
|
|
4
|
+
import { isInSplitTestVariant, trackSplitTestAction, trackSplitTestView } from '$lib/splitTest'
|
|
2
5
|
import { onMount } from 'svelte'
|
|
3
6
|
|
|
4
7
|
const linksWithPosters = Array.from(document.querySelectorAll<HTMLElement>('[data-playpilot-poster-url]'))
|
|
@@ -6,13 +9,37 @@
|
|
|
6
9
|
const targetThreshold = 0.6
|
|
7
10
|
const posterSelector = '[data-playpilot-poster]'
|
|
8
11
|
|
|
12
|
+
let windowWidth = $state(0)
|
|
9
13
|
let scrollTimeout: ReturnType<typeof setTimeout> | null = null
|
|
10
14
|
|
|
15
|
+
const isMobile = $derived(windowWidth < mobileBreakpoint)
|
|
16
|
+
|
|
11
17
|
onMount(() => {
|
|
18
|
+
if (!isMobile) return
|
|
19
|
+
|
|
20
|
+
trackSplitTestView(SplitTest.PostersScrollReveal)
|
|
21
|
+
|
|
12
22
|
return destroyAllPosters
|
|
13
23
|
})
|
|
14
24
|
|
|
25
|
+
$effect(() => {
|
|
26
|
+
if (!isMobile) return
|
|
27
|
+
if (!isInSplitTestVariant(SplitTest.PostersScrollReveal)) return
|
|
28
|
+
if (!linksWithPosters.length) return
|
|
29
|
+
|
|
30
|
+
const onclick = () => trackSplitTestAction(SplitTest.PostersScrollReveal, 'click')
|
|
31
|
+
|
|
32
|
+
for(const link of linksWithPosters) link.addEventListener('click', onclick)
|
|
33
|
+
|
|
34
|
+
return () => {
|
|
35
|
+
for(const link of linksWithPosters) link.removeEventListener('click', onclick)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
15
39
|
function onscroll(): void {
|
|
40
|
+
if (!isMobile) return
|
|
41
|
+
if (!isInSplitTestVariant(SplitTest.PostersScrollReveal)) return
|
|
42
|
+
|
|
16
43
|
setScrollTimeout()
|
|
17
44
|
|
|
18
45
|
const windowHeight = window.innerHeight
|
|
@@ -82,8 +109,8 @@
|
|
|
82
109
|
destroyPosterForLink(link)
|
|
83
110
|
linksWithCurrentlyVisiblePosters.delete(link)
|
|
84
111
|
}
|
|
85
|
-
},
|
|
112
|
+
}, 500)
|
|
86
113
|
}
|
|
87
114
|
</script>
|
|
88
115
|
|
|
89
|
-
<svelte:window {onscroll} />
|
|
116
|
+
<svelte:window {onscroll} bind:innerWidth={windowWidth} />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
targets: HTMLElement[]
|
|
4
4
|
threshold?: number
|
|
5
5
|
isDragging?: boolean
|
|
6
6
|
passedThreshold?: boolean
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
let {
|
|
11
|
-
|
|
11
|
+
targets,
|
|
12
12
|
threshold = 100,
|
|
13
13
|
isDragging = $bindable(false),
|
|
14
14
|
passedThreshold = $bindable(false),
|
|
@@ -28,28 +28,33 @@
|
|
|
28
28
|
|
|
29
29
|
export function start(event: TouchEvent): void {
|
|
30
30
|
if (!event) return
|
|
31
|
-
if (!target) return
|
|
32
31
|
|
|
33
32
|
isDragging = true
|
|
34
33
|
hasBeenDragged = true
|
|
35
34
|
|
|
36
35
|
movementStartY = event.touches[0].pageY
|
|
37
|
-
|
|
36
|
+
|
|
37
|
+
for (const target of targets) {
|
|
38
|
+
target.style.transitionDuration = '0ms'
|
|
39
|
+
}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export function move(event: TouchEvent): void {
|
|
41
43
|
if (!event) return
|
|
42
|
-
if (!target) return
|
|
43
44
|
if (!isDragging) return
|
|
44
45
|
|
|
46
|
+
event.preventDefault()
|
|
47
|
+
|
|
45
48
|
movementCurrentY = event.touches[0].pageY
|
|
46
49
|
|
|
47
|
-
target.style.transform = `translateY(${difference}px)`
|
|
48
50
|
handleElement!.style.transform = `translateY(${difference}px)`
|
|
51
|
+
|
|
52
|
+
for (const target of targets) {
|
|
53
|
+
target.style.top = `${difference}px`
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
export function end(): void {
|
|
52
|
-
if (!target) return
|
|
53
58
|
if (!isDragging) return
|
|
54
59
|
|
|
55
60
|
isDragging = false
|
|
@@ -57,8 +62,12 @@
|
|
|
57
62
|
if (passedThreshold) {
|
|
58
63
|
onpassed()
|
|
59
64
|
} else {
|
|
60
|
-
target.removeAttribute('style')
|
|
61
65
|
handleElement!.removeAttribute('style')
|
|
66
|
+
|
|
67
|
+
for (const target of targets) {
|
|
68
|
+
target.style.removeProperty('transition')
|
|
69
|
+
requestAnimationFrame(() => target.style.top = '0px')
|
|
70
|
+
}
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
movementStartY = 0
|
|
@@ -6,6 +6,7 @@ import { fetchTitles } from '$lib/api/titles'
|
|
|
6
6
|
import { title } from '$lib/fakeData'
|
|
7
7
|
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
8
8
|
import { track } from '$lib/tracking'
|
|
9
|
+
import { fetchAds } from '$lib/api/ads'
|
|
9
10
|
|
|
10
11
|
vi.mock('$lib/api/titles', () => ({
|
|
11
12
|
fetchTitles: vi.fn(),
|
|
@@ -19,8 +20,15 @@ vi.mock('$lib/tracking', () => ({
|
|
|
19
20
|
track: vi.fn(),
|
|
20
21
|
}))
|
|
21
22
|
|
|
23
|
+
vi.mock('$lib/api/ads', () => ({
|
|
24
|
+
fetchAds: vi.fn(),
|
|
25
|
+
}))
|
|
26
|
+
|
|
22
27
|
describe('Explore.svelte', () => {
|
|
23
28
|
beforeEach(() => {
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
window.PlayPilotLinkInjections = {}
|
|
31
|
+
|
|
24
32
|
vi.resetAllMocks()
|
|
25
33
|
})
|
|
26
34
|
|
|
@@ -30,10 +38,23 @@ describe('Explore.svelte', () => {
|
|
|
30
38
|
expect(fetchTitles).toHaveBeenCalledWith({ page_size: 24, page: 1 })
|
|
31
39
|
})
|
|
32
40
|
|
|
33
|
-
it('Should call tracking event on mount', () => {
|
|
41
|
+
it('Should call tracking event and fetchAds on mount', () => {
|
|
34
42
|
render(Explore)
|
|
35
43
|
|
|
36
44
|
expect(track).toHaveBeenCalledWith(TrackingEvent.ExplorePageView)
|
|
45
|
+
expect(fetchAds).toHaveBeenCalled()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('Should not call fetchAds on mount if ads are already present', () => {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
window.PlayPilotLinkInjections = {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
ads: ['a'],
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
render(Explore)
|
|
56
|
+
|
|
57
|
+
expect(fetchAds).not.toHaveBeenCalled()
|
|
37
58
|
})
|
|
38
59
|
|
|
39
60
|
it('Should render all returned titles', async () => {
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import { render } from '@testing-library/svelte'
|
|
1
|
+
import { fireEvent, render } from '@testing-library/svelte'
|
|
2
2
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
3
3
|
import PostersScrollReveal from '../../../routes/components/PostersScrollReveal.svelte'
|
|
4
|
+
import { mobileBreakpoint } from '$lib/constants'
|
|
5
|
+
import { isInSplitTestVariant, trackSplitTestAction } from '$lib/splitTest'
|
|
6
|
+
|
|
7
|
+
vi.mock('$lib/splitTest', () => ({
|
|
8
|
+
trackSplitTestView: vi.fn(),
|
|
9
|
+
trackSplitTestAction: vi.fn(),
|
|
10
|
+
isInSplitTestVariant: vi.fn(() => true),
|
|
11
|
+
}))
|
|
4
12
|
|
|
5
13
|
function createPosterLink(top = 0, url = 'poster.jpg') {
|
|
6
14
|
const link = document.createElement('a')
|
|
@@ -22,8 +30,15 @@ describe('FloatingPoster', () => {
|
|
|
22
30
|
writable: true,
|
|
23
31
|
})
|
|
24
32
|
|
|
33
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
34
|
+
value: mobileBreakpoint - 1,
|
|
35
|
+
writable: true,
|
|
36
|
+
})
|
|
37
|
+
|
|
25
38
|
vi.useFakeTimers()
|
|
26
39
|
vi.resetAllMocks()
|
|
40
|
+
|
|
41
|
+
vi.mocked(isInSplitTestVariant).mockReturnValue(true)
|
|
27
42
|
})
|
|
28
43
|
|
|
29
44
|
it('Should create poster when link is in viewport', async () => {
|
|
@@ -38,6 +53,21 @@ describe('FloatingPoster', () => {
|
|
|
38
53
|
expect(poster?.getAttribute('src')).toBe('poster.jpg')
|
|
39
54
|
})
|
|
40
55
|
|
|
56
|
+
it('Should not create posters on desktop when link is in viewport', async () => {
|
|
57
|
+
createPosterLink(500)
|
|
58
|
+
|
|
59
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
60
|
+
value: mobileBreakpoint + 1,
|
|
61
|
+
writable: true,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
render(PostersScrollReveal)
|
|
65
|
+
|
|
66
|
+
window.dispatchEvent(new Event('scroll'))
|
|
67
|
+
|
|
68
|
+
expect(document.querySelector('[data-playpilot-poster]')).not.toBeTruthy()
|
|
69
|
+
})
|
|
70
|
+
|
|
41
71
|
it('Should not create poster when link is below in viewport', async () => {
|
|
42
72
|
createPosterLink(2000)
|
|
43
73
|
|
|
@@ -104,4 +134,16 @@ describe('FloatingPoster', () => {
|
|
|
104
134
|
window.dispatchEvent(new Event('scroll'))
|
|
105
135
|
expect(document.querySelector('[data-playpilot-poster]')).toBeTruthy()
|
|
106
136
|
})
|
|
137
|
+
|
|
138
|
+
it('Should fire split test tracking on click', async () => {
|
|
139
|
+
createPosterLink(500)
|
|
140
|
+
|
|
141
|
+
render(PostersScrollReveal)
|
|
142
|
+
|
|
143
|
+
window.dispatchEvent(new Event('scroll'))
|
|
144
|
+
|
|
145
|
+
await fireEvent.click(/** @type {HTMLElement} */ (document.querySelector('[data-playpilot-poster]')))
|
|
146
|
+
|
|
147
|
+
expect(trackSplitTestAction).toHaveBeenCalled()
|
|
148
|
+
})
|
|
107
149
|
})
|