@playpilot/tpi 8.41.0 → 8.42.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/editorial.mount.js +10 -10
- package/dist/link-injections.js +2 -2
- package/dist/mount.css +1 -1
- package/dist/mount.js +7 -7
- package/package.json +1 -1
- package/src/lib/enums/SplitTest.ts +5 -0
- package/src/lib/fakeData.ts +2 -2
- package/src/lib/injection.ts +3 -13
- package/src/lib/types/config.d.ts +0 -5
- package/src/lib/url.ts +0 -4
- package/src/routes/components/Ads/Display.svelte +52 -5
- package/src/routes/components/Debugger.svelte +2 -0
- package/src/routes/components/Modals/RailModal.svelte +12 -4
- package/src/routes/components/Modals/TitlesRailModal.svelte +3 -1
- package/src/routes/components/Playlinks/Playlinks.svelte +11 -3
- package/src/routes/components/Title.svelte +10 -2
- package/src/routes/elements/+page.svelte +20 -1
- package/src/tests/lib/injection.test.js +1520 -1548
- package/src/tests/lib/url.test.js +1 -24
- package/src/tests/routes/components/Ads/Display.test.js +11 -1
|
@@ -1,1548 +1,1520 @@
|
|
|
1
|
-
import { fireEvent } from '@testing-library/svelte'
|
|
2
|
-
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
|
|
3
|
-
|
|
4
|
-
import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType, removePlayPilotTitleLinks, hasValidTypeData, doesParticipantMeetThreshold } from '$lib/injection'
|
|
5
|
-
import { mount, unmount } from 'svelte'
|
|
6
|
-
import { fakeFetch, generateInjection } from '../helpers'
|
|
7
|
-
import { openModalForInjectedLink } from '$lib/modal'
|
|
8
|
-
import { getLinkInjectionElements } from '$lib/injectionElements'
|
|
9
|
-
import { participants } from '$lib/fakeData'
|
|
10
|
-
import { titleUrl } from '$lib/routes'
|
|
11
|
-
|
|
12
|
-
vi.mock('svelte', () => ({
|
|
13
|
-
mount: vi.fn(),
|
|
14
|
-
unmount: vi.fn(),
|
|
15
|
-
}))
|
|
16
|
-
|
|
17
|
-
vi.mock('$lib/modal', () => ({
|
|
18
|
-
openModal: vi.fn(),
|
|
19
|
-
destroyAllModals: vi.fn(),
|
|
20
|
-
getPreviousModal: vi.fn(),
|
|
21
|
-
goBackToPreviousModal: vi.fn(),
|
|
22
|
-
openModalForInjectedLink: vi.fn(),
|
|
23
|
-
}))
|
|
24
|
-
|
|
25
|
-
vi.mock('$lib/tracking', () => ({
|
|
26
|
-
track: vi.fn(),
|
|
27
|
-
}))
|
|
28
|
-
|
|
29
|
-
function mockMatchMedia(matches = false) {
|
|
30
|
-
Object.defineProperty(window, 'matchMedia', {
|
|
31
|
-
writable: true,
|
|
32
|
-
value: vi.fn().mockImplementation((query) => ({
|
|
33
|
-
matches,
|
|
34
|
-
media: query,
|
|
35
|
-
})),
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
describe('injection.ts', () => {
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
vi.resetAllMocks()
|
|
42
|
-
clearLinkInjections()
|
|
43
|
-
|
|
44
|
-
mockMatchMedia()
|
|
45
|
-
fakeFetch()
|
|
46
|
-
vi.mocked(mount).mockReturnValueOnce({})
|
|
47
|
-
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
window.PlayPilotLinkInjections = {}
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
afterEach(() => {
|
|
53
|
-
vi.useRealTimers()
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
describe('injectLinksInDocument', () => {
|
|
57
|
-
it('Should replace given words with injections', () => {
|
|
58
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
59
|
-
const linkInjections = [injection]
|
|
60
|
-
|
|
61
|
-
document.body.innerHTML = `<p>${injection.sentence}</p>`
|
|
62
|
-
|
|
63
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
64
|
-
|
|
65
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
66
|
-
|
|
67
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
68
|
-
|
|
69
|
-
// @ts-ignore
|
|
70
|
-
expect(link.href).toBe(titleUrl(injection.title_details))
|
|
71
|
-
expect(link.innerText).toBe(injection.title)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('Should replace given words as expected when more than 1 injection per sentence is present', () => {
|
|
75
|
-
const sentence = 'This is a sentence with an injection.'
|
|
76
|
-
const linkInjections = [
|
|
77
|
-
generateInjection(sentence, 'a sentence'),
|
|
78
|
-
generateInjection(sentence, 'an injection'),
|
|
79
|
-
]
|
|
80
|
-
|
|
81
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
82
|
-
|
|
83
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
84
|
-
|
|
85
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
86
|
-
|
|
87
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
88
|
-
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
expect(links[0].href).toBe(titleUrl(linkInjections[0].title_details))
|
|
91
|
-
expect(links[0].innerText).toBe(linkInjections[0].title)
|
|
92
|
-
|
|
93
|
-
// @ts-ignore
|
|
94
|
-
expect(links[1].href).toBe(titleUrl(linkInjections[1].title_details))
|
|
95
|
-
expect(links[1].innerText).toBe(linkInjections[1].title)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('Should ignore injections that are marked as inactive', () => {
|
|
99
|
-
const sentence = 'This is a sentence with an injection.'
|
|
100
|
-
const injection = generateInjection(sentence, 'an injection')
|
|
101
|
-
const linkInjections = [{ ...injection, inactive: true }]
|
|
102
|
-
|
|
103
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
104
|
-
|
|
105
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
106
|
-
|
|
107
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
108
|
-
|
|
109
|
-
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('Should ignore injections that are marked as removed', () => {
|
|
113
|
-
const sentence = 'This is a sentence with an injection.'
|
|
114
|
-
const injection = generateInjection(sentence, 'an injection')
|
|
115
|
-
const linkInjections = [{ ...injection, removed: true }]
|
|
116
|
-
|
|
117
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
118
|
-
|
|
119
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
120
|
-
|
|
121
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
122
|
-
|
|
123
|
-
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
it('Should ignore AI injections that are marked as removed as a matching manual injections', () => {
|
|
127
|
-
const sentence = 'This is a sentence with an injection.'
|
|
128
|
-
const injection = generateInjection(sentence, 'an injection')
|
|
129
|
-
|
|
130
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
131
|
-
|
|
132
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
133
|
-
|
|
134
|
-
const injections = {
|
|
135
|
-
aiInjections: [injection],
|
|
136
|
-
manualInjections: [{ ...injection, manual: true, removed: true }],
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
injectLinksInDocument(elements, injections)
|
|
140
|
-
|
|
141
|
-
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
it('Should ignore AI injections that are marked as inactive as a matching manual injections', () => {
|
|
145
|
-
const sentence = 'This is a sentence with an injection.'
|
|
146
|
-
const injection = generateInjection(sentence, 'an injection')
|
|
147
|
-
|
|
148
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
149
|
-
|
|
150
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
151
|
-
|
|
152
|
-
const injections = {
|
|
153
|
-
aiInjections: [injection],
|
|
154
|
-
manualInjections: [{ ...injection, manual: true, inactive: true }],
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
injectLinksInDocument(elements, injections)
|
|
158
|
-
|
|
159
|
-
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('Should keep existing HTML elements intact', () => {
|
|
163
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
164
|
-
const linkInjections = [injection]
|
|
165
|
-
|
|
166
|
-
document.body.innerHTML = '<p>This is a <button>sentence</button> with an injection.</p>'
|
|
167
|
-
|
|
168
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
169
|
-
|
|
170
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
171
|
-
|
|
172
|
-
const button = /** @type {HTMLButtonElement} */ (document.querySelector('button'))
|
|
173
|
-
|
|
174
|
-
expect(button.innerText).toBe('sentence')
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('Should ignore elements that were not selected', () => {
|
|
178
|
-
document.body.innerHTML = '<h1>I am a title</h1><p>This is a sentence with an injection.</p>'
|
|
179
|
-
|
|
180
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
181
|
-
const injection = generateInjection('I am a title', 'a title')
|
|
182
|
-
|
|
183
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
184
|
-
|
|
185
|
-
expect(document.body.innerHTML.includes(injection.sentence)).toBeTruthy()
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it('Should ignore partial matches due to interfering elements', () => {
|
|
189
|
-
document.body.innerHTML = '<p>This is a sentence with <strong>an</strong> injection.</p>'
|
|
190
|
-
|
|
191
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
192
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
193
|
-
|
|
194
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
195
|
-
|
|
196
|
-
expect(document.body.innerHTML.includes('an injection')).not.toBeTruthy()
|
|
197
|
-
expect(document.body.innerHTML.includes('an')).toBeTruthy()
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it('Should ignore encoded characters in given sentences', () => {
|
|
201
|
-
document.body.innerHTML = '<p>This is a sentence & an injection.</p>'
|
|
202
|
-
|
|
203
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
204
|
-
const injection = generateInjection('This is a sentence & an injection.', 'an injection')
|
|
205
|
-
|
|
206
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
207
|
-
|
|
208
|
-
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('Should ignore matches due to parent links', () => {
|
|
212
|
-
document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
|
|
213
|
-
|
|
214
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
215
|
-
const injection = generateInjection('This is a sentence with an injection.', 'a sentence')
|
|
216
|
-
|
|
217
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
218
|
-
|
|
219
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
it('Should ignore matches inside of attributes inside of links', () => {
|
|
223
|
-
document.body.innerHTML = '<p>This is <a data-thing="some word">a sentence</a> with an injection.</p>'
|
|
224
|
-
|
|
225
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
226
|
-
const injection = generateInjection('This is a sentence with an injection.', 'some word')
|
|
227
|
-
|
|
228
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
229
|
-
|
|
230
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
it('Should ignore matches inside of attributes inside of links but still inject into other matches', () => {
|
|
234
|
-
document.body.innerHTML = '<p>This is <a data-thing="some word">some word</a> with an injection in some word.</p>'
|
|
235
|
-
|
|
236
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
237
|
-
const injection = generateInjection('This is some word with an injection in some word.', 'some word')
|
|
238
|
-
|
|
239
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
240
|
-
|
|
241
|
-
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
242
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
it('Should skip links and replace other words instead', () => {
|
|
246
|
-
document.body.innerHTML = '<p>This is <a>a word</a> with a word.</p>'
|
|
247
|
-
|
|
248
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
249
|
-
const injection = generateInjection('This is a word with a word.', 'a word')
|
|
250
|
-
|
|
251
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
252
|
-
|
|
253
|
-
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
254
|
-
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('Should skip links inside of other elements and replace other words instead', () => {
|
|
258
|
-
document.body.innerHTML = '<p>This is <em><a>a word</a></em> with a word.</p>'
|
|
259
|
-
|
|
260
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
261
|
-
const injection = generateInjection('This is a word with a word.', 'a word')
|
|
262
|
-
|
|
263
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
264
|
-
|
|
265
|
-
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
266
|
-
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
it('Should skip partial matches in sentences that are broken up by different nodes but have the same match', () => {
|
|
270
|
-
document.body.innerHTML = '<p>This is <a>a word</a> with a word.</p>'
|
|
271
|
-
|
|
272
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
273
|
-
const injection = generateInjection('this is a word with a word.', 'a word')
|
|
274
|
-
|
|
275
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
276
|
-
|
|
277
|
-
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
278
|
-
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
279
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
it('Should inject into correct sentence when element contains other sentences with the same matching title', () => {
|
|
283
|
-
document.body.innerHTML = '<p>This is a match. But this sentence is a match.</p>'
|
|
284
|
-
|
|
285
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
286
|
-
const injection = generateInjection('But this sentence is a match.', 'a match')
|
|
287
|
-
|
|
288
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
289
|
-
|
|
290
|
-
expect(document.body.innerHTML).toContain('This is a match')
|
|
291
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
it('Should inject properly when sentence contains element that are not part of the match', () => {
|
|
295
|
-
document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
|
|
296
|
-
|
|
297
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
298
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
299
|
-
|
|
300
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
301
|
-
|
|
302
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
it('Should inject correctly when sentence is broken up by html and element contains multiple matches', () => {
|
|
306
|
-
document.body.innerHTML = '<p>This is some match. Some other sentence with a match. But this is yet another <em>sentence</em> with a match.</p>'
|
|
307
|
-
|
|
308
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
309
|
-
|
|
310
|
-
const injections = [
|
|
311
|
-
generateInjection('This is some match.', 'some match'),
|
|
312
|
-
generateInjection('But this is yet another sentence with a match.', 'a match'),
|
|
313
|
-
]
|
|
314
|
-
|
|
315
|
-
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
316
|
-
|
|
317
|
-
expect(document.body.innerHTML).toContain('Some other sentence with a match')
|
|
318
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
it('Should disregard missing trailing periods', () => {
|
|
322
|
-
document.body.innerHTML = '<p>This is a sentence with a phrase in it</p>'
|
|
323
|
-
|
|
324
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
325
|
-
const injection = generateInjection('This is a sentence with a phrase in it.', 'a phrase')
|
|
326
|
-
|
|
327
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
328
|
-
|
|
329
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
it('Should disregard additional quotes', () => {
|
|
333
|
-
document.body.innerHTML = '<p>This is part of a paragraph. This is a sentence with a phrase in it."</p>'
|
|
334
|
-
|
|
335
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
336
|
-
const injection = generateInjection('"This is a sentence with a phrase in it."', 'a phrase')
|
|
337
|
-
|
|
338
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
339
|
-
|
|
340
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
it('Should disregard differences in accents', () => {
|
|
344
|
-
document.body.innerHTML = '<p>This is à sentence with a phràse in it."</p>'
|
|
345
|
-
|
|
346
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
347
|
-
const injection = generateInjection('This is a sentence with a phrase in it.', 'a phràse')
|
|
348
|
-
|
|
349
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
350
|
-
|
|
351
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
it('Should treat different types of quotes as the same', () => {
|
|
355
|
-
document.body.innerHTML = '<p>This is a “sentence” with a "phrase" in it.</p>'
|
|
356
|
-
|
|
357
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
358
|
-
const injection = generateInjection('This is a "sentence" with a \'phrase’ in it.', 'phrase')
|
|
359
|
-
|
|
360
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
361
|
-
|
|
362
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
it('Should disregard differences in special characters', () => {
|
|
366
|
-
document.body.innerHTML = '<p>This -> is a sentence, with a phrase - in it.</p>'
|
|
367
|
-
|
|
368
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
369
|
-
const injection = generateInjection('This is a sentence with a _phrase_ in it.', 'phrase')
|
|
370
|
-
|
|
371
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
372
|
-
|
|
373
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
374
|
-
})
|
|
375
|
-
|
|
376
|
-
it('Should leave the text intact if no injections were found', () => {
|
|
377
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
378
|
-
|
|
379
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
380
|
-
|
|
381
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
382
|
-
const linkInjections = []
|
|
383
|
-
|
|
384
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
385
|
-
|
|
386
|
-
expect(document.body.innerHTML.includes('This is a sentence with an injection.')).toBeTruthy()
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
it('Should handle not receiving elements or injections', () => {
|
|
390
|
-
/** @type {HTMLElement[]} */
|
|
391
|
-
const elements = []
|
|
392
|
-
|
|
393
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
394
|
-
const linkInjections = []
|
|
395
|
-
|
|
396
|
-
expect(() => injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })).not.toThrow()
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
it('Should open modal when link is clicked', async () => {
|
|
400
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
401
|
-
|
|
402
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
403
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
404
|
-
|
|
405
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
406
|
-
|
|
407
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
408
|
-
await fireEvent.click(link)
|
|
409
|
-
|
|
410
|
-
expect(openModalForInjectedLink).toHaveBeenCalled()
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
it('Should not fire given onclick function when clicked with modifier keys or not left click', async () => {
|
|
414
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
415
|
-
|
|
416
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
417
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
418
|
-
|
|
419
|
-
const mock = vi.fn()
|
|
420
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
421
|
-
|
|
422
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
423
|
-
|
|
424
|
-
await fireEvent.click(link, { ctrlKey: true })
|
|
425
|
-
await fireEvent.click(link, { metaKey: true })
|
|
426
|
-
await fireEvent.click(link, { button: 1 })
|
|
427
|
-
await fireEvent.click(link, { button: 2 })
|
|
428
|
-
|
|
429
|
-
expect(mock).not.toHaveBeenCalled()
|
|
430
|
-
})
|
|
431
|
-
|
|
432
|
-
it('Should return array with failed injections marked as such', () => {
|
|
433
|
-
const sentence = 'This is a sentence with an injection.'
|
|
434
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
435
|
-
|
|
436
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
437
|
-
|
|
438
|
-
const linkInjections = [
|
|
439
|
-
generateInjection(sentence, 'a sentence'),
|
|
440
|
-
generateInjection(sentence, 'not an injection'),
|
|
441
|
-
]
|
|
442
|
-
|
|
443
|
-
const results = injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
444
|
-
|
|
445
|
-
expect(results[0].failed).toBe(false)
|
|
446
|
-
expect(results[1].failed).toBe(true)
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
it('Should return corresponding messages for failed injections', () => {
|
|
450
|
-
const sentence = 'This is <a href="/">a sentence</a> with an injection.'
|
|
451
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
452
|
-
|
|
453
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
454
|
-
|
|
455
|
-
const manuallyRemoved = generateInjection(sentence, 'an injection')
|
|
456
|
-
|
|
457
|
-
const linkInjections = [
|
|
458
|
-
generateInjection(sentence, 'a sentence'),
|
|
459
|
-
generateInjection('Some unknown sentence', 'nothing'),
|
|
460
|
-
{ ...manuallyRemoved, duplicate: true, removed: true, manual: true },
|
|
461
|
-
]
|
|
462
|
-
|
|
463
|
-
const results = injectLinksInDocument(elements, { aiInjections: [manuallyRemoved], manualInjections: linkInjections })
|
|
464
|
-
|
|
465
|
-
expect(results[0].failed_message).toBe('Given text is already inside of a link.')
|
|
466
|
-
expect(results[1].failed_message).toBe('Given sentence was not found in the article.')
|
|
467
|
-
expect(results[2].failed_message).toBe('')
|
|
468
|
-
expect(results[3].failed_message).toBe('Injection was manually removed.')
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
it('Should return sentence message if text was found in full body text but not in individual elements', () => {
|
|
472
|
-
document.body.innerHTML = '<article><p>Some sentence</p><p>that is broken in two</p></main>'
|
|
473
|
-
|
|
474
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
475
|
-
const linkInjections = [generateInjection('Some sentence that is broken in two', 'broken')]
|
|
476
|
-
|
|
477
|
-
const results = injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
478
|
-
|
|
479
|
-
expect(results[0].failed_message).toBe('Given sentence was not found in the article.')
|
|
480
|
-
})
|
|
481
|
-
|
|
482
|
-
it('Should disregard spaces and special characters in failed message', () => {
|
|
483
|
-
const sentence = 'This is a & sentence with an injection.'
|
|
484
|
-
document.body.innerHTML = `<p>${sentence}</p>`
|
|
485
|
-
|
|
486
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
487
|
-
|
|
488
|
-
const linkInjections = [
|
|
489
|
-
generateInjection('This is a&sentence with aninjection.', 'an injection'),
|
|
490
|
-
generateInjection('This is a&sentence with aninjection.', 'nothing'),
|
|
491
|
-
]
|
|
492
|
-
|
|
493
|
-
const results = injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
494
|
-
|
|
495
|
-
expect(results[0].failed_message).not.toBeTruthy()
|
|
496
|
-
expect(results[1].failed_message).toBe('The link failed to inject for unknown reasons.')
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
it('Should mount popover component when element other than popover or link is hovered', async () => {
|
|
500
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
501
|
-
|
|
502
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
503
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
504
|
-
|
|
505
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
506
|
-
|
|
507
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
508
|
-
|
|
509
|
-
vi.useFakeTimers()
|
|
510
|
-
|
|
511
|
-
await fireEvent.mouseEnter(link)
|
|
512
|
-
vi.advanceTimersByTime(200)
|
|
513
|
-
expect(mount).toHaveBeenCalled()
|
|
514
|
-
|
|
515
|
-
await fireEvent.mouseMove(link)
|
|
516
|
-
expect(unmount).not.toHaveBeenCalled()
|
|
517
|
-
|
|
518
|
-
await fireEvent.mouseMove(document.body)
|
|
519
|
-
expect(unmount).toHaveBeenCalled()
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('Should mount popover on mouseover again after previously having mounted and unmounted that same popover', async () => {
|
|
523
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
524
|
-
|
|
525
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
526
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
527
|
-
|
|
528
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
529
|
-
|
|
530
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
531
|
-
|
|
532
|
-
vi.useFakeTimers()
|
|
533
|
-
|
|
534
|
-
await fireEvent.mouseEnter(link)
|
|
535
|
-
vi.advanceTimersByTime(200)
|
|
536
|
-
await fireEvent.mouseMove(document.body)
|
|
537
|
-
await fireEvent.mouseEnter(link)
|
|
538
|
-
vi.advanceTimersByTime(200)
|
|
539
|
-
|
|
540
|
-
expect(mount).toHaveBeenCalledTimes(2)
|
|
541
|
-
})
|
|
542
|
-
|
|
543
|
-
it('Should not mount popover on mouseover if not hovered for long enough duration', async () => {
|
|
544
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
545
|
-
|
|
546
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
547
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
548
|
-
|
|
549
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
550
|
-
|
|
551
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
552
|
-
|
|
553
|
-
vi.useFakeTimers()
|
|
554
|
-
|
|
555
|
-
await fireEvent.mouseEnter(link)
|
|
556
|
-
vi.advanceTimersByTime(50)
|
|
557
|
-
await fireEvent.mouseLeave(link)
|
|
558
|
-
vi.advanceTimersByTime(500)
|
|
559
|
-
|
|
560
|
-
expect(mount).not.toHaveBeenCalled()
|
|
561
|
-
})
|
|
562
|
-
|
|
563
|
-
it('Should not mount popover on mouseover again if link is already being hovered', async () => {
|
|
564
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
565
|
-
|
|
566
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
567
|
-
const injections = [
|
|
568
|
-
generateInjection('This is a sentence with an injection.', 'a sentence'),
|
|
569
|
-
generateInjection('This is a sentence with an injection.', 'an injection'),
|
|
570
|
-
]
|
|
571
|
-
|
|
572
|
-
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
573
|
-
|
|
574
|
-
const [link1, link2] = document.querySelectorAll('[data-playpilot-injection-key]')
|
|
575
|
-
|
|
576
|
-
vi.useFakeTimers()
|
|
577
|
-
|
|
578
|
-
await fireEvent.mouseEnter(link1)
|
|
579
|
-
vi.advanceTimersByTime(200)
|
|
580
|
-
await fireEvent.mouseEnter(link2)
|
|
581
|
-
vi.advanceTimersByTime(500)
|
|
582
|
-
|
|
583
|
-
expect(mount).toHaveBeenCalledTimes(1)
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
it('Should remove all popovers that may not have been removed properly in previous destroy attempts', async () => {
|
|
587
|
-
document.body.innerHTML = '<div data-playpilot-injection-key></div><div data-playpilot-injection-popover></div> <p>This is a sentence with an injection.</p>'
|
|
588
|
-
|
|
589
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
590
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
591
|
-
|
|
592
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
593
|
-
|
|
594
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
595
|
-
|
|
596
|
-
vi.useFakeTimers()
|
|
597
|
-
|
|
598
|
-
await fireEvent.mouseEnter(link)
|
|
599
|
-
await fireEvent.mouseMove(document.body)
|
|
600
|
-
vi.advanceTimersByTime(200)
|
|
601
|
-
|
|
602
|
-
expect(document.querySelectorAll('[data-playpilot-injection-popover]')).toHaveLength(0)
|
|
603
|
-
})
|
|
604
|
-
|
|
605
|
-
it('Should inject links of the same phrase when multiple are present', () => {
|
|
606
|
-
document.body.innerHTML = '<p>This is a sentence with an injection and another injection</p>'
|
|
607
|
-
|
|
608
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
609
|
-
|
|
610
|
-
const sentence = 'This is a sentence with an injection and another injection'
|
|
611
|
-
const linkInjections = [
|
|
612
|
-
generateInjection(sentence, 'injection'),
|
|
613
|
-
generateInjection(sentence, 'injection'),
|
|
614
|
-
]
|
|
615
|
-
|
|
616
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
617
|
-
|
|
618
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
|
|
619
|
-
|
|
620
|
-
expect(links).toHaveLength(2)
|
|
621
|
-
expect(links[0].dataset.playpilotInjectionKey).toBe(linkInjections[0].key)
|
|
622
|
-
expect(links[1].dataset.playpilotInjectionKey).toBe(linkInjections[1].key)
|
|
623
|
-
})
|
|
624
|
-
|
|
625
|
-
it('Should inject links of the same phrase when multiple are present, but ignore injectios into links that contain the same phrase', () => {
|
|
626
|
-
document.body.innerHTML = '<p>First phrase, <a href="/phrase">second</a> phrase</p>'
|
|
627
|
-
|
|
628
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
629
|
-
|
|
630
|
-
const sentence = 'First phrase, second phrase'
|
|
631
|
-
const linkInjections = [
|
|
632
|
-
generateInjection(sentence, 'phrase'),
|
|
633
|
-
generateInjection(sentence, 'phrase'),
|
|
634
|
-
]
|
|
635
|
-
|
|
636
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
637
|
-
|
|
638
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
639
|
-
|
|
640
|
-
expect(links).toHaveLength(3)
|
|
641
|
-
})
|
|
642
|
-
|
|
643
|
-
it('Should inject link properly when sentence already contains match of the same phrase but the sentence is broken up by HTML very early in the sentence.', () => {
|
|
644
|
-
document.body.innerHTML = '<p>A <em><a>phrase</a></em> within a sentence. Another <strong>sentence</strong> with a <em>phrase</em> in it.</p>'
|
|
645
|
-
|
|
646
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
647
|
-
|
|
648
|
-
const linkInjections = [generateInjection('Another sentence with a phrase in it.', 'phrase')]
|
|
649
|
-
|
|
650
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
651
|
-
|
|
652
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
653
|
-
|
|
654
|
-
expect(links).toHaveLength(2)
|
|
655
|
-
})
|
|
656
|
-
|
|
657
|
-
it('Should inject link properly when sentence already contains partial match of the same phrase when the sentence is broken up by html.', () => {
|
|
658
|
-
document.body.innerHTML = '<p>Some sentence with a phrase: something, and another phrase.</p>'
|
|
659
|
-
|
|
660
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
661
|
-
|
|
662
|
-
const linkInjections = [
|
|
663
|
-
generateInjection('Some sentence with a phrase: something, and another phrase.', 'phrase: something'),
|
|
664
|
-
generateInjection('Some sentence with a phrase: something, and another phrase.', 'phrase'),
|
|
665
|
-
]
|
|
666
|
-
|
|
667
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
668
|
-
|
|
669
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
670
|
-
|
|
671
|
-
expect(links).toHaveLength(2)
|
|
672
|
-
})
|
|
673
|
-
|
|
674
|
-
it('Should inject longer titles before shorter titles', () => {
|
|
675
|
-
document.body.innerHTML = '<p>Some sentence with phrase 2, and another phrase.</p>'
|
|
676
|
-
|
|
677
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
678
|
-
|
|
679
|
-
const linkInjections = [
|
|
680
|
-
generateInjection('Some sentence with phrase 2, and another phrase.', 'phrase'),
|
|
681
|
-
generateInjection('Some sentence with phrase 2, and another phrase.', 'phrase 2'),
|
|
682
|
-
]
|
|
683
|
-
|
|
684
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
685
|
-
|
|
686
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
687
|
-
|
|
688
|
-
expect(links).toHaveLength(2)
|
|
689
|
-
expect(links[0].innerText).toBe('phrase 2')
|
|
690
|
-
expect(links[1].innerText).toBe('phrase')
|
|
691
|
-
})
|
|
692
|
-
|
|
693
|
-
it('Should not inject links into element attributes', () => {
|
|
694
|
-
document.body.innerHTML = '<p><span data-thing="phrase">Some</span> phrase</p>'
|
|
695
|
-
|
|
696
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
697
|
-
|
|
698
|
-
const sentence = 'Some phrase'
|
|
699
|
-
const linkInjections = [
|
|
700
|
-
generateInjection(sentence, 'phrase'),
|
|
701
|
-
generateInjection(sentence, 'phrase'),
|
|
702
|
-
]
|
|
703
|
-
|
|
704
|
-
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
705
|
-
|
|
706
|
-
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
|
|
707
|
-
|
|
708
|
-
expect(links).toHaveLength(1)
|
|
709
|
-
expect(document.body.innerText).toBe(sentence)
|
|
710
|
-
})
|
|
711
|
-
|
|
712
|
-
it('Should not inject injections with in_text set to false', () => {
|
|
713
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
714
|
-
|
|
715
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
716
|
-
const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), in_text: false }
|
|
717
|
-
|
|
718
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
719
|
-
|
|
720
|
-
expect(document.querySelector('a')).not.toBeTruthy()
|
|
721
|
-
})
|
|
722
|
-
|
|
723
|
-
it('Should not inject injections into already existing links when the page contains multiple sentences of the same text where one has an existing link and the other does not.', () => {
|
|
724
|
-
document.body.innerHTML = '<p>This is a <a href="#">phrase</a>.</p> <p>This is a phrase.</p>'
|
|
725
|
-
|
|
726
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
727
|
-
const injection = generateInjection('This is a phrase.', 'phrase')
|
|
728
|
-
|
|
729
|
-
injectLinksInDocument(elements, { aiInjections: [injection, injection], manualInjections: [] })
|
|
730
|
-
|
|
731
|
-
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
732
|
-
})
|
|
733
|
-
|
|
734
|
-
it('Should not inject injections into already existing links when multiple injections are present for the same phrase in the same sentence that only contain the phrase once and the phrase is broken up by HTML', () => {
|
|
735
|
-
document.body.innerHTML = '<p>This is a <strong>phr</strong>ase.</p>'
|
|
736
|
-
|
|
737
|
-
const elements = Array.from(document.querySelectorAll('p'))
|
|
738
|
-
const injection = generateInjection('This is a phrase.', 'phrase')
|
|
739
|
-
|
|
740
|
-
injectLinksInDocument(elements, { aiInjections: [injection, injection], manualInjections: [] })
|
|
741
|
-
|
|
742
|
-
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
743
|
-
})
|
|
744
|
-
|
|
745
|
-
it('Should not mount popover if user uses touch', async () => {
|
|
746
|
-
mockMatchMedia(true)
|
|
747
|
-
|
|
748
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
749
|
-
|
|
750
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
751
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
752
|
-
|
|
753
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
754
|
-
|
|
755
|
-
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
756
|
-
|
|
757
|
-
await fireEvent.mouseEnter(link)
|
|
758
|
-
expect(mount).not.toHaveBeenCalled()
|
|
759
|
-
})
|
|
760
|
-
|
|
761
|
-
it('Should not call insertAfterArticlePlaylinks if injections only contain inactive or removed items', () => {
|
|
762
|
-
document.body.innerHTML = `<section>
|
|
763
|
-
<div>Some text</div>
|
|
764
|
-
<div>Some other text</div>
|
|
765
|
-
</section>
|
|
766
|
-
`
|
|
767
|
-
|
|
768
|
-
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
769
|
-
const injection = generateInjection('Some sentence', 'an injection')
|
|
770
|
-
const linkInjections = [{ ...injection, after_article: true, inactive: true }, { ...injection, after_article: true, removed: true }]
|
|
771
|
-
|
|
772
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
773
|
-
|
|
774
|
-
expect(mount).not.toHaveBeenCalled()
|
|
775
|
-
expect(document.querySelector('[data-playpilot-after-article-playlinks]')).not.toBeTruthy()
|
|
776
|
-
})
|
|
777
|
-
|
|
778
|
-
it('Should not call insertAfterArticlePlaylinks if article contains no valid injections', () => {
|
|
779
|
-
window.PlayPilotLinkInjections.config = {
|
|
780
|
-
in_text_disclaimer_enabled: true,
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
document.body.innerHTML = `<section>
|
|
784
|
-
<div>Some text</div>
|
|
785
|
-
<div>Some other text</div>
|
|
786
|
-
</section>
|
|
787
|
-
`
|
|
788
|
-
|
|
789
|
-
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
790
|
-
const injection = generateInjection('Some sentence', 'an injection')
|
|
791
|
-
const linkInjections = [{ ...injection, inactive: true }, { ...injection, removed: true }]
|
|
792
|
-
|
|
793
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
794
|
-
|
|
795
|
-
expect(mount).not.toHaveBeenCalled()
|
|
796
|
-
expect(document.querySelector('[data-playpilot-in-text-disclaimer]')).not.toBeTruthy()
|
|
797
|
-
})
|
|
798
|
-
|
|
799
|
-
it('Should call insertAfterArticlePlaylinks if article contains valid injections', () => {
|
|
800
|
-
window.PlayPilotLinkInjections.config = {
|
|
801
|
-
in_text_disclaimer_enabled: true,
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
document.body.innerHTML = '<p>Some sentence with an injection</p>'
|
|
805
|
-
|
|
806
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
807
|
-
const injection = generateInjection('Some sentence with an injection', 'an injection')
|
|
808
|
-
|
|
809
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
810
|
-
|
|
811
|
-
expect(mount).toHaveBeenCalled()
|
|
812
|
-
expect(document.querySelector('[data-playpilot-in-text-disclaimer]')).toBeTruthy()
|
|
813
|
-
})
|
|
814
|
-
|
|
815
|
-
it('Should treat sentences the same regardless of differences spaces', () => {
|
|
816
|
-
document.body.innerHTML = `<section>
|
|
817
|
-
<div>Some text</div>
|
|
818
|
-
<div>Someothertext</div>
|
|
819
|
-
<div>Some thirdtext</div>
|
|
820
|
-
<div>Some fourth text </div>
|
|
821
|
-
</section>
|
|
822
|
-
`
|
|
823
|
-
|
|
824
|
-
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
825
|
-
const injections = [
|
|
826
|
-
generateInjection('Sometext', 'Some'),
|
|
827
|
-
generateInjection('Some other text ', 'Some'),
|
|
828
|
-
generateInjection('Somethird text', 'Some'),
|
|
829
|
-
generateInjection('Some fourthtext', 'Some'),
|
|
830
|
-
]
|
|
831
|
-
|
|
832
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
833
|
-
|
|
834
|
-
expect(document.querySelectorAll('a')).toHaveLength(4)
|
|
835
|
-
})
|
|
836
|
-
|
|
837
|
-
it('Should treat sentences the same regardless of casings', () => {
|
|
838
|
-
document.body.innerHTML = `<section>
|
|
839
|
-
<div>Some text</div>
|
|
840
|
-
<div>Some OTHER TEXT</div>
|
|
841
|
-
<div>Some ThIrD tExT</div>
|
|
842
|
-
</section>
|
|
843
|
-
`
|
|
844
|
-
|
|
845
|
-
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
846
|
-
const injections = [
|
|
847
|
-
generateInjection('Some text', 'Some'),
|
|
848
|
-
generateInjection('Some OTHER Text ', 'Some'),
|
|
849
|
-
generateInjection('Somethird text', 'Some'),
|
|
850
|
-
]
|
|
851
|
-
|
|
852
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
853
|
-
|
|
854
|
-
expect(document.querySelectorAll('a')).toHaveLength(3)
|
|
855
|
-
})
|
|
856
|
-
|
|
857
|
-
it('Should properly inject into lists', () => {
|
|
858
|
-
document.body.innerHTML = `<section>
|
|
859
|
-
<ul>
|
|
860
|
-
<li>First</li>
|
|
861
|
-
<li>Title</li>
|
|
862
|
-
<li>Some other title</li>
|
|
863
|
-
<li>Fourth</li>
|
|
864
|
-
</ul>
|
|
865
|
-
</section>
|
|
866
|
-
`
|
|
867
|
-
|
|
868
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
869
|
-
const injections = [
|
|
870
|
-
generateInjection('First Title Some other title', 'First'),
|
|
871
|
-
generateInjection('First Title Some other title', 'Title'),
|
|
872
|
-
generateInjection('First Title Some other title', 'Some other title'),
|
|
873
|
-
generateInjection('First Title Some other title', 'Fourth'),
|
|
874
|
-
]
|
|
875
|
-
|
|
876
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
877
|
-
|
|
878
|
-
expect(document.querySelectorAll('a')).toHaveLength(4)
|
|
879
|
-
})
|
|
880
|
-
|
|
881
|
-
it('Should properly inject into lists of titles that contain special characters', () => {
|
|
882
|
-
document.body.innerHTML = `<section>
|
|
883
|
-
<ul>
|
|
884
|
-
<li>Daisy Jones & The Six</li>
|
|
885
|
-
<li>Love & Death</li>
|
|
886
|
-
</ul>
|
|
887
|
-
</section>
|
|
888
|
-
`
|
|
889
|
-
|
|
890
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
891
|
-
const injections = [
|
|
892
|
-
generateInjection('Daisy Jones & The Six', 'Daisy Jones & The Six'),
|
|
893
|
-
generateInjection('Love & Death', 'Love & Death'),
|
|
894
|
-
]
|
|
895
|
-
|
|
896
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
897
|
-
|
|
898
|
-
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
899
|
-
})
|
|
900
|
-
|
|
901
|
-
it('Should properly inject into titles that are split up by multiple elements when phrase_before and phrase_after are given', () => {
|
|
902
|
-
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong> in it</section>'
|
|
903
|
-
|
|
904
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
905
|
-
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
906
|
-
injection.phrase_before = 'with a'
|
|
907
|
-
injection.phrase_after = 'in it'
|
|
908
|
-
|
|
909
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
910
|
-
|
|
911
|
-
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
912
|
-
})
|
|
913
|
-
|
|
914
|
-
it('Should not inject when phrase_before and phrase_after are given, but the index would split HTML elements before the phrase', () => {
|
|
915
|
-
document.body.innerHTML = '<section>Some text <a href="#">with a phr</a>ase in it</section>'
|
|
916
|
-
|
|
917
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
918
|
-
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
919
|
-
injection.phrase_before = 'with a'
|
|
920
|
-
injection.phrase_after = 'in it'
|
|
921
|
-
|
|
922
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
923
|
-
|
|
924
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
925
|
-
})
|
|
926
|
-
|
|
927
|
-
it('Should properly inject into titles that are split up by multiple elements when only phrase_before is given', () => {
|
|
928
|
-
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong></section>'
|
|
929
|
-
|
|
930
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
931
|
-
const injection = generateInjection('Some text with a phrase', 'phrase')
|
|
932
|
-
injection.phrase_before = 'with a'
|
|
933
|
-
|
|
934
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
935
|
-
|
|
936
|
-
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
937
|
-
})
|
|
938
|
-
|
|
939
|
-
it('Should properly inject into titles that are split up by multiple elements when only phrase_after is given', () => {
|
|
940
|
-
document.body.innerHTML = '<section><strong>phra</strong><strong>se</strong> in it</section>'
|
|
941
|
-
|
|
942
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
943
|
-
const injection = generateInjection('phrase in it', 'phrase')
|
|
944
|
-
injection.phrase_after = 'in it'
|
|
945
|
-
|
|
946
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
947
|
-
|
|
948
|
-
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
949
|
-
})
|
|
950
|
-
|
|
951
|
-
it('Should properly inject into titles if phrase_before or phrase_after are nonsense, but title can be matched simply', () => {
|
|
952
|
-
document.body.innerHTML = '<section>Some text with a phrase in it</section>'
|
|
953
|
-
|
|
954
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
955
|
-
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
956
|
-
injection.phrase_before = 'random'
|
|
957
|
-
injection.phrase_after = 'crap'
|
|
958
|
-
|
|
959
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
960
|
-
|
|
961
|
-
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
962
|
-
})
|
|
963
|
-
|
|
964
|
-
it('Should properly inject into titles that are split up by multiple elements when neither phrase_before or phrase_after are given but the phrase occurs only once', () => {
|
|
965
|
-
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong> in it</section>'
|
|
966
|
-
|
|
967
|
-
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
968
|
-
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
969
|
-
|
|
970
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
971
|
-
|
|
972
|
-
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
973
|
-
})
|
|
974
|
-
|
|
975
|
-
it('Should replace existing PlayPilot links', () => {
|
|
976
|
-
document.body.innerHTML = '<p>This is a sentence with <a href="https://playpilot.com/movie/123">an injection</a>.</p>'
|
|
977
|
-
|
|
978
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
979
|
-
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
980
|
-
|
|
981
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
982
|
-
|
|
983
|
-
expect(document.querySelector('a')?.closest('[data-playpilot-injection-key]')).toBeTruthy()
|
|
984
|
-
})
|
|
985
|
-
|
|
986
|
-
describe('Participants', () => {
|
|
987
|
-
it('Should inject participants just as a title', () => {
|
|
988
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
989
|
-
|
|
990
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
991
|
-
const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: participants[0] }
|
|
992
|
-
|
|
993
|
-
// @ts-ignore
|
|
994
|
-
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
995
|
-
|
|
996
|
-
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
997
|
-
})
|
|
998
|
-
|
|
999
|
-
it('Should ignore participants below a given popularity threshold', () => {
|
|
1000
|
-
window.PlayPilotLinkInjections.config = {
|
|
1001
|
-
participant_injection_popularity_threshold: 50,
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1005
|
-
|
|
1006
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1007
|
-
|
|
1008
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1009
|
-
const injections = [
|
|
1010
|
-
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', participant_details: { ...participants[0], popularity: 20 } },
|
|
1011
|
-
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: { ...participants[0], popularity: 70 } },
|
|
1012
|
-
]
|
|
1013
|
-
|
|
1014
|
-
// @ts-ignore
|
|
1015
|
-
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1016
|
-
|
|
1017
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
1018
|
-
})
|
|
1019
|
-
|
|
1020
|
-
it('Should ignore participants popularity for manual injections', () => {
|
|
1021
|
-
window.PlayPilotLinkInjections.config = {
|
|
1022
|
-
participant_injection_popularity_threshold_use_article_average: false,
|
|
1023
|
-
participant_injection_popularity_threshold: 50,
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1027
|
-
|
|
1028
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1029
|
-
|
|
1030
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1031
|
-
const injections = [
|
|
1032
|
-
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', manual: true, participant_details: { ...participants[0], popularity: 20 } },
|
|
1033
|
-
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', manual: true, participant_details: { ...participants[0], popularity: 70 } },
|
|
1034
|
-
]
|
|
1035
|
-
|
|
1036
|
-
// @ts-ignore
|
|
1037
|
-
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
1038
|
-
|
|
1039
|
-
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
1040
|
-
})
|
|
1041
|
-
|
|
1042
|
-
it('Should include injection type on element', () => {
|
|
1043
|
-
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1044
|
-
|
|
1045
|
-
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1046
|
-
const injections = [
|
|
1047
|
-
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', participant_details: participants[0] },
|
|
1048
|
-
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'title' },
|
|
1049
|
-
]
|
|
1050
|
-
|
|
1051
|
-
// @ts-ignore
|
|
1052
|
-
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1053
|
-
|
|
1054
|
-
expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[0]).dataset.playpilotInjectionType).toBe('participant')
|
|
1055
|
-
expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[1]).dataset.playpilotInjectionType).toBe('title')
|
|
1056
|
-
})
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
})
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
]
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
expect(
|
|
1250
|
-
})
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
it('Should return
|
|
1262
|
-
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1263
|
-
const manualInjection = { ...aiInjection, manual: true }
|
|
1264
|
-
|
|
1265
|
-
expect(
|
|
1266
|
-
})
|
|
1267
|
-
|
|
1268
|
-
it('Should return
|
|
1269
|
-
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
it('Should
|
|
1283
|
-
const
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
expect(filterRemovedAndInactiveInjections([
|
|
1287
|
-
})
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
expect(
|
|
1301
|
-
})
|
|
1302
|
-
|
|
1303
|
-
it('Should return
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
expect(
|
|
1315
|
-
})
|
|
1316
|
-
})
|
|
1317
|
-
|
|
1318
|
-
describe('
|
|
1319
|
-
it('Should return
|
|
1320
|
-
expect(
|
|
1321
|
-
})
|
|
1322
|
-
|
|
1323
|
-
it('Should return
|
|
1324
|
-
expect(
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
expect(
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
expect(
|
|
1339
|
-
expect(
|
|
1340
|
-
expect(
|
|
1341
|
-
expect(
|
|
1342
|
-
expect(
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
expect(
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
expect(
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
expect(
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
expect(
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
expect(
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
expect(
|
|
1430
|
-
})
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
expect(
|
|
1469
|
-
})
|
|
1470
|
-
|
|
1471
|
-
it('Should not
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
const
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
const truthyParticipant = { ...participants[0], popularity: 0 }
|
|
1524
|
-
const truthyParticipant2 = { ...participants[0], popularity: 60 }
|
|
1525
|
-
|
|
1526
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1527
|
-
const injections = [
|
|
1528
|
-
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1529
|
-
]
|
|
1530
|
-
|
|
1531
|
-
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1532
|
-
expect(doesParticipantMeetThreshold(injections, truthyParticipant2)).toBe(true)
|
|
1533
|
-
})
|
|
1534
|
-
|
|
1535
|
-
it('Should use threshold of 0 by default', () => {
|
|
1536
|
-
const truthyParticipant = { ...participants[0], popularity: 0 }
|
|
1537
|
-
const truthyParticipant2 = { ...participants[0], popularity: 1 }
|
|
1538
|
-
|
|
1539
|
-
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1540
|
-
const injections = [
|
|
1541
|
-
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1542
|
-
]
|
|
1543
|
-
|
|
1544
|
-
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1545
|
-
expect(doesParticipantMeetThreshold(injections, truthyParticipant2)).toBe(true)
|
|
1546
|
-
})
|
|
1547
|
-
})
|
|
1548
|
-
})
|
|
1
|
+
import { fireEvent } from '@testing-library/svelte'
|
|
2
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType, removePlayPilotTitleLinks, hasValidTypeData, doesParticipantMeetThreshold } from '$lib/injection'
|
|
5
|
+
import { mount, unmount } from 'svelte'
|
|
6
|
+
import { fakeFetch, generateInjection } from '../helpers'
|
|
7
|
+
import { openModalForInjectedLink } from '$lib/modal'
|
|
8
|
+
import { getLinkInjectionElements } from '$lib/injectionElements'
|
|
9
|
+
import { participants } from '$lib/fakeData'
|
|
10
|
+
import { titleUrl } from '$lib/routes'
|
|
11
|
+
|
|
12
|
+
vi.mock('svelte', () => ({
|
|
13
|
+
mount: vi.fn(),
|
|
14
|
+
unmount: vi.fn(),
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
vi.mock('$lib/modal', () => ({
|
|
18
|
+
openModal: vi.fn(),
|
|
19
|
+
destroyAllModals: vi.fn(),
|
|
20
|
+
getPreviousModal: vi.fn(),
|
|
21
|
+
goBackToPreviousModal: vi.fn(),
|
|
22
|
+
openModalForInjectedLink: vi.fn(),
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
vi.mock('$lib/tracking', () => ({
|
|
26
|
+
track: vi.fn(),
|
|
27
|
+
}))
|
|
28
|
+
|
|
29
|
+
function mockMatchMedia(matches = false) {
|
|
30
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
31
|
+
writable: true,
|
|
32
|
+
value: vi.fn().mockImplementation((query) => ({
|
|
33
|
+
matches,
|
|
34
|
+
media: query,
|
|
35
|
+
})),
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('injection.ts', () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
vi.resetAllMocks()
|
|
42
|
+
clearLinkInjections()
|
|
43
|
+
|
|
44
|
+
mockMatchMedia()
|
|
45
|
+
fakeFetch()
|
|
46
|
+
vi.mocked(mount).mockReturnValueOnce({})
|
|
47
|
+
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
window.PlayPilotLinkInjections = {}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
vi.useRealTimers()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('injectLinksInDocument', () => {
|
|
57
|
+
it('Should replace given words with injections', () => {
|
|
58
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
59
|
+
const linkInjections = [injection]
|
|
60
|
+
|
|
61
|
+
document.body.innerHTML = `<p>${injection.sentence}</p>`
|
|
62
|
+
|
|
63
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
64
|
+
|
|
65
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
66
|
+
|
|
67
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
68
|
+
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
expect(link.href).toBe(titleUrl(injection.title_details))
|
|
71
|
+
expect(link.innerText).toBe(injection.title)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('Should replace given words as expected when more than 1 injection per sentence is present', () => {
|
|
75
|
+
const sentence = 'This is a sentence with an injection.'
|
|
76
|
+
const linkInjections = [
|
|
77
|
+
generateInjection(sentence, 'a sentence'),
|
|
78
|
+
generateInjection(sentence, 'an injection'),
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
82
|
+
|
|
83
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
84
|
+
|
|
85
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
86
|
+
|
|
87
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
88
|
+
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
expect(links[0].href).toBe(titleUrl(linkInjections[0].title_details))
|
|
91
|
+
expect(links[0].innerText).toBe(linkInjections[0].title)
|
|
92
|
+
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
expect(links[1].href).toBe(titleUrl(linkInjections[1].title_details))
|
|
95
|
+
expect(links[1].innerText).toBe(linkInjections[1].title)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('Should ignore injections that are marked as inactive', () => {
|
|
99
|
+
const sentence = 'This is a sentence with an injection.'
|
|
100
|
+
const injection = generateInjection(sentence, 'an injection')
|
|
101
|
+
const linkInjections = [{ ...injection, inactive: true }]
|
|
102
|
+
|
|
103
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
104
|
+
|
|
105
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
106
|
+
|
|
107
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
108
|
+
|
|
109
|
+
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('Should ignore injections that are marked as removed', () => {
|
|
113
|
+
const sentence = 'This is a sentence with an injection.'
|
|
114
|
+
const injection = generateInjection(sentence, 'an injection')
|
|
115
|
+
const linkInjections = [{ ...injection, removed: true }]
|
|
116
|
+
|
|
117
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
118
|
+
|
|
119
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
120
|
+
|
|
121
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
122
|
+
|
|
123
|
+
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('Should ignore AI injections that are marked as removed as a matching manual injections', () => {
|
|
127
|
+
const sentence = 'This is a sentence with an injection.'
|
|
128
|
+
const injection = generateInjection(sentence, 'an injection')
|
|
129
|
+
|
|
130
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
131
|
+
|
|
132
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
133
|
+
|
|
134
|
+
const injections = {
|
|
135
|
+
aiInjections: [injection],
|
|
136
|
+
manualInjections: [{ ...injection, manual: true, removed: true }],
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
injectLinksInDocument(elements, injections)
|
|
140
|
+
|
|
141
|
+
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('Should ignore AI injections that are marked as inactive as a matching manual injections', () => {
|
|
145
|
+
const sentence = 'This is a sentence with an injection.'
|
|
146
|
+
const injection = generateInjection(sentence, 'an injection')
|
|
147
|
+
|
|
148
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
149
|
+
|
|
150
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
151
|
+
|
|
152
|
+
const injections = {
|
|
153
|
+
aiInjections: [injection],
|
|
154
|
+
manualInjections: [{ ...injection, manual: true, inactive: true }],
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
injectLinksInDocument(elements, injections)
|
|
158
|
+
|
|
159
|
+
expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('Should keep existing HTML elements intact', () => {
|
|
163
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
164
|
+
const linkInjections = [injection]
|
|
165
|
+
|
|
166
|
+
document.body.innerHTML = '<p>This is a <button>sentence</button> with an injection.</p>'
|
|
167
|
+
|
|
168
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
169
|
+
|
|
170
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
171
|
+
|
|
172
|
+
const button = /** @type {HTMLButtonElement} */ (document.querySelector('button'))
|
|
173
|
+
|
|
174
|
+
expect(button.innerText).toBe('sentence')
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('Should ignore elements that were not selected', () => {
|
|
178
|
+
document.body.innerHTML = '<h1>I am a title</h1><p>This is a sentence with an injection.</p>'
|
|
179
|
+
|
|
180
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
181
|
+
const injection = generateInjection('I am a title', 'a title')
|
|
182
|
+
|
|
183
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
184
|
+
|
|
185
|
+
expect(document.body.innerHTML.includes(injection.sentence)).toBeTruthy()
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it('Should ignore partial matches due to interfering elements', () => {
|
|
189
|
+
document.body.innerHTML = '<p>This is a sentence with <strong>an</strong> injection.</p>'
|
|
190
|
+
|
|
191
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
192
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
193
|
+
|
|
194
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
195
|
+
|
|
196
|
+
expect(document.body.innerHTML.includes('an injection')).not.toBeTruthy()
|
|
197
|
+
expect(document.body.innerHTML.includes('an')).toBeTruthy()
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('Should ignore encoded characters in given sentences', () => {
|
|
201
|
+
document.body.innerHTML = '<p>This is a sentence & an injection.</p>'
|
|
202
|
+
|
|
203
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
204
|
+
const injection = generateInjection('This is a sentence & an injection.', 'an injection')
|
|
205
|
+
|
|
206
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
207
|
+
|
|
208
|
+
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('Should ignore matches due to parent links', () => {
|
|
212
|
+
document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
|
|
213
|
+
|
|
214
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
215
|
+
const injection = generateInjection('This is a sentence with an injection.', 'a sentence')
|
|
216
|
+
|
|
217
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
218
|
+
|
|
219
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('Should ignore matches inside of attributes inside of links', () => {
|
|
223
|
+
document.body.innerHTML = '<p>This is <a data-thing="some word">a sentence</a> with an injection.</p>'
|
|
224
|
+
|
|
225
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
226
|
+
const injection = generateInjection('This is a sentence with an injection.', 'some word')
|
|
227
|
+
|
|
228
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
229
|
+
|
|
230
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it('Should ignore matches inside of attributes inside of links but still inject into other matches', () => {
|
|
234
|
+
document.body.innerHTML = '<p>This is <a data-thing="some word">some word</a> with an injection in some word.</p>'
|
|
235
|
+
|
|
236
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
237
|
+
const injection = generateInjection('This is some word with an injection in some word.', 'some word')
|
|
238
|
+
|
|
239
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
240
|
+
|
|
241
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
242
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('Should skip links and replace other words instead', () => {
|
|
246
|
+
document.body.innerHTML = '<p>This is <a>a word</a> with a word.</p>'
|
|
247
|
+
|
|
248
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
249
|
+
const injection = generateInjection('This is a word with a word.', 'a word')
|
|
250
|
+
|
|
251
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
252
|
+
|
|
253
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
254
|
+
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
it('Should skip links inside of other elements and replace other words instead', () => {
|
|
258
|
+
document.body.innerHTML = '<p>This is <em><a>a word</a></em> with a word.</p>'
|
|
259
|
+
|
|
260
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
261
|
+
const injection = generateInjection('This is a word with a word.', 'a word')
|
|
262
|
+
|
|
263
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
264
|
+
|
|
265
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
266
|
+
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
it('Should skip partial matches in sentences that are broken up by different nodes but have the same match', () => {
|
|
270
|
+
document.body.innerHTML = '<p>This is <a>a word</a> with a word.</p>'
|
|
271
|
+
|
|
272
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
273
|
+
const injection = generateInjection('this is a word with a word.', 'a word')
|
|
274
|
+
|
|
275
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
276
|
+
|
|
277
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
278
|
+
expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
|
|
279
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it('Should inject into correct sentence when element contains other sentences with the same matching title', () => {
|
|
283
|
+
document.body.innerHTML = '<p>This is a match. But this sentence is a match.</p>'
|
|
284
|
+
|
|
285
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
286
|
+
const injection = generateInjection('But this sentence is a match.', 'a match')
|
|
287
|
+
|
|
288
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
289
|
+
|
|
290
|
+
expect(document.body.innerHTML).toContain('This is a match')
|
|
291
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
it('Should inject properly when sentence contains element that are not part of the match', () => {
|
|
295
|
+
document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
|
|
296
|
+
|
|
297
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
298
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
299
|
+
|
|
300
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
301
|
+
|
|
302
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('Should inject correctly when sentence is broken up by html and element contains multiple matches', () => {
|
|
306
|
+
document.body.innerHTML = '<p>This is some match. Some other sentence with a match. But this is yet another <em>sentence</em> with a match.</p>'
|
|
307
|
+
|
|
308
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
309
|
+
|
|
310
|
+
const injections = [
|
|
311
|
+
generateInjection('This is some match.', 'some match'),
|
|
312
|
+
generateInjection('But this is yet another sentence with a match.', 'a match'),
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
316
|
+
|
|
317
|
+
expect(document.body.innerHTML).toContain('Some other sentence with a match')
|
|
318
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('Should disregard missing trailing periods', () => {
|
|
322
|
+
document.body.innerHTML = '<p>This is a sentence with a phrase in it</p>'
|
|
323
|
+
|
|
324
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
325
|
+
const injection = generateInjection('This is a sentence with a phrase in it.', 'a phrase')
|
|
326
|
+
|
|
327
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
328
|
+
|
|
329
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
it('Should disregard additional quotes', () => {
|
|
333
|
+
document.body.innerHTML = '<p>This is part of a paragraph. This is a sentence with a phrase in it."</p>'
|
|
334
|
+
|
|
335
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
336
|
+
const injection = generateInjection('"This is a sentence with a phrase in it."', 'a phrase')
|
|
337
|
+
|
|
338
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
339
|
+
|
|
340
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
it('Should disregard differences in accents', () => {
|
|
344
|
+
document.body.innerHTML = '<p>This is à sentence with a phràse in it."</p>'
|
|
345
|
+
|
|
346
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
347
|
+
const injection = generateInjection('This is a sentence with a phrase in it.', 'a phràse')
|
|
348
|
+
|
|
349
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
350
|
+
|
|
351
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('Should treat different types of quotes as the same', () => {
|
|
355
|
+
document.body.innerHTML = '<p>This is a “sentence” with a "phrase" in it.</p>'
|
|
356
|
+
|
|
357
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
358
|
+
const injection = generateInjection('This is a "sentence" with a \'phrase’ in it.', 'phrase')
|
|
359
|
+
|
|
360
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
361
|
+
|
|
362
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
it('Should disregard differences in special characters', () => {
|
|
366
|
+
document.body.innerHTML = '<p>This -> is a sentence, with a phrase - in it.</p>'
|
|
367
|
+
|
|
368
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
369
|
+
const injection = generateInjection('This is a sentence with a _phrase_ in it.', 'phrase')
|
|
370
|
+
|
|
371
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
372
|
+
|
|
373
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
it('Should leave the text intact if no injections were found', () => {
|
|
377
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
378
|
+
|
|
379
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
380
|
+
|
|
381
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
382
|
+
const linkInjections = []
|
|
383
|
+
|
|
384
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
385
|
+
|
|
386
|
+
expect(document.body.innerHTML.includes('This is a sentence with an injection.')).toBeTruthy()
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
it('Should handle not receiving elements or injections', () => {
|
|
390
|
+
/** @type {HTMLElement[]} */
|
|
391
|
+
const elements = []
|
|
392
|
+
|
|
393
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
394
|
+
const linkInjections = []
|
|
395
|
+
|
|
396
|
+
expect(() => injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })).not.toThrow()
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
it('Should open modal when link is clicked', async () => {
|
|
400
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
401
|
+
|
|
402
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
403
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
404
|
+
|
|
405
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
406
|
+
|
|
407
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
408
|
+
await fireEvent.click(link)
|
|
409
|
+
|
|
410
|
+
expect(openModalForInjectedLink).toHaveBeenCalled()
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it('Should not fire given onclick function when clicked with modifier keys or not left click', async () => {
|
|
414
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
415
|
+
|
|
416
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
417
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
418
|
+
|
|
419
|
+
const mock = vi.fn()
|
|
420
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
421
|
+
|
|
422
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
423
|
+
|
|
424
|
+
await fireEvent.click(link, { ctrlKey: true })
|
|
425
|
+
await fireEvent.click(link, { metaKey: true })
|
|
426
|
+
await fireEvent.click(link, { button: 1 })
|
|
427
|
+
await fireEvent.click(link, { button: 2 })
|
|
428
|
+
|
|
429
|
+
expect(mock).not.toHaveBeenCalled()
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it('Should return array with failed injections marked as such', () => {
|
|
433
|
+
const sentence = 'This is a sentence with an injection.'
|
|
434
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
435
|
+
|
|
436
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
437
|
+
|
|
438
|
+
const linkInjections = [
|
|
439
|
+
generateInjection(sentence, 'a sentence'),
|
|
440
|
+
generateInjection(sentence, 'not an injection'),
|
|
441
|
+
]
|
|
442
|
+
|
|
443
|
+
const results = injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
444
|
+
|
|
445
|
+
expect(results[0].failed).toBe(false)
|
|
446
|
+
expect(results[1].failed).toBe(true)
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
it('Should return corresponding messages for failed injections', () => {
|
|
450
|
+
const sentence = 'This is <a href="/">a sentence</a> with an injection.'
|
|
451
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
452
|
+
|
|
453
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
454
|
+
|
|
455
|
+
const manuallyRemoved = generateInjection(sentence, 'an injection')
|
|
456
|
+
|
|
457
|
+
const linkInjections = [
|
|
458
|
+
generateInjection(sentence, 'a sentence'),
|
|
459
|
+
generateInjection('Some unknown sentence', 'nothing'),
|
|
460
|
+
{ ...manuallyRemoved, duplicate: true, removed: true, manual: true },
|
|
461
|
+
]
|
|
462
|
+
|
|
463
|
+
const results = injectLinksInDocument(elements, { aiInjections: [manuallyRemoved], manualInjections: linkInjections })
|
|
464
|
+
|
|
465
|
+
expect(results[0].failed_message).toBe('Given text is already inside of a link.')
|
|
466
|
+
expect(results[1].failed_message).toBe('Given sentence was not found in the article.')
|
|
467
|
+
expect(results[2].failed_message).toBe('')
|
|
468
|
+
expect(results[3].failed_message).toBe('Injection was manually removed.')
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
it('Should return sentence message if text was found in full body text but not in individual elements', () => {
|
|
472
|
+
document.body.innerHTML = '<article><p>Some sentence</p><p>that is broken in two</p></main>'
|
|
473
|
+
|
|
474
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
475
|
+
const linkInjections = [generateInjection('Some sentence that is broken in two', 'broken')]
|
|
476
|
+
|
|
477
|
+
const results = injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
478
|
+
|
|
479
|
+
expect(results[0].failed_message).toBe('Given sentence was not found in the article.')
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
it('Should disregard spaces and special characters in failed message', () => {
|
|
483
|
+
const sentence = 'This is a & sentence with an injection.'
|
|
484
|
+
document.body.innerHTML = `<p>${sentence}</p>`
|
|
485
|
+
|
|
486
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
487
|
+
|
|
488
|
+
const linkInjections = [
|
|
489
|
+
generateInjection('This is a&sentence with aninjection.', 'an injection'),
|
|
490
|
+
generateInjection('This is a&sentence with aninjection.', 'nothing'),
|
|
491
|
+
]
|
|
492
|
+
|
|
493
|
+
const results = injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
494
|
+
|
|
495
|
+
expect(results[0].failed_message).not.toBeTruthy()
|
|
496
|
+
expect(results[1].failed_message).toBe('The link failed to inject for unknown reasons.')
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
it('Should mount popover component when element other than popover or link is hovered', async () => {
|
|
500
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
501
|
+
|
|
502
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
503
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
504
|
+
|
|
505
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
506
|
+
|
|
507
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
508
|
+
|
|
509
|
+
vi.useFakeTimers()
|
|
510
|
+
|
|
511
|
+
await fireEvent.mouseEnter(link)
|
|
512
|
+
vi.advanceTimersByTime(200)
|
|
513
|
+
expect(mount).toHaveBeenCalled()
|
|
514
|
+
|
|
515
|
+
await fireEvent.mouseMove(link)
|
|
516
|
+
expect(unmount).not.toHaveBeenCalled()
|
|
517
|
+
|
|
518
|
+
await fireEvent.mouseMove(document.body)
|
|
519
|
+
expect(unmount).toHaveBeenCalled()
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
it('Should mount popover on mouseover again after previously having mounted and unmounted that same popover', async () => {
|
|
523
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
524
|
+
|
|
525
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
526
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
527
|
+
|
|
528
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
529
|
+
|
|
530
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
531
|
+
|
|
532
|
+
vi.useFakeTimers()
|
|
533
|
+
|
|
534
|
+
await fireEvent.mouseEnter(link)
|
|
535
|
+
vi.advanceTimersByTime(200)
|
|
536
|
+
await fireEvent.mouseMove(document.body)
|
|
537
|
+
await fireEvent.mouseEnter(link)
|
|
538
|
+
vi.advanceTimersByTime(200)
|
|
539
|
+
|
|
540
|
+
expect(mount).toHaveBeenCalledTimes(2)
|
|
541
|
+
})
|
|
542
|
+
|
|
543
|
+
it('Should not mount popover on mouseover if not hovered for long enough duration', async () => {
|
|
544
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
545
|
+
|
|
546
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
547
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
548
|
+
|
|
549
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
550
|
+
|
|
551
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
552
|
+
|
|
553
|
+
vi.useFakeTimers()
|
|
554
|
+
|
|
555
|
+
await fireEvent.mouseEnter(link)
|
|
556
|
+
vi.advanceTimersByTime(50)
|
|
557
|
+
await fireEvent.mouseLeave(link)
|
|
558
|
+
vi.advanceTimersByTime(500)
|
|
559
|
+
|
|
560
|
+
expect(mount).not.toHaveBeenCalled()
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
it('Should not mount popover on mouseover again if link is already being hovered', async () => {
|
|
564
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
565
|
+
|
|
566
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
567
|
+
const injections = [
|
|
568
|
+
generateInjection('This is a sentence with an injection.', 'a sentence'),
|
|
569
|
+
generateInjection('This is a sentence with an injection.', 'an injection'),
|
|
570
|
+
]
|
|
571
|
+
|
|
572
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
573
|
+
|
|
574
|
+
const [link1, link2] = document.querySelectorAll('[data-playpilot-injection-key]')
|
|
575
|
+
|
|
576
|
+
vi.useFakeTimers()
|
|
577
|
+
|
|
578
|
+
await fireEvent.mouseEnter(link1)
|
|
579
|
+
vi.advanceTimersByTime(200)
|
|
580
|
+
await fireEvent.mouseEnter(link2)
|
|
581
|
+
vi.advanceTimersByTime(500)
|
|
582
|
+
|
|
583
|
+
expect(mount).toHaveBeenCalledTimes(1)
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
it('Should remove all popovers that may not have been removed properly in previous destroy attempts', async () => {
|
|
587
|
+
document.body.innerHTML = '<div data-playpilot-injection-key></div><div data-playpilot-injection-popover></div> <p>This is a sentence with an injection.</p>'
|
|
588
|
+
|
|
589
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
590
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
591
|
+
|
|
592
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
593
|
+
|
|
594
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
|
|
595
|
+
|
|
596
|
+
vi.useFakeTimers()
|
|
597
|
+
|
|
598
|
+
await fireEvent.mouseEnter(link)
|
|
599
|
+
await fireEvent.mouseMove(document.body)
|
|
600
|
+
vi.advanceTimersByTime(200)
|
|
601
|
+
|
|
602
|
+
expect(document.querySelectorAll('[data-playpilot-injection-popover]')).toHaveLength(0)
|
|
603
|
+
})
|
|
604
|
+
|
|
605
|
+
it('Should inject links of the same phrase when multiple are present', () => {
|
|
606
|
+
document.body.innerHTML = '<p>This is a sentence with an injection and another injection</p>'
|
|
607
|
+
|
|
608
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
609
|
+
|
|
610
|
+
const sentence = 'This is a sentence with an injection and another injection'
|
|
611
|
+
const linkInjections = [
|
|
612
|
+
generateInjection(sentence, 'injection'),
|
|
613
|
+
generateInjection(sentence, 'injection'),
|
|
614
|
+
]
|
|
615
|
+
|
|
616
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
617
|
+
|
|
618
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
|
|
619
|
+
|
|
620
|
+
expect(links).toHaveLength(2)
|
|
621
|
+
expect(links[0].dataset.playpilotInjectionKey).toBe(linkInjections[0].key)
|
|
622
|
+
expect(links[1].dataset.playpilotInjectionKey).toBe(linkInjections[1].key)
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
it('Should inject links of the same phrase when multiple are present, but ignore injectios into links that contain the same phrase', () => {
|
|
626
|
+
document.body.innerHTML = '<p>First phrase, <a href="/phrase">second</a> phrase</p>'
|
|
627
|
+
|
|
628
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
629
|
+
|
|
630
|
+
const sentence = 'First phrase, second phrase'
|
|
631
|
+
const linkInjections = [
|
|
632
|
+
generateInjection(sentence, 'phrase'),
|
|
633
|
+
generateInjection(sentence, 'phrase'),
|
|
634
|
+
]
|
|
635
|
+
|
|
636
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
637
|
+
|
|
638
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
639
|
+
|
|
640
|
+
expect(links).toHaveLength(3)
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
it('Should inject link properly when sentence already contains match of the same phrase but the sentence is broken up by HTML very early in the sentence.', () => {
|
|
644
|
+
document.body.innerHTML = '<p>A <em><a>phrase</a></em> within a sentence. Another <strong>sentence</strong> with a <em>phrase</em> in it.</p>'
|
|
645
|
+
|
|
646
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
647
|
+
|
|
648
|
+
const linkInjections = [generateInjection('Another sentence with a phrase in it.', 'phrase')]
|
|
649
|
+
|
|
650
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
651
|
+
|
|
652
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
653
|
+
|
|
654
|
+
expect(links).toHaveLength(2)
|
|
655
|
+
})
|
|
656
|
+
|
|
657
|
+
it('Should inject link properly when sentence already contains partial match of the same phrase when the sentence is broken up by html.', () => {
|
|
658
|
+
document.body.innerHTML = '<p>Some sentence with a phrase: something, and another phrase.</p>'
|
|
659
|
+
|
|
660
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
661
|
+
|
|
662
|
+
const linkInjections = [
|
|
663
|
+
generateInjection('Some sentence with a phrase: something, and another phrase.', 'phrase: something'),
|
|
664
|
+
generateInjection('Some sentence with a phrase: something, and another phrase.', 'phrase'),
|
|
665
|
+
]
|
|
666
|
+
|
|
667
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
668
|
+
|
|
669
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
670
|
+
|
|
671
|
+
expect(links).toHaveLength(2)
|
|
672
|
+
})
|
|
673
|
+
|
|
674
|
+
it('Should inject longer titles before shorter titles', () => {
|
|
675
|
+
document.body.innerHTML = '<p>Some sentence with phrase 2, and another phrase.</p>'
|
|
676
|
+
|
|
677
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
678
|
+
|
|
679
|
+
const linkInjections = [
|
|
680
|
+
generateInjection('Some sentence with phrase 2, and another phrase.', 'phrase'),
|
|
681
|
+
generateInjection('Some sentence with phrase 2, and another phrase.', 'phrase 2'),
|
|
682
|
+
]
|
|
683
|
+
|
|
684
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
685
|
+
|
|
686
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
|
|
687
|
+
|
|
688
|
+
expect(links).toHaveLength(2)
|
|
689
|
+
expect(links[0].innerText).toBe('phrase 2')
|
|
690
|
+
expect(links[1].innerText).toBe('phrase')
|
|
691
|
+
})
|
|
692
|
+
|
|
693
|
+
it('Should not inject links into element attributes', () => {
|
|
694
|
+
document.body.innerHTML = '<p><span data-thing="phrase">Some</span> phrase</p>'
|
|
695
|
+
|
|
696
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
697
|
+
|
|
698
|
+
const sentence = 'Some phrase'
|
|
699
|
+
const linkInjections = [
|
|
700
|
+
generateInjection(sentence, 'phrase'),
|
|
701
|
+
generateInjection(sentence, 'phrase'),
|
|
702
|
+
]
|
|
703
|
+
|
|
704
|
+
injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
|
|
705
|
+
|
|
706
|
+
const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
|
|
707
|
+
|
|
708
|
+
expect(links).toHaveLength(1)
|
|
709
|
+
expect(document.body.innerText).toBe(sentence)
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
it('Should not inject injections with in_text set to false', () => {
|
|
713
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
714
|
+
|
|
715
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
716
|
+
const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), in_text: false }
|
|
717
|
+
|
|
718
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
719
|
+
|
|
720
|
+
expect(document.querySelector('a')).not.toBeTruthy()
|
|
721
|
+
})
|
|
722
|
+
|
|
723
|
+
it('Should not inject injections into already existing links when the page contains multiple sentences of the same text where one has an existing link and the other does not.', () => {
|
|
724
|
+
document.body.innerHTML = '<p>This is a <a href="#">phrase</a>.</p> <p>This is a phrase.</p>'
|
|
725
|
+
|
|
726
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
727
|
+
const injection = generateInjection('This is a phrase.', 'phrase')
|
|
728
|
+
|
|
729
|
+
injectLinksInDocument(elements, { aiInjections: [injection, injection], manualInjections: [] })
|
|
730
|
+
|
|
731
|
+
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
732
|
+
})
|
|
733
|
+
|
|
734
|
+
it('Should not inject injections into already existing links when multiple injections are present for the same phrase in the same sentence that only contain the phrase once and the phrase is broken up by HTML', () => {
|
|
735
|
+
document.body.innerHTML = '<p>This is a <strong>phr</strong>ase.</p>'
|
|
736
|
+
|
|
737
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
738
|
+
const injection = generateInjection('This is a phrase.', 'phrase')
|
|
739
|
+
|
|
740
|
+
injectLinksInDocument(elements, { aiInjections: [injection, injection], manualInjections: [] })
|
|
741
|
+
|
|
742
|
+
expect(document.querySelectorAll('a')).toHaveLength(1)
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
it('Should not mount popover if user uses touch', async () => {
|
|
746
|
+
mockMatchMedia(true)
|
|
747
|
+
|
|
748
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
749
|
+
|
|
750
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
751
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
752
|
+
|
|
753
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
754
|
+
|
|
755
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
756
|
+
|
|
757
|
+
await fireEvent.mouseEnter(link)
|
|
758
|
+
expect(mount).not.toHaveBeenCalled()
|
|
759
|
+
})
|
|
760
|
+
|
|
761
|
+
it('Should not call insertAfterArticlePlaylinks if injections only contain inactive or removed items', () => {
|
|
762
|
+
document.body.innerHTML = `<section>
|
|
763
|
+
<div>Some text</div>
|
|
764
|
+
<div>Some other text</div>
|
|
765
|
+
</section>
|
|
766
|
+
`
|
|
767
|
+
|
|
768
|
+
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
769
|
+
const injection = generateInjection('Some sentence', 'an injection')
|
|
770
|
+
const linkInjections = [{ ...injection, after_article: true, inactive: true }, { ...injection, after_article: true, removed: true }]
|
|
771
|
+
|
|
772
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
773
|
+
|
|
774
|
+
expect(mount).not.toHaveBeenCalled()
|
|
775
|
+
expect(document.querySelector('[data-playpilot-after-article-playlinks]')).not.toBeTruthy()
|
|
776
|
+
})
|
|
777
|
+
|
|
778
|
+
it('Should not call insertAfterArticlePlaylinks if article contains no valid injections', () => {
|
|
779
|
+
window.PlayPilotLinkInjections.config = {
|
|
780
|
+
in_text_disclaimer_enabled: true,
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
document.body.innerHTML = `<section>
|
|
784
|
+
<div>Some text</div>
|
|
785
|
+
<div>Some other text</div>
|
|
786
|
+
</section>
|
|
787
|
+
`
|
|
788
|
+
|
|
789
|
+
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
790
|
+
const injection = generateInjection('Some sentence', 'an injection')
|
|
791
|
+
const linkInjections = [{ ...injection, inactive: true }, { ...injection, removed: true }]
|
|
792
|
+
|
|
793
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
|
|
794
|
+
|
|
795
|
+
expect(mount).not.toHaveBeenCalled()
|
|
796
|
+
expect(document.querySelector('[data-playpilot-in-text-disclaimer]')).not.toBeTruthy()
|
|
797
|
+
})
|
|
798
|
+
|
|
799
|
+
it('Should call insertAfterArticlePlaylinks if article contains valid injections', () => {
|
|
800
|
+
window.PlayPilotLinkInjections.config = {
|
|
801
|
+
in_text_disclaimer_enabled: true,
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
document.body.innerHTML = '<p>Some sentence with an injection</p>'
|
|
805
|
+
|
|
806
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
807
|
+
const injection = generateInjection('Some sentence with an injection', 'an injection')
|
|
808
|
+
|
|
809
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
810
|
+
|
|
811
|
+
expect(mount).toHaveBeenCalled()
|
|
812
|
+
expect(document.querySelector('[data-playpilot-in-text-disclaimer]')).toBeTruthy()
|
|
813
|
+
})
|
|
814
|
+
|
|
815
|
+
it('Should treat sentences the same regardless of differences spaces', () => {
|
|
816
|
+
document.body.innerHTML = `<section>
|
|
817
|
+
<div>Some text</div>
|
|
818
|
+
<div>Someothertext</div>
|
|
819
|
+
<div>Some thirdtext</div>
|
|
820
|
+
<div>Some fourth text </div>
|
|
821
|
+
</section>
|
|
822
|
+
`
|
|
823
|
+
|
|
824
|
+
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
825
|
+
const injections = [
|
|
826
|
+
generateInjection('Sometext', 'Some'),
|
|
827
|
+
generateInjection('Some other text ', 'Some'),
|
|
828
|
+
generateInjection('Somethird text', 'Some'),
|
|
829
|
+
generateInjection('Some fourthtext', 'Some'),
|
|
830
|
+
]
|
|
831
|
+
|
|
832
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
833
|
+
|
|
834
|
+
expect(document.querySelectorAll('a')).toHaveLength(4)
|
|
835
|
+
})
|
|
836
|
+
|
|
837
|
+
it('Should treat sentences the same regardless of casings', () => {
|
|
838
|
+
document.body.innerHTML = `<section>
|
|
839
|
+
<div>Some text</div>
|
|
840
|
+
<div>Some OTHER TEXT</div>
|
|
841
|
+
<div>Some ThIrD tExT</div>
|
|
842
|
+
</section>
|
|
843
|
+
`
|
|
844
|
+
|
|
845
|
+
const elements = Array.from(document.body.querySelectorAll('div'))
|
|
846
|
+
const injections = [
|
|
847
|
+
generateInjection('Some text', 'Some'),
|
|
848
|
+
generateInjection('Some OTHER Text ', 'Some'),
|
|
849
|
+
generateInjection('Somethird text', 'Some'),
|
|
850
|
+
]
|
|
851
|
+
|
|
852
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
853
|
+
|
|
854
|
+
expect(document.querySelectorAll('a')).toHaveLength(3)
|
|
855
|
+
})
|
|
856
|
+
|
|
857
|
+
it('Should properly inject into lists', () => {
|
|
858
|
+
document.body.innerHTML = `<section>
|
|
859
|
+
<ul>
|
|
860
|
+
<li>First</li>
|
|
861
|
+
<li>Title</li>
|
|
862
|
+
<li>Some other title</li>
|
|
863
|
+
<li>Fourth</li>
|
|
864
|
+
</ul>
|
|
865
|
+
</section>
|
|
866
|
+
`
|
|
867
|
+
|
|
868
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
869
|
+
const injections = [
|
|
870
|
+
generateInjection('First Title Some other title', 'First'),
|
|
871
|
+
generateInjection('First Title Some other title', 'Title'),
|
|
872
|
+
generateInjection('First Title Some other title', 'Some other title'),
|
|
873
|
+
generateInjection('First Title Some other title', 'Fourth'),
|
|
874
|
+
]
|
|
875
|
+
|
|
876
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
877
|
+
|
|
878
|
+
expect(document.querySelectorAll('a')).toHaveLength(4)
|
|
879
|
+
})
|
|
880
|
+
|
|
881
|
+
it('Should properly inject into lists of titles that contain special characters', () => {
|
|
882
|
+
document.body.innerHTML = `<section>
|
|
883
|
+
<ul>
|
|
884
|
+
<li>Daisy Jones & The Six</li>
|
|
885
|
+
<li>Love & Death</li>
|
|
886
|
+
</ul>
|
|
887
|
+
</section>
|
|
888
|
+
`
|
|
889
|
+
|
|
890
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
891
|
+
const injections = [
|
|
892
|
+
generateInjection('Daisy Jones & The Six', 'Daisy Jones & The Six'),
|
|
893
|
+
generateInjection('Love & Death', 'Love & Death'),
|
|
894
|
+
]
|
|
895
|
+
|
|
896
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
897
|
+
|
|
898
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
899
|
+
})
|
|
900
|
+
|
|
901
|
+
it('Should properly inject into titles that are split up by multiple elements when phrase_before and phrase_after are given', () => {
|
|
902
|
+
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong> in it</section>'
|
|
903
|
+
|
|
904
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
905
|
+
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
906
|
+
injection.phrase_before = 'with a'
|
|
907
|
+
injection.phrase_after = 'in it'
|
|
908
|
+
|
|
909
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
910
|
+
|
|
911
|
+
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
912
|
+
})
|
|
913
|
+
|
|
914
|
+
it('Should not inject when phrase_before and phrase_after are given, but the index would split HTML elements before the phrase', () => {
|
|
915
|
+
document.body.innerHTML = '<section>Some text <a href="#">with a phr</a>ase in it</section>'
|
|
916
|
+
|
|
917
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
918
|
+
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
919
|
+
injection.phrase_before = 'with a'
|
|
920
|
+
injection.phrase_after = 'in it'
|
|
921
|
+
|
|
922
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
923
|
+
|
|
924
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
|
|
925
|
+
})
|
|
926
|
+
|
|
927
|
+
it('Should properly inject into titles that are split up by multiple elements when only phrase_before is given', () => {
|
|
928
|
+
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong></section>'
|
|
929
|
+
|
|
930
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
931
|
+
const injection = generateInjection('Some text with a phrase', 'phrase')
|
|
932
|
+
injection.phrase_before = 'with a'
|
|
933
|
+
|
|
934
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
935
|
+
|
|
936
|
+
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
937
|
+
})
|
|
938
|
+
|
|
939
|
+
it('Should properly inject into titles that are split up by multiple elements when only phrase_after is given', () => {
|
|
940
|
+
document.body.innerHTML = '<section><strong>phra</strong><strong>se</strong> in it</section>'
|
|
941
|
+
|
|
942
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
943
|
+
const injection = generateInjection('phrase in it', 'phrase')
|
|
944
|
+
injection.phrase_after = 'in it'
|
|
945
|
+
|
|
946
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
947
|
+
|
|
948
|
+
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
949
|
+
})
|
|
950
|
+
|
|
951
|
+
it('Should properly inject into titles if phrase_before or phrase_after are nonsense, but title can be matched simply', () => {
|
|
952
|
+
document.body.innerHTML = '<section>Some text with a phrase in it</section>'
|
|
953
|
+
|
|
954
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
955
|
+
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
956
|
+
injection.phrase_before = 'random'
|
|
957
|
+
injection.phrase_after = 'crap'
|
|
958
|
+
|
|
959
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
960
|
+
|
|
961
|
+
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
962
|
+
})
|
|
963
|
+
|
|
964
|
+
it('Should properly inject into titles that are split up by multiple elements when neither phrase_before or phrase_after are given but the phrase occurs only once', () => {
|
|
965
|
+
document.body.innerHTML = '<section>Some text with a <strong>phra</strong><strong>se</strong> in it</section>'
|
|
966
|
+
|
|
967
|
+
const elements = getLinkInjectionElements(/** @type {HTMLElement} */ (document.querySelector('section')))
|
|
968
|
+
const injection = generateInjection('Some text with a phrase in it', 'phrase')
|
|
969
|
+
|
|
970
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: [injection] })
|
|
971
|
+
|
|
972
|
+
expect(document.querySelector('a')?.innerText).toBe(injection.title)
|
|
973
|
+
})
|
|
974
|
+
|
|
975
|
+
it('Should replace existing PlayPilot links', () => {
|
|
976
|
+
document.body.innerHTML = '<p>This is a sentence with <a href="https://playpilot.com/movie/123">an injection</a>.</p>'
|
|
977
|
+
|
|
978
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
979
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
980
|
+
|
|
981
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
982
|
+
|
|
983
|
+
expect(document.querySelector('a')?.closest('[data-playpilot-injection-key]')).toBeTruthy()
|
|
984
|
+
})
|
|
985
|
+
|
|
986
|
+
describe('Participants', () => {
|
|
987
|
+
it('Should inject participants just as a title', () => {
|
|
988
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
989
|
+
|
|
990
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
991
|
+
const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: participants[0] }
|
|
992
|
+
|
|
993
|
+
// @ts-ignore
|
|
994
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
995
|
+
|
|
996
|
+
expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
|
|
997
|
+
})
|
|
998
|
+
|
|
999
|
+
it('Should ignore participants below a given popularity threshold', () => {
|
|
1000
|
+
window.PlayPilotLinkInjections.config = {
|
|
1001
|
+
participant_injection_popularity_threshold: 50,
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1005
|
+
|
|
1006
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1007
|
+
|
|
1008
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1009
|
+
const injections = [
|
|
1010
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', participant_details: { ...participants[0], popularity: 20 } },
|
|
1011
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: { ...participants[0], popularity: 70 } },
|
|
1012
|
+
]
|
|
1013
|
+
|
|
1014
|
+
// @ts-ignore
|
|
1015
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1016
|
+
|
|
1017
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
|
|
1018
|
+
})
|
|
1019
|
+
|
|
1020
|
+
it('Should ignore participants popularity for manual injections', () => {
|
|
1021
|
+
window.PlayPilotLinkInjections.config = {
|
|
1022
|
+
participant_injection_popularity_threshold_use_article_average: false,
|
|
1023
|
+
participant_injection_popularity_threshold: 50,
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1027
|
+
|
|
1028
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1029
|
+
|
|
1030
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1031
|
+
const injections = [
|
|
1032
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', manual: true, participant_details: { ...participants[0], popularity: 20 } },
|
|
1033
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', manual: true, participant_details: { ...participants[0], popularity: 70 } },
|
|
1034
|
+
]
|
|
1035
|
+
|
|
1036
|
+
// @ts-ignore
|
|
1037
|
+
injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
|
|
1038
|
+
|
|
1039
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
1040
|
+
})
|
|
1041
|
+
|
|
1042
|
+
it('Should include injection type on element', () => {
|
|
1043
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1044
|
+
|
|
1045
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1046
|
+
const injections = [
|
|
1047
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), type: 'participant', participant_details: participants[0] },
|
|
1048
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'title' },
|
|
1049
|
+
]
|
|
1050
|
+
|
|
1051
|
+
// @ts-ignore
|
|
1052
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1053
|
+
|
|
1054
|
+
expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[0]).dataset.playpilotInjectionType).toBe('participant')
|
|
1055
|
+
expect(/** @type {HTMLElement} */ (document.querySelectorAll('[data-playpilot-injection-key]')[1]).dataset.playpilotInjectionType).toBe('title')
|
|
1056
|
+
})
|
|
1057
|
+
})
|
|
1058
|
+
|
|
1059
|
+
describe('config.open_tpi_links_in_explore', () => {
|
|
1060
|
+
beforeEach(() => {
|
|
1061
|
+
window.PlayPilotLinkInjections.config = {
|
|
1062
|
+
open_tpi_links_in_explore: true,
|
|
1063
|
+
explore_navigation_path: 'https://some-path.com/explore',
|
|
1064
|
+
}
|
|
1065
|
+
})
|
|
1066
|
+
|
|
1067
|
+
it('Should use href with explore links if open_tpi_links_in_explore is true', () => {
|
|
1068
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
1069
|
+
|
|
1070
|
+
document.body.innerHTML = `<p>${injection.sentence}</p>`
|
|
1071
|
+
|
|
1072
|
+
const elements = Array.from(document.querySelectorAll('p'))
|
|
1073
|
+
|
|
1074
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
1075
|
+
|
|
1076
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
1077
|
+
expect(link.href).toBe(window.PlayPilotLinkInjections.config?.explore_navigation_path + `?route=modal&sid=${injection.title_details?.sid}`)
|
|
1078
|
+
expect(link.target).not.toBeTruthy()
|
|
1079
|
+
})
|
|
1080
|
+
|
|
1081
|
+
it('Should not open modal when link is clicked when open_tpi_links_in_explore is true', async () => {
|
|
1082
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1083
|
+
|
|
1084
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1085
|
+
const injection = generateInjection('This is a sentence with an injection.', 'an injection')
|
|
1086
|
+
|
|
1087
|
+
injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
|
|
1088
|
+
|
|
1089
|
+
const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
|
|
1090
|
+
await fireEvent.click(link)
|
|
1091
|
+
|
|
1092
|
+
expect(openModalForInjectedLink).not.toHaveBeenCalled()
|
|
1093
|
+
})
|
|
1094
|
+
})
|
|
1095
|
+
|
|
1096
|
+
describe('config.unique_injection_count_limit', () => {
|
|
1097
|
+
it('Should not insert another link if the count for links of the same sid is met', () => {
|
|
1098
|
+
window.PlayPilotLinkInjections.config = {
|
|
1099
|
+
unique_injection_count_limit: 2,
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1103
|
+
|
|
1104
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1105
|
+
const injections = [
|
|
1106
|
+
{ ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a' },
|
|
1107
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'a' },
|
|
1108
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'a' },
|
|
1109
|
+
]
|
|
1110
|
+
|
|
1111
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1112
|
+
|
|
1113
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
1114
|
+
})
|
|
1115
|
+
|
|
1116
|
+
it('Should disregard limit for manual injections', () => {
|
|
1117
|
+
window.PlayPilotLinkInjections.config = {
|
|
1118
|
+
unique_injection_count_limit: 2,
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1122
|
+
|
|
1123
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1124
|
+
const aiInjections = [
|
|
1125
|
+
{ ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a' },
|
|
1126
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'a' },
|
|
1127
|
+
]
|
|
1128
|
+
const manualInjections = [{ ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'a' }]
|
|
1129
|
+
|
|
1130
|
+
injectLinksInDocument(elements, { aiInjections, manualInjections })
|
|
1131
|
+
|
|
1132
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
|
|
1133
|
+
})
|
|
1134
|
+
})
|
|
1135
|
+
|
|
1136
|
+
describe('config.total_participant_injection_count_limit', () => {
|
|
1137
|
+
it('Should not insert another link if the total count of participants exceeds the given limit', () => {
|
|
1138
|
+
window.PlayPilotLinkInjections.config = {
|
|
1139
|
+
total_participant_injection_count_limit: 2,
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1143
|
+
|
|
1144
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1145
|
+
|
|
1146
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1147
|
+
const injections = [
|
|
1148
|
+
{ ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a', type: 'participant', participant_details: participants[0] },
|
|
1149
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'b', type: 'participant', participant_details: participants[0] },
|
|
1150
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'c', type: 'participant', participant_details: participants[0] },
|
|
1151
|
+
]
|
|
1152
|
+
|
|
1153
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1154
|
+
|
|
1155
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(2)
|
|
1156
|
+
})
|
|
1157
|
+
|
|
1158
|
+
it('Should disregard any limit if none if given', () => {
|
|
1159
|
+
window.PlayPilotLinkInjections.config = {}
|
|
1160
|
+
|
|
1161
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1162
|
+
|
|
1163
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1164
|
+
|
|
1165
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1166
|
+
const injections = [
|
|
1167
|
+
{ ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a', type: 'participant', participant_details: participants[0] },
|
|
1168
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'b', type: 'participant', participant_details: participants[0] },
|
|
1169
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'c', type: 'participant', participant_details: participants[0] },
|
|
1170
|
+
]
|
|
1171
|
+
|
|
1172
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1173
|
+
|
|
1174
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
|
|
1175
|
+
})
|
|
1176
|
+
|
|
1177
|
+
it('Should disregard title types for participant limit if none if given', () => {
|
|
1178
|
+
window.PlayPilotLinkInjections.config = {
|
|
1179
|
+
total_participant_injection_count_limit: 1,
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
|
|
1183
|
+
|
|
1184
|
+
const elements = Array.from(document.body.querySelectorAll('p'))
|
|
1185
|
+
|
|
1186
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1187
|
+
const injections = [
|
|
1188
|
+
{ ...generateInjection('This is a sentence with an injection.', 'This is'), sid: 'a' },
|
|
1189
|
+
{ ...generateInjection('This is a sentence with an injection.', 'a sentence'), sid: 'b' },
|
|
1190
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), sid: 'c', type: 'participant', participant_details: participants[0] },
|
|
1191
|
+
]
|
|
1192
|
+
|
|
1193
|
+
injectLinksInDocument(elements, { aiInjections: injections, manualInjections: [] })
|
|
1194
|
+
|
|
1195
|
+
expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(3)
|
|
1196
|
+
})
|
|
1197
|
+
})
|
|
1198
|
+
})
|
|
1199
|
+
|
|
1200
|
+
describe('clearLinkInjections', () => {
|
|
1201
|
+
it('Should remove injected links from the page', () => {
|
|
1202
|
+
document.body.innerHTML = '<p><span data-playpilot-injection-key><a>Some link</a></span></p>'
|
|
1203
|
+
clearLinkInjections()
|
|
1204
|
+
|
|
1205
|
+
expect(document.body.innerHTML).toBe('<p>Some link</p>')
|
|
1206
|
+
})
|
|
1207
|
+
|
|
1208
|
+
it('Should leave non-injected links intact', () => {
|
|
1209
|
+
document.body.innerHTML = '<p><a>Some link</a></p>'
|
|
1210
|
+
clearLinkInjections()
|
|
1211
|
+
|
|
1212
|
+
expect(document.body.innerHTML).toBe('<p><a>Some link</a></p>')
|
|
1213
|
+
})
|
|
1214
|
+
})
|
|
1215
|
+
|
|
1216
|
+
describe('clearLinkInjection', () => {
|
|
1217
|
+
it('Should remove injected link from the page', () => {
|
|
1218
|
+
document.body.innerHTML = '<p><span data-playpilot-injection-key="a"><a>Some link</a></span></p>'
|
|
1219
|
+
clearLinkInjection('a')
|
|
1220
|
+
|
|
1221
|
+
expect(document.body.innerHTML).toBe('<p>Some link</p>')
|
|
1222
|
+
})
|
|
1223
|
+
|
|
1224
|
+
it('Should keep other keys intact', () => {
|
|
1225
|
+
document.body.innerHTML = '<p><span data-playpilot-injection-key="b"><a>Some link</a></span></p>'
|
|
1226
|
+
clearLinkInjection('a')
|
|
1227
|
+
|
|
1228
|
+
expect(document.body.innerHTML).toBe('<p><span data-playpilot-injection-key="b"><a>Some link</a></span></p>')
|
|
1229
|
+
})
|
|
1230
|
+
})
|
|
1231
|
+
|
|
1232
|
+
describe('isAvailableAsManualInjection', () => {
|
|
1233
|
+
it('Should return true if the ai injection has a matching manual injection', () => {
|
|
1234
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1235
|
+
const manualInjection = { ...aiInjection, manual: true }
|
|
1236
|
+
|
|
1237
|
+
expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection, manualInjection]))
|
|
1238
|
+
})
|
|
1239
|
+
|
|
1240
|
+
it('Should return false if the ai injection has no matching manual injection', () => {
|
|
1241
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1242
|
+
|
|
1243
|
+
expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection]))
|
|
1244
|
+
})
|
|
1245
|
+
|
|
1246
|
+
it('Should return false if the ai injection has a matching ai injection', () => {
|
|
1247
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1248
|
+
|
|
1249
|
+
expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection, aiInjection]))
|
|
1250
|
+
})
|
|
1251
|
+
})
|
|
1252
|
+
|
|
1253
|
+
describe('filterRemovedAndInactiveInjections', () => {
|
|
1254
|
+
it('Should not return injections that are removed or have an removed manual equivalent', () => {
|
|
1255
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1256
|
+
const manualInjection = { ...aiInjection, manual: true, removed: true }
|
|
1257
|
+
|
|
1258
|
+
expect(filterRemovedAndInactiveInjections([aiInjection, manualInjection])).toEqual([])
|
|
1259
|
+
})
|
|
1260
|
+
|
|
1261
|
+
it('Should not return injections that are inactive or have an inactive manual equivalent', () => {
|
|
1262
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1263
|
+
const manualInjection = { ...aiInjection, manual: true, inactive: true }
|
|
1264
|
+
|
|
1265
|
+
expect(filterRemovedAndInactiveInjections([aiInjection, manualInjection])).toEqual([])
|
|
1266
|
+
})
|
|
1267
|
+
|
|
1268
|
+
it('Should return ai injections that have no matching manual injection', () => {
|
|
1269
|
+
const aiInjection = generateInjection('Some sentence', 'Some title')
|
|
1270
|
+
const manualInjection = { ...generateInjection('Some other sentence', 'Some other title'), manual: true }
|
|
1271
|
+
|
|
1272
|
+
expect(filterRemovedAndInactiveInjections([aiInjection, manualInjection])).toEqual([aiInjection, manualInjection])
|
|
1273
|
+
})
|
|
1274
|
+
|
|
1275
|
+
it('Should return manual injections that have been removed at one point, but a new injection for the same title was created', () => {
|
|
1276
|
+
const manualInjection = { ...generateInjection('Some other sentence', 'Some other title'), manual: true }
|
|
1277
|
+
const removedManualInjection = { ...manualInjection, removed: true }
|
|
1278
|
+
|
|
1279
|
+
expect(filterRemovedAndInactiveInjections([manualInjection, removedManualInjection])).toEqual([manualInjection])
|
|
1280
|
+
})
|
|
1281
|
+
|
|
1282
|
+
it('Should return manual injections that have been inactive at one point, but a new injection for the same title was created', () => {
|
|
1283
|
+
const manualInjection = { ...generateInjection('Some other sentence', 'Some other title'), manual: true }
|
|
1284
|
+
const inactiveManualInjection = { ...manualInjection, inactive: true }
|
|
1285
|
+
|
|
1286
|
+
expect(filterRemovedAndInactiveInjections([manualInjection, inactiveManualInjection])).toEqual([manualInjection])
|
|
1287
|
+
})
|
|
1288
|
+
})
|
|
1289
|
+
|
|
1290
|
+
describe('isEquivalentInjection', () => {
|
|
1291
|
+
it('Should return true if injections have the same title and sentence', () => {
|
|
1292
|
+
expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('a', 'b'))).toBe(true)
|
|
1293
|
+
})
|
|
1294
|
+
|
|
1295
|
+
it('Should return false if injections have different titles', () => {
|
|
1296
|
+
expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('a', 'c'))).toBe(false)
|
|
1297
|
+
})
|
|
1298
|
+
|
|
1299
|
+
it('Should return false if injections have different sentences', () => {
|
|
1300
|
+
expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('b', 'b'))).toBe(false)
|
|
1301
|
+
})
|
|
1302
|
+
|
|
1303
|
+
it('Should return false if injections have both different titles and sentences', () => {
|
|
1304
|
+
expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('c', 'd'))).toBe(false)
|
|
1305
|
+
})
|
|
1306
|
+
})
|
|
1307
|
+
|
|
1308
|
+
describe('isValidInjection', () => {
|
|
1309
|
+
it('Should only return true when the injection is valid', () => {
|
|
1310
|
+
expect(isValidInjection({ ...generateInjection('a', 'b') })).toBe(true)
|
|
1311
|
+
expect(isValidInjection({ ...generateInjection('a', 'b'), inactive: true })).toBe(false)
|
|
1312
|
+
expect(isValidInjection({ ...generateInjection('a', 'b'), removed: true })).toBe(false)
|
|
1313
|
+
expect(isValidInjection({ ...generateInjection('a', 'b'), duplicate: true })).toBe(false)
|
|
1314
|
+
expect(isValidInjection({ ...generateInjection('a', 'b'), title_details: undefined })).toBe(false)
|
|
1315
|
+
})
|
|
1316
|
+
})
|
|
1317
|
+
|
|
1318
|
+
describe('filterInvalidInTextInjections', () => {
|
|
1319
|
+
it('Should return injections that are valid', () => {
|
|
1320
|
+
expect(filterInvalidInTextInjections([generateInjection('a', 'b')])).toHaveLength(1)
|
|
1321
|
+
})
|
|
1322
|
+
|
|
1323
|
+
it('Should return not injections that inactive, removed, duplicate, have no title_details, or are not in_text', () => {
|
|
1324
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), inactive: true }])).toHaveLength(0)
|
|
1325
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), removed: true }])).toHaveLength(0)
|
|
1326
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), duplicate: true }])).toHaveLength(0)
|
|
1327
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), title_details: undefined }])).toHaveLength(0)
|
|
1328
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: false }])).toHaveLength(0)
|
|
1329
|
+
|
|
1330
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: undefined }])).toHaveLength(1)
|
|
1331
|
+
expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: true }])).toHaveLength(1)
|
|
1332
|
+
})
|
|
1333
|
+
})
|
|
1334
|
+
|
|
1335
|
+
describe('filterInvalidAfterArticleInjections', () => {
|
|
1336
|
+
it('Should return not injections that inactive, removed, duplicate, have no title_details, or are not after_article', () => {
|
|
1337
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), inactive: true }])).toHaveLength(0)
|
|
1338
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), removed: true }])).toHaveLength(0)
|
|
1339
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), duplicate: true }])).toHaveLength(0)
|
|
1340
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), title_details: undefined }])).toHaveLength(0)
|
|
1341
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: false }])).toHaveLength(0)
|
|
1342
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: undefined }])).toHaveLength(0)
|
|
1343
|
+
|
|
1344
|
+
expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: true }])).toHaveLength(1)
|
|
1345
|
+
})
|
|
1346
|
+
})
|
|
1347
|
+
|
|
1348
|
+
describe('isValidPlaylinkType', () => {
|
|
1349
|
+
it('Should return true if in_text is true', () => {
|
|
1350
|
+
// @ts-ignore
|
|
1351
|
+
expect(isValidPlaylinkType({ in_text: true })).toBe(true)
|
|
1352
|
+
// @ts-ignore
|
|
1353
|
+
expect(isValidPlaylinkType({ in_text: true, after_article: false })).toBe(true)
|
|
1354
|
+
})
|
|
1355
|
+
|
|
1356
|
+
it('Should return true if after_article is true', () => {
|
|
1357
|
+
// @ts-ignore
|
|
1358
|
+
expect(isValidPlaylinkType({ after_article: true })).toBe(true)
|
|
1359
|
+
// @ts-ignore
|
|
1360
|
+
expect(isValidPlaylinkType({ after_article: true, in_text: false })).toBe(true)
|
|
1361
|
+
})
|
|
1362
|
+
|
|
1363
|
+
it('Should return true if neither in_text or after_article are given', () => {
|
|
1364
|
+
// @ts-ignore
|
|
1365
|
+
expect(isValidPlaylinkType({ })).toBe(true)
|
|
1366
|
+
})
|
|
1367
|
+
|
|
1368
|
+
it('Should return false if in_text is false', () => {
|
|
1369
|
+
// @ts-ignore
|
|
1370
|
+
expect(isValidPlaylinkType({ in_text: false })).toBe(false)
|
|
1371
|
+
})
|
|
1372
|
+
|
|
1373
|
+
it('Should return false if both in_text and after_article are are false', () => {
|
|
1374
|
+
// @ts-ignore
|
|
1375
|
+
expect(isValidPlaylinkType({ in_text: false, after_article: false })).toBe(false)
|
|
1376
|
+
})
|
|
1377
|
+
})
|
|
1378
|
+
|
|
1379
|
+
describe('hasValidTypeData', () => {
|
|
1380
|
+
it('Should return true if injection has type title and has title_details', () => {
|
|
1381
|
+
// @ts-ignore
|
|
1382
|
+
expect(hasValidTypeData({ type: 'title', title_details: {} })).toBe(true)
|
|
1383
|
+
})
|
|
1384
|
+
|
|
1385
|
+
it('Should return true if injection has type participant and has participant_details', () => {
|
|
1386
|
+
// @ts-ignore
|
|
1387
|
+
expect(hasValidTypeData({ type: 'participant', participant_details: {} })).toBe(true)
|
|
1388
|
+
})
|
|
1389
|
+
|
|
1390
|
+
it('Should return false if injection has type title but has no title_details', () => {
|
|
1391
|
+
// @ts-ignore
|
|
1392
|
+
expect(hasValidTypeData({ type: 'title', title_details: null })).toBe(false)
|
|
1393
|
+
// @ts-ignore
|
|
1394
|
+
expect(hasValidTypeData({ type: 'title' })).toBe(false)
|
|
1395
|
+
})
|
|
1396
|
+
|
|
1397
|
+
it('Should return false if injection has type participant but has no participant_details', () => {
|
|
1398
|
+
// @ts-ignore
|
|
1399
|
+
expect(hasValidTypeData({ type: 'participant', participant_details: null })).toBe(false)
|
|
1400
|
+
// @ts-ignore
|
|
1401
|
+
expect(hasValidTypeData({ type: 'participant' })).toBe(false)
|
|
1402
|
+
})
|
|
1403
|
+
})
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
describe('removePlayPilotTitleLinks', () => {
|
|
1407
|
+
it('Should remove existing title links', () => {
|
|
1408
|
+
document.body.innerHTML = `
|
|
1409
|
+
<a href="https://www.playpilot.com/movie/123">Movie Link</a>
|
|
1410
|
+
<a href="https://www.playpilot.com/show/123">Show Link</a>
|
|
1411
|
+
`
|
|
1412
|
+
|
|
1413
|
+
removePlayPilotTitleLinks()
|
|
1414
|
+
|
|
1415
|
+
expect(document.body.innerHTML).toContain('Movie Link')
|
|
1416
|
+
expect(document.body.innerHTML).toContain('Show Link')
|
|
1417
|
+
expect(document.querySelectorAll('a')).toHaveLength(0)
|
|
1418
|
+
})
|
|
1419
|
+
|
|
1420
|
+
it('Should not remove injected links', () => {
|
|
1421
|
+
document.body.innerHTML = `
|
|
1422
|
+
<span data-playpilot-injection-key>
|
|
1423
|
+
<a href="https://www.playpilot.com/movie/123">Movie Link</a>
|
|
1424
|
+
</span>
|
|
1425
|
+
`
|
|
1426
|
+
|
|
1427
|
+
removePlayPilotTitleLinks()
|
|
1428
|
+
|
|
1429
|
+
expect(document.querySelector('a')).toBeTruthy()
|
|
1430
|
+
})
|
|
1431
|
+
|
|
1432
|
+
it('Should not remove links without /movie/ or /show/', () => {
|
|
1433
|
+
document.body.innerHTML = `
|
|
1434
|
+
<a href="https://www.playpilot.com/something/123">Not a show or movie</a>
|
|
1435
|
+
<a href="https://www.playpilot.com/">Root</a>
|
|
1436
|
+
`
|
|
1437
|
+
|
|
1438
|
+
removePlayPilotTitleLinks()
|
|
1439
|
+
|
|
1440
|
+
expect(document.querySelectorAll('a')).toHaveLength(2)
|
|
1441
|
+
})
|
|
1442
|
+
|
|
1443
|
+
it('Should not remove non-playpilot links', () => {
|
|
1444
|
+
document.body.innerHTML = '<a href="https://some-website.com">Not PlayPilot</a>'
|
|
1445
|
+
|
|
1446
|
+
removePlayPilotTitleLinks()
|
|
1447
|
+
|
|
1448
|
+
expect(document.querySelector('a')).toBeTruthy()
|
|
1449
|
+
})
|
|
1450
|
+
})
|
|
1451
|
+
|
|
1452
|
+
describe('doesParticipantMeetThreshold', () => {
|
|
1453
|
+
it('Should return true or false if article average is used and participant is above or below average', () => {
|
|
1454
|
+
window.PlayPilotLinkInjections.config = {
|
|
1455
|
+
participant_injection_popularity_threshold: 75,
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
const truthyParticipant = { ...participants[0], popularity: 70 }
|
|
1459
|
+
const falseyParticipant = { ...participants[0], popularity: 20 }
|
|
1460
|
+
|
|
1461
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1462
|
+
const injections = [
|
|
1463
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1464
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: falseyParticipant },
|
|
1465
|
+
]
|
|
1466
|
+
|
|
1467
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1468
|
+
expect(doesParticipantMeetThreshold(injections, falseyParticipant)).toBe(false)
|
|
1469
|
+
})
|
|
1470
|
+
|
|
1471
|
+
it('Should return true or false if article average is not used and participant is above or below threshold', () => {
|
|
1472
|
+
window.PlayPilotLinkInjections.config = {
|
|
1473
|
+
participant_injection_popularity_threshold: 5500,
|
|
1474
|
+
participant_injection_popularity_threshold_use_article_average: false,
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
const truthyParticipant = { ...participants[0], popularity: 6000 }
|
|
1478
|
+
const falseyParticipant = { ...participants[0], popularity: 5000 }
|
|
1479
|
+
|
|
1480
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1481
|
+
const injections = [
|
|
1482
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1483
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: falseyParticipant },
|
|
1484
|
+
]
|
|
1485
|
+
|
|
1486
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1487
|
+
expect(doesParticipantMeetThreshold(injections, falseyParticipant)).toBe(false)
|
|
1488
|
+
})
|
|
1489
|
+
|
|
1490
|
+
it('Should return true if threshold is 0, regardless of popularity', () => {
|
|
1491
|
+
window.PlayPilotLinkInjections.config = {
|
|
1492
|
+
participant_injection_popularity_threshold: 0,
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
const truthyParticipant = { ...participants[0], popularity: 0 }
|
|
1496
|
+
const truthyParticipant2 = { ...participants[0], popularity: 60 }
|
|
1497
|
+
|
|
1498
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1499
|
+
const injections = [
|
|
1500
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1501
|
+
]
|
|
1502
|
+
|
|
1503
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1504
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant2)).toBe(true)
|
|
1505
|
+
})
|
|
1506
|
+
|
|
1507
|
+
it('Should use threshold of 0 by default', () => {
|
|
1508
|
+
const truthyParticipant = { ...participants[0], popularity: 0 }
|
|
1509
|
+
const truthyParticipant2 = { ...participants[0], popularity: 1 }
|
|
1510
|
+
|
|
1511
|
+
/** @type {import('$lib/types/injection').LinkInjection[]} */
|
|
1512
|
+
const injections = [
|
|
1513
|
+
{ ...generateInjection('This is a sentence with an injection.', 'an injection'), type: 'participant', participant_details: truthyParticipant },
|
|
1514
|
+
]
|
|
1515
|
+
|
|
1516
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant)).toBe(true)
|
|
1517
|
+
expect(doesParticipantMeetThreshold(injections, truthyParticipant2)).toBe(true)
|
|
1518
|
+
})
|
|
1519
|
+
})
|
|
1520
|
+
})
|