@playpilot/tpi 5.2.1 → 5.4.0-beta.topscroll-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.
@@ -5,6 +5,7 @@
5
5
  import { onMount } from 'svelte'
6
6
  import Popover from './Popover.svelte'
7
7
  import Title from './Title.svelte'
8
+ import TopScroll from './Ads/TopScroll.svelte'
8
9
 
9
10
  interface Props {
10
11
  event: MouseEvent
@@ -18,7 +19,12 @@
18
19
 
19
20
  track(TrackingEvent.TitlePopoverView, title)
20
21
 
21
- onMount(setOffset)
22
+ onMount(() => {
23
+ setOffset()
24
+
25
+ const openTimestamp = Date.now()
26
+ return () => track(TrackingEvent.TitlePopoverClose, title, { time_spent: Date.now() - openTimestamp })
27
+ })
22
28
 
23
29
  /**
24
30
  * An element can be split up over multiple lines, giving it multiple ClientRects.
@@ -45,6 +51,10 @@
45
51
  <div class="title-popover" bind:this={element} data-playpilot-title-popover role="region" aria-labelledby="title">
46
52
  <Popover bind:maxHeight>
47
53
  <Title {title} small compact={!!maxHeight && maxHeight < 250} />
54
+
55
+ {#snippet bubble()}
56
+ <TopScroll />
57
+ {/snippet}
48
58
  </Popover>
49
59
  </div>
50
60
 
@@ -0,0 +1,99 @@
1
+ import { fireEvent, render, waitFor } from '@testing-library/svelte'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+
4
+ import TopScroll from '../../../../routes/components/Ads/TopScroll.svelte'
5
+ import { track } from '$lib/tracking'
6
+ import { TrackingEvent } from '$lib/enums/TrackingEvent'
7
+
8
+ vi.mock('$lib/tracking', () => ({
9
+ track: vi.fn(),
10
+ }))
11
+
12
+ export const campaign = {
13
+ campaign_format: 'top_scroll',
14
+ campaign_type: 'video',
15
+ campaign_platforms: ['web', 'android_app', 'ios_app'],
16
+ campaign_name: 'some_campaign_NL',
17
+ campaign_start: '2025-04-24T00:00:00Z',
18
+ campaign_end: '2025-04-30T23:59:00Z',
19
+ campaign_region: 'nl',
20
+ content: {
21
+ header: 'Some top scroll header',
22
+ header_logo: 'https://example.com/',
23
+ header_logo_uuid: '4fb7d6ea152111f08dd20a58a9feac02',
24
+ subheader: null,
25
+ image: 'https://example.com/',
26
+ image_uuid: '4fb7d6ea152111f08dd20a58a9feac02',
27
+ video: null,
28
+ format: null,
29
+ },
30
+ cta: {
31
+ header: 'Button Label',
32
+ subheader: null,
33
+ image: null,
34
+ image_uuid: null,
35
+ url: 'https://google.com/',
36
+ },
37
+ content_playlist: null,
38
+ provider: null,
39
+ impression_trackers: [],
40
+ target_title_uuid: null,
41
+ target_title_sid: null,
42
+ backfill_providers: [],
43
+ autogenerated: false,
44
+ enabled: true,
45
+ hide_imdb_score: false,
46
+ hide_sponsored_message: false,
47
+ disclaimer: 'Some disclaimer',
48
+ }
49
+
50
+ describe('TopScroll.svelte', () => {
51
+ it('Should render the given content', () => {
52
+ const { getByText, container } = render(TopScroll, { campaign })
53
+
54
+ expect(getByText(campaign.cta.header)).toBeTruthy()
55
+ expect(getByText(campaign.content.header)).toBeTruthy()
56
+ expect(container.querySelector('.tooltip')).toBeTruthy()
57
+ })
58
+
59
+ it('Should not show disclaimer when not given', async () => {
60
+ const { getByText, container } = render(TopScroll, {
61
+ campaign: { ...campaign, disclaimer: null },
62
+ })
63
+
64
+ await waitFor(() => getByText(campaign.cta.header))
65
+
66
+ expect(container.querySelector('.tooltip')).not.toBeTruthy()
67
+ })
68
+
69
+ it('Should toggle disclaimer on click', async () => {
70
+ const { getByText, container, queryByText } = render(TopScroll, { campaign })
71
+
72
+ await waitFor(() => getByText(campaign.cta.header))
73
+
74
+ await fireEvent.click(/** @type {HTMLElement} */ (container.querySelector('.tooltip')))
75
+ expect(getByText(campaign.disclaimer)).toBeTruthy()
76
+
77
+ await fireEvent.click(/** @type {HTMLElement} */ (container.querySelector('.tooltip')))
78
+ expect(queryByText(campaign.disclaimer)).not.toBeTruthy()
79
+ })
80
+
81
+ it('Should fire track even on click', async () => {
82
+ const { getByRole } = render(TopScroll, { campaign })
83
+
84
+ await fireEvent.click(getByRole('link'))
85
+
86
+ expect(track).toHaveBeenCalledWith(TrackingEvent.TopScrollClick)
87
+ })
88
+
89
+ it('Should render as simple variant when content format is large', async () => {
90
+ const simpleCampaign = { ...campaign, content: { ...campaign.content, format: 'large' } }
91
+ const { queryByText, container } = render(TopScroll, { campaign: simpleCampaign })
92
+
93
+ expect(queryByText(simpleCampaign.content.header)).not.toBeTruthy()
94
+ expect(queryByText(simpleCampaign.cta.header)).not.toBeTruthy()
95
+ expect(container.querySelector('.background')).not.toBeTruthy()
96
+ expect(container.querySelector('.disclaimer')).not.toBeTruthy()
97
+ expect(container.querySelector('.content-image')).toBeTruthy()
98
+ })
99
+ })
@@ -1,5 +1,5 @@
1
1
  import { fireEvent, render } from '@testing-library/svelte'
