@playpilot/tpi 5.14.0 → 5.16.0

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.
Files changed (59) hide show
  1. package/dist/link-injections.js +10 -9
  2. package/package.json +2 -1
  3. package/src/lib/ads.ts +5 -0
  4. package/src/lib/consent.ts +13 -0
  5. package/src/lib/enums/SplitTest.ts +4 -0
  6. package/src/lib/fakeData.ts +70 -0
  7. package/src/lib/linkInjection.ts +11 -29
  8. package/src/lib/modal.ts +97 -0
  9. package/src/lib/playlink.ts +4 -1
  10. package/src/lib/splitTest.ts +5 -0
  11. package/src/lib/tracking.ts +3 -0
  12. package/src/lib/types/consent.d.ts +9 -0
  13. package/src/lib/types/participant.d.ts +14 -0
  14. package/src/lib/types/script.d.ts +3 -0
  15. package/src/lib/types/title.d.ts +2 -0
  16. package/src/main.ts +21 -1
  17. package/src/routes/+layout.svelte +20 -3
  18. package/src/routes/+page.svelte +14 -10
  19. package/src/routes/components/Consent.svelte +72 -0
  20. package/src/routes/components/Icons/IconArrow.svelte +22 -0
  21. package/src/routes/components/Icons/IconClose.svelte +1 -1
  22. package/src/routes/components/Icons/IconIMDb.svelte +9 -1
  23. package/src/routes/components/ListTitle.svelte +204 -0
  24. package/src/routes/components/Modal.svelte +63 -13
  25. package/src/routes/components/Participant.svelte +92 -0
  26. package/src/routes/components/ParticipantModal.svelte +31 -0
  27. package/src/routes/components/Playlink.svelte +16 -4
  28. package/src/routes/components/PlaylinkIcon.svelte +41 -0
  29. package/src/routes/components/PlaylinkLabel.svelte +37 -0
  30. package/src/routes/components/Playlinks.svelte +1 -3
  31. package/src/routes/components/Rails/ParticipantsRail.svelte +56 -0
  32. package/src/routes/components/Rails/Rail.svelte +91 -0
  33. package/src/routes/components/Rails/SimilarRail.svelte +16 -0
  34. package/src/routes/components/Rails/TitlesRail.svelte +95 -0
  35. package/src/routes/components/Tabs.svelte +47 -0
  36. package/src/routes/components/Title.svelte +19 -16
  37. package/src/routes/components/TitleModal.svelte +3 -3
  38. package/src/routes/components/TitlePoster.svelte +30 -0
  39. package/src/routes/components/TrackingPixels.svelte +7 -3
  40. package/src/tests/lib/ads.test.js +24 -1
  41. package/src/tests/lib/consent.test.js +50 -0
  42. package/src/tests/lib/linkInjection.test.js +10 -22
  43. package/src/tests/lib/modal.test.js +148 -0
  44. package/src/tests/lib/playlink.test.js +25 -10
  45. package/src/tests/lib/splitTest.test.js +30 -6
  46. package/src/tests/lib/tracking.test.js +18 -3
  47. package/src/tests/routes/components/Consent.test.js +69 -0
  48. package/src/tests/routes/components/ListTitle.test.js +84 -0
  49. package/src/tests/routes/components/Modal.test.js +51 -19
  50. package/src/tests/routes/components/Playlink.test.js +22 -1
  51. package/src/tests/routes/components/PlaylinkIcon.test.js +27 -0
  52. package/src/tests/routes/components/PlaylinkLabel.test.js +19 -0
  53. package/src/tests/routes/components/Rails/ParticipantsRail.test.js +41 -0
  54. package/src/tests/routes/components/Rails/TitleRail.test.js +38 -0
  55. package/src/tests/routes/components/TitleModal.test.js +6 -0
  56. package/src/tests/routes/components/TitlePopover.test.js +6 -0
  57. package/src/tests/routes/components/TitlePoster.test.js +20 -0
  58. package/src/tests/routes/components/TrackingPixels.test.js +15 -1
  59. package/src/tests/setup.js +14 -1
