@playpilot/tpi 8.42.0-beta.1 → 8.42.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.
@@ -7,14 +7,11 @@
7
7
  import type { TitleData } from '$lib/types/title'
8
8
  import { heading } from '$lib/actions/heading'
9
9
  import { campaignToPlaylink, getFirstAdOfType } from '$lib/api/ads'
10
- import { getContext, type Snippet } from 'svelte'
10
+ import { getContext } from 'svelte'
11
11
  import Playlink from './Playlink.svelte'
12
12
  import Button from '../Button.svelte'
13
13
  import PlaylinksDisclaimer from './PlaylinksDisclaimer.svelte'
14
14
  import { getConfigValue } from '$lib/api/config'
15
- import { getSplitTestVariantName } from '$lib/splitTest'
16
- import { SplitTest } from '$lib/enums/SplitTest'
17
- import Display from '../Ads/Display.svelte'
18
15
 
19
16
  type Category = PlaylinkCategory | '' | 'Other'
20
17
  type CategorizedPlaylinks = Partial<Record<Category, PlaylinkData[]>>
@@ -24,10 +21,9 @@
24
21
  playlinks: PlaylinkData[]
25
22
  title: TitleData
26
23
  limit?: number
27
- children?: Snippet
28
24
  }
29
25
 
30
- const { playlinks, title, limit = 3, children }: Props = $props()
26
+ const { playlinks, title, limit = 3 }: Props = $props()
31
27
 
32
28
  const isModal = getContext('scope') === 'modal'
33
29
  const type = getContext('type')
@@ -98,11 +94,7 @@
98
94
 
99
95
  <!-- A fake highlighted playlink as part of the display ad, to be shown after the first playlink -->
100
96
  {#if displayAd && (index === 0)}
101
- {#if children}
102
- {@render children()}
103
- {:else}
104
- <Playlink playlink={campaignToPlaylink(displayAd)} onclick={() => track(TrackingEvent.DisplayedAdPlaylickClick, title, { campaign_name: displayAd.campaign_name })} hideCategory disclaimer={displayAd.disclaimer || ''} />
105
- {/if}
97
+ <Playlink playlink={campaignToPlaylink(displayAd)} onclick={() => track(TrackingEvent.DisplayedAdPlaylickClick, title, { campaign_name: displayAd.campaign_name })} hideCategory disclaimer={displayAd.disclaimer || ''} />
106
98
  {/if}
107
99
  {/each}
108
100
  </div>
@@ -14,18 +14,14 @@
14
14
  import { TrackingEvent } from '$lib/enums/TrackingEvent'
15
15
  import TitleBackground from './TitleBackground.svelte'
16
16
  import TitleInfo from './TitleInfo.svelte'
17
- import Display from './Ads/Display.svelte'
18
- import type { Campaign } from '$lib/types/campaign'
19
- import { getFirstAdOfType } from '$lib/api/ads'
20
17
 
21
18
  interface Props {
22
19
  title: TitleData
23
20
  small?: boolean
24
21
  useVideoBackground?: boolean
25
- useDisplayAdSplitTest?: boolean // NOTE: Temporary split test, remove me after the DisplayAdFormat split test is gone
26
22
  }
27
23
 
28
- const { title, small = false, useVideoBackground = true, useDisplayAdSplitTest = false }: Props = $props()
24
+ const { title, small = false, useVideoBackground = true }: Props = $props()
29
25
 
30
26
  const noAffiliate = !!window.PlayPilotLinkInjections?.no_affiliate
31
27
 
@@ -62,11 +58,7 @@
62
58
  {/if}
63
59
 
64
60
  {#if !noAffiliate}
65
- <Playlinks playlinks={title.providers} {title}>
66
- {#if useDisplayAdSplitTest && getFirstAdOfType('card')}
67
- <Display campaign={getFirstAdOfType('card')!} />
68
- {/if}
69
- </Playlinks>
61
+ <Playlinks playlinks={title.providers} {title} />
70
62
  {/if}
71
63
 
72
64
  <ParticipantsRail {title} />
@@ -39,21 +39,10 @@
39
39
 
40
40
  // Used to re-render some elements with a key
41
41
  let renderKey = Math.random()
42
-
43
- function insertMockAd(): void {
44
- // @ts-ignore
45
- window.PlayPilotLinkInjections.consents = {
46
- ads: true
47
- }
48
-
49
- window.PlayPilotLinkInjections.ads = [campaign]
50
- }
51
42
  </script>
52
43
 
53
44
  <h1>Elements</h1>
54
45
 
55
- <button onclick={insertMockAd}>Insert mock ad</button>
56
-
57
46
  <p>This page lays out various elements used in TPI. It does not currently include editor elements.</p>
58
47
 
59
48
  <h2>Youtube Embed</h2>
@@ -184,15 +173,7 @@
184
173
  <div class="group">
185
174
  <div>
186
175
  <h3>Ads/Display.svelte</h3>
187
- <div class="item">
188
- <Display {campaign} />
189
-
190
- Compact (Used in popover)
191
- <Display {campaign} compact />
192
-
193
- Slim (Used in rail modals)
194
- <Display {campaign} slim />
195
- </div>
176
+ <div class="item"><Display {campaign} /></div>
196
177
  </div>
197
178
 
198
179
  <div>
@@ -1054,6 +1054,34 @@ describe('injection.ts', () => {
1054
1054
  expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[0]).dataset.playpilotInjectionType).toBe('participant')
1055
1055
  expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[1]).dataset.playpilotInjectionType).toBe('title')
1056
1056
  })