2
- import { describe, expect, it, vi, beforeEach } from 'vitest'
2
+ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
3
3
 
4
4
  import TitleModal from '../../../routes/components/TitleModal.svelte'
5
5
  import { title } from '$lib/fakeData'
@@ -15,6 +15,10 @@ describe('TitleModal.svelte', () => {
15
15
  vi.resetAllMocks()
16
16
  })
17
17
 
18
+ afterEach(() => {
19
+ vi.useRealTimers()
20
+ })
21
+
18
22
  const onclose = vi.fn()
19
23
 
20
24
  it('Should call track function when rendered', () => {
@@ -30,4 +34,15 @@ describe('TitleModal.svelte', () => {
30
34
 
31
35
  expect(track).toHaveBeenCalledWith(TrackingEvent.TitleModalScroll, title)
32
36
  })
37
+
38
+ it('Should call track function with time_spent when destroyed', async () => {
39
+ vi.useFakeTimers()
40
+
41
+ const { unmount } = render(TitleModal, { onclose, title })
42
+
43
+ vi.advanceTimersByTime(200)
44
+ unmount()
45
+
46
+ expect(track).toHaveBeenCalledWith(TrackingEvent.TitleModalClose, title, { time_spent: 200 })
47
+ })
33
48
  })
@@ -1,5 +1,5 @@
1
1
  import { render } from '@testing-library/svelte'
2
- import { describe, expect, it, vi, beforeEach } from 'vitest'
2
+ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
3
3
 
4
4
  import TitlePopover from '../../../routes/components/TitlePopover.svelte'
5
5
  import { title } from '$lib/fakeData'
@@ -15,10 +15,26 @@ describe('TitlePopover.svelte', () => {
15
15
  vi.resetAllMocks()
16
16
  })
17
17
 
18
+ afterEach(() => {
19
+ vi.useRealTimers()
20
+ })
21
+
18
22
  it('Should call track function when rendered', () => {
19
23
  const event = new MouseEvent('mouseenter')
20
24
  render(TitlePopover, { event, title })
21
25
 
22
26
  expect(track).toHaveBeenCalledWith(TrackingEvent.TitlePopoverView, title)
23
27
  })
28
+
29
+ it('Should call track function with time_spent when destroyed', async () => {
30
+ vi.useFakeTimers()
31
+
32
+ const event = new MouseEvent('mouseenter')
33
+ const { unmount } = render(TitlePopover, { event, title })
34
+
35
+ vi.advanceTimersByTime(200)
36
+ unmount()
37
+
38
+ expect(track).toHaveBeenCalledWith(TrackingEvent.TitlePopoverClose, title, { time_spent: 200 })
39
+ })
24
40
  })