@@ -0,0 +1,27 @@
1
+ import { fireEvent, render } from '@testing-library/svelte'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+
4
+ import PlaylinkIcon from '../../../routes/components/PlaylinkIcon.svelte'
5
+
6
+ describe('PlaylinkIcon.svelte', () => {
7
+ const playlink = { name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } }
8
+
9
+ it('Should call given onclick function', async () => {
10
+ const onclick = vi.fn()
11
+
12
+ // @ts-ignore
13
+ const { getByAltText } = render(PlaylinkIcon, { playlink, onclick })
14
+
15
+ await fireEvent.click(getByAltText(playlink.name))
16
+
17
+ expect(onclick).toHaveBeenCalled()
18
+ })
19
+
20
+ it('Should render playlink with given size', () => {
21
+ // @ts-ignore
22
+ const { getByAltText } = render(PlaylinkIcon, { playlink, size: 20 })
23
+
24
+ expect(getByAltText(playlink.name).getAttribute('width')).toBe('20')
25
+ expect(getByAltText(playlink.name).getAttribute('height')).toBe('20')
26
+ })
27
+ })
@@ -0,0 +1,19 @@
1
+ import { fireEvent, render } from '@testing-library/svelte'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+
4
+ import PlaylinkLabel from '../../../routes/components/PlaylinkLabel.svelte'
5
+
6
+ describe('PlaylinkLabel.svelte', () => {
7
+ const playlink = { name: 'Some playlink', logo_url: 'logo', extra_info: { category: 'SVOD' } }
8
+
9
+ it('Should call given onclick function', async () => {
10
+ const onclick = vi.fn()
11
+
12
+ // @ts-ignore
13
+ const { getByText } = render(PlaylinkLabel, { playlink, onclick })
14
+
15
+ await fireEvent.click(getByText(playlink.name))
16
+
17
+ expect(onclick).toHaveBeenCalled()
18
+ })
19
+ })
@@ -0,0 +1,41 @@
1
+ import { fireEvent, render } from '@testing-library/svelte'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+
4
+ import ParticipantsRail from '../../../../routes/components/Rails/ParticipantsRail.svelte'
5
+ import { openModal } from '$lib/modal'
6
+
7
+ vi.mock('$lib/modal', () => ({
8
+ openModal: vi.fn(),
9
+ }))
10
+
11
+ describe('ParticipantsRail.svelte', () => {
12
+ const participants = [
13
+ { name: 'Some name', character: 'Some character' },
14
+ { name: 'Some second name', character: 'Second second character' },
15
+ ]
16
+
17
+ it('Should render each given participant', () => {
18
+ // @ts-ignore
19
+ const { getByText } = render(ParticipantsRail, { participants })
20
+
21
+ expect(getByText('Some name')).toBeTruthy()
22
+ expect(getByText('Some second name')).toBeTruthy()
23
+ })
24
+
25
+ it('Should handle not being given any participants', () => {
26
+ /** @type {import('$lib/types/participant').ParticipantData[]} */
27
+ const participants = []
28
+ const { container } = render(ParticipantsRail, { participants })
29
+
30
+ expect(container.querySelectorAll('.participant').length).toBe(0)
31
+ })
32
+
33
+ it('Should open modal on click of participant', async () => {
34
+ // @ts-ignore
35
+ const { getAllByRole } = render(ParticipantsRail, { participants })
36
+
37
+ await fireEvent.click(getAllByRole('button')[0])
38
+
39
+ expect(openModal).toHaveBeenCalledWith({ event: expect.any(Object), type: 'participant', data: participants[0] })
40
+ })
41
+ })
@@ -0,0 +1,38 @@
1
+ import { fireEvent, render, waitFor } from '@testing-library/svelte'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+
4
+ import TitlesRail from '../../../../routes/components/Rails/TitlesRail.svelte'
5
+ import { title } from '$lib/fakeData'
6
+ import { openModal } from '$lib/modal'
7
+
8
+ vi.mock('$lib/modal', () => ({
9
+ openModal: vi.fn(),
10
+ }))
11
+
12
+ describe('TitlesRail.svelte', () => {
13
+ it('Should show loading state while promise is resolving', async () => {
14
+ // @ts-ignore
15
+ const { queryAllByTestId } = render(TitlesRail, { titles: new Promise(res => setTimeout(res, 100)) })
16
+
17
+ expect(queryAllByTestId('skeleton')).toHaveLength(8)
18
+
19
+ await waitFor(() => {
20
+ expect(queryAllByTestId('skeleton')).toHaveLength(0)
21
+ })
22
+ })
23
+
24
+ it('Should render all titles', async () => {
25
+ const { getAllByTestId, getAllByRole } = render(TitlesRail, { titles: [title, title] })
26
+
27
+ expect(getAllByTestId('title')).toHaveLength(2)
28
+ expect(getAllByRole('link')[0].getAttribute('href')).toBe(`https://www.playpilot.com/series/${title.slug}`)
29
+ })
30
+
31
+ it('Should fire openModal when title is clicked', async () => {
32
+ const { getAllByRole } = render(TitlesRail, { titles: [title] })
33
+
34
+ await fireEvent.click(getAllByRole('link')[0])
35
+
36
+ expect(openModal).toHaveBeenCalledWith({ event: expect.any(Object), data: title })
37
+ })
38
+ })
@@ -5,6 +5,11 @@ import TitleModal from '../../../routes/components/TitleModal.svelte'
5
5
  import { title } from '$lib/fakeData'