1057
+
1058
+ it('Should ignore participants with exclude_participants_url_pattern is true', () => {
1059
+ window.PlayPilotLinkInjections.config = {
1060
+ exclude_participants_urls_pattern: '/',
1061
+ }
1062
+
1063
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
1064
+
1065
+ const elements = Array.from(document.body.querySelectorAll('p'))
1066
+
1067
+ /** @type {import('$lib/types/injection').LinkInjection[]} */
1068
+ const aiInjections = [
1069
+ generateInjection('This is a sentence with an injection.', 'is a'),
1070
+ { ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: participants[0] },
1071
+ ]
1072
+
1073
+ /** @type {import('$lib/types/injection').LinkInjection[]} */
1074
+ const manualInjections = [
1075
+ { ...generateInjection('This is a sentence with an injection.', 'sentence with'), type: 'participant', manual: true, participant_details: participants[0] },
1076
+ ]
1077
+
1078
+ // @ts-ignore
1079
+ injectLinksInDocument(elements, { aiInjections, manualInjections })
1080
+
1081
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
1082
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[0].getAttribute('data-playpilot-injection-key')).toBe(aiInjections[0].key)
1083
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[1].getAttribute('data-playpilot-injection-key')).toBe(manualInjections[0].key)
1084
+ })
1057
1085
  })
1058
1086
 
1059
1087
  describe('config.open_tpi_links_in_explore', () => {
@@ -1195,6 +1223,76 @@ describe('injection.ts', () => {
1195
1223
  expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
1196
1224
  })
1197
1225
  })
1226
+
1227
+ describe('config.exclude_injections_by_anchors', () => {
1228
+ /** @type {import('$lib/types/injection').LinkInjection[]} */
1229
+ const injections = [
1230
+ { ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a' },
1231
+ { ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'b', anchor: 'full' },
1232
+ { ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'c', anchor: 'attached' },
1233
+ ]
1234
+
1235
+ it('Should exclude injections with anchors matching exclude_injections_by_anchors', () => {
1236
+ window.PlayPilotLinkInjections.config = {
1237
+ exclude_injections_by_anchors: ['attached'],
1238
+ }
1239
+
1240
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
1241
+
1242
+ const elements = Array.from(document.body.querySelectorAll('p'))
1243
+
1244
+ injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
1245
+
1246
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
1247
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[0].getAttribute('data-playpilot-injection-key')).toBe(injections[0].key)
1248
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[1].getAttribute('data-playpilot-injection-key')).toBe(injections[1].key)
1249
+ })
1250
+
1251
+ it('Should not exclude injections if config is not given', () => {
1252
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
1253
+
1254
+ const elements = Array.from(document.body.querySelectorAll('p'))
1255
+
1256
+ injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
1257
+
1258
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
1259
+ })
1260
+ })
1261
+
1262
+ describe('config.exclude_injections_by_evidence', () => {
1263
+ /** @type {import('$lib/types/injection').LinkInjection[]} */
1264
+ const injections = [
1265
+ { ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a' },
1266
+ { ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'b', evidence: 'screen_work' },
1267
+ { ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'c', evidence: 'credited' },
1268
+ ]
1269
+
1270
+ it('Should exclude injections with anchors matching exclude_injections_by_evidence', () => {
1271
+ window.PlayPilotLinkInjections.config = {
1272
+ exclude_injections_by_evidence: ['screen_work'],
1273
+ }
1274
+
1275
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
1276
+
1277
+ const elements = Array.from(document.body.querySelectorAll('p'))
1278
+
1279
+ injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
1280
+
1281
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
1282
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[0].getAttribute('data-playpilot-injection-key')).toBe(injections[0].key)
1283
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')[1].getAttribute('data-playpilot-injection-key')).toBe(injections[2].key)
1284
+ })
1285
+
1286
+ it('Should not exclude injections if config is not given', () => {
1287
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
1288
+
1289
+ const elements = Array.from(document.body.querySelectorAll('p'))
1290
+
1291
+ injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
1292
+
1293
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
1294
+ })
1295
+ })
1198
1296
  })
1199
1297
 
1200
1298
  describe('clearLinkInjections', () => {
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
- import { getFullUrlPath, getUrlParams, isUrlExcludedViaConfig, paramsToString } from '$lib/url'
2
+ import { getFullUrlPath, getUrlParams, isUrlExcludedViaConfig, isParticipantsUrlExcludedViaConfig, paramsToString } from '$lib/url'
3
3
 
4
4
  describe('url.ts', () => {
5
5
  describe('getFullUrlPath', () => {
@@ -113,4 +113,27 @@ describe('url.ts', () => {
113
113
  expect(isUrlExcludedViaConfig({ exclude_urls_pattern: '/some-page(/.*)?$' })).toBe(true)
114
114
  })
115
115
  })
116
+
117
+ describe('isParticipantsUrlExcludedViaConfig', () => {
118
+ it('Should return false if no key is given in config object', () => {
119
+ expect(isParticipantsUrlExcludedViaConfig({})).toBe(false)
120
+ })
121
+
122
+ it('Should return false if no key is given but is empty', () => {
123
+ expect(isParticipantsUrlExcludedViaConfig({ exclude_participants_urls_pattern: '' })).toBe(false)
124
+ })
125
+
126
+ it('Should return false if pattern is given but does not match url', () => {
127
+ window.location.pathname = '/path'
128
+ expect(isParticipantsUrlExcludedViaConfig({ exclude_participants_urls_pattern: '/not-path' })).toBe(false)
129
+ })
130
+
131
+ it('Should return true if pattern is given and does matches url', () => {
132
+ window.location.pathname = '/path'
133
+ expect(isParticipantsUrlExcludedViaConfig({ exclude_participants_urls_pattern: '/path' })).toBe(true)
134
+
135
+ window.location.pathname = '/some-page/subpath'
136
+ expect(isParticipantsUrlExcludedViaConfig({ exclude_participants_urls_pattern: '/some-page(/.*)?$' })).toBe(true)
137
+ })
138
+ })
116
139
  })
@@ -86,7 +86,7 @@ describe('Display.svelte', () => {
86
86
 
87
87
  it('Should render content subheader when given', () => {
88
88
  /** @ts-ignore */
89
- const { getByText } = render(Display, { campaign: { cta: { subheader: 'Some cta subheader' }, content: {} } })
89
+ const { getByText } = render(Display, { campaign: { cta: { subheader: 'Some cta subheader' }, content: { } } })
90
90
 
91
91
  expect(getByText('Some cta subheader')).toBeTruthy()
92
92
  })
@@ -153,14 +153,4 @@ describe('Display.svelte', () => {
153
153
 
154
154
  expect(container.querySelector('video')).toBeTruthy()
155
155
  })
156
-
157
- it('Should render with expected content when slim variant is given', () => {
158
- /** @ts-ignore */
159
- const { container, queryByText } = render(Display, { slim: true, campaign: { campaign_type: 'video', cta: { header: 'Some header', subheader: 'Some cta subheader' }, content: { header_logo: 'dfg', video: 'abc' } } })
160
-
161
- expect(container.querySelector('.slim')).toBeTruthy()
162
- expect(container.querySelector('.logo')).toBeTruthy()
163
- expect(queryByText('Some header')).toBeTruthy()
164
- expect(queryByText('Some cta header')).not.toBeTruthy()
165
- })
166
156
  })