6
6
  import { track } from '$lib/tracking'
7
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
+ }))
8
13
 
9
14
  vi.mock('$lib/tracking', () => ({
10
15
  track: vi.fn(),
@@ -13,6 +18,7 @@ vi.mock('$lib/tracking', () => ({
13
18
  describe('TitleModal.svelte', () => {
14
19
  beforeEach(() => {
15
20
  vi.resetAllMocks()
21
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
16
22
  })
17
23
 
18
24
  afterEach(() => {
@@ -5,6 +5,11 @@ import TitlePopover from '../../../routes/components/TitlePopover.svelte'
5
5
  import { title } from '$lib/fakeData'
6
6
  import { track } from '$lib/tracking'
7
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
+ }))
8
13
 
9
14
  vi.mock('$lib/tracking', () => ({
10
15
  track: vi.fn(),
@@ -13,6 +18,7 @@ vi.mock('$lib/tracking', () => ({
13
18
  describe('TitlePopover.svelte', () => {
14
19
  beforeEach(() => {
15
20
  vi.resetAllMocks()
21
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
16
22
  })
17
23
 
18
24
  afterEach(() => {
@@ -0,0 +1,20 @@
1
+ import { render } from '@testing-library/svelte'
2
+ import { describe, expect, it } from 'vitest'
3
+
4
+ import TitlePoster from '../../../routes/components/TitlePoster.svelte'
5
+ import { title } from '$lib/fakeData'
6
+
7
+ describe('Title.svelte', () => {
8
+ it('Should render the given image', () => {
9
+ const { getByAltText } = render(TitlePoster, { title })
10
+
11
+ expect(getByAltText(`Movie poster for '${title.title}'`)).toBeTruthy()
12
+ })
13
+
14
+ it('Should include the given width and height', () => {
15
+ const { getByAltText } = render(TitlePoster, { title, width: 10, height: 20 })
16
+
17
+ expect(getByAltText(`Movie poster for '${title.title}'`).getAttribute('width')).toBe('10')
18
+ expect(getByAltText(`Movie poster for '${title.title}'`).getAttribute('height')).toBe('20')
19
+ })
20
+ })
@@ -1,7 +1,12 @@
1
1
  import { render } from '@testing-library/svelte'
2
- import { describe, expect, it } from 'vitest'
2
+ import { describe, expect, it, vi } from 'vitest'
3
3
 
4
4
  import TrackingPixels from '../../../routes/components/TrackingPixels.svelte'
5
+ import { hasConsentedTo } from '$lib/consent'
6
+
7
+ vi.mock('$lib/consent', () => ({
8
+ hasConsentedTo: vi.fn(() => true),
9
+ }))
5
10
 
6
11
  describe('TrackingPixels.svelte', () => {
7
12
  it('Should render all given pixels', () => {
@@ -12,4 +17,13 @@ describe('TrackingPixels.svelte', () => {
12
17
  expect(/** @type {HTMLImageElement} */ (getAllByRole('presentation')[0]).src).toBe('https://image.com/a.jpg')
13
18
  expect(/** @type {HTMLImageElement} */ (getAllByRole('presentation')[1]).src).toBe('https://image.com/b.jpg')
14
19
  })
20
+
21
+ it('Should not render any pixels when user has not consented', () => {
22
+ vi.mocked(hasConsentedTo).mockImplementation(() => false)
23
+
24
+ const pixels = ['https://image.com/a.jpg', 'https://image.com/b.jpg']
25
+ const { queryByRole } = render(TrackingPixels, { pixels })
26
+
27
+ expect(queryByRole('presentation')).not.toBeTruthy()
28
+ })
15
29
  })
@@ -73,7 +73,20 @@ beforeAll(() => {
73
73
 
74
74
  beforeEach(() => {
75
75
  // @ts-ignore
76
- window.PlayPilotLinkInjections = { token: 'some-token' }
76
+ window.PlayPilotLinkInjections = { token: 'some-token', require_consent: false }
77
+
78
+ // Enable all consent
79
+ // @ts-ignore
80
+ window.__tcfapi = (command, _version, callback) => {
81
+ if (command !== 'addEventListener') return
82
+
83
+ setTimeout(() => callback({
84
+ purpose: { consents: { 1: true, 2: true, 7: true, 8: true, 9: true, 10: true } },
85
+ eventStatus: 'tcloaded',
86
+ }, true), 0)
87
+
88
+ return 1
89
+ }
77
90
 
78
91
  // Reset cookies
79
92
  document.cookie.split(';').forEach((cookie) => document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, '=;'))