@playpilot/tpi 1.4.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import { fireEvent } from '@testing-library/svelte'
2
2
  import { describe, expect, it, vi, beforeEach } from 'vitest'
3
3
 
4
- import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, getLinkInjectionElements, insertAfterArticlePlaylinks, getLinkInjectionsParentElement, sortLinkInjectionsByRange } from '$lib/linkInjection'
5
- import { title } from '$lib/fakeData'
4
+ import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, getLinkInjectionElements, insertAfterArticlePlaylinks, getLinkInjectionsParentElement, sortLinkInjectionsByRange, isAvailableAsManualInjection, filterRemovedInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection } from '$lib/linkInjection'
6
5
  import { mount, unmount } from 'svelte'
6
+ import { generateInjection } from '../helpers'
7
7
 
8
8
  vi.mock('svelte', () => ({
9
9
  mount: vi.fn(),
@@ -31,98 +31,102 @@ describe('linkInjection.js', () => {
31
31
 
32
32
  describe('injectLinksInDocument', () => {
33
33
  it('Should replace given words with injections', () => {
34
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
34
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
35
+ const linkInjections = [injection]
35
36
 
36
- const elements = Array.from(document.querySelectorAll('p'))
37
+ document.body.innerHTML = `<p>${injection.sentence}</p>`
37
38
 
38
- const linkInjections = [{
39
- sid: '1',
40
- title: 'an injection',
41
- sentence: 'This is a sentence with an injection.',
42
- playpilot_url: 'https://some-link.com/',
43
- poster: 'some-poster',
44
- key: 'some-key',
45
- }]
39
+ const elements = Array.from(document.querySelectorAll('p'))
46
40
 
47
- injectLinksInDocument(elements, linkInjections, () => null)
41
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
48
42
 
49
43
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
50
44
 
51
- expect(link.innerText).toBe('an injection')
52
- expect(link.href).toBe('https://some-link.com/')
45
+ expect(link.innerText).toBe(injection.title)
46
+ expect(link.href).toBe(injection.playpilot_url)
53
47
  })
54
48
 
55
49
  it('Should replace given words as expected when more than 1 injection per sentence is present', () => {
56
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
50
+ const sentence = 'This is a sentence with an injection.'
51
+ const linkInjections = [
52
+ generateInjection(sentence, 'a sentence'),
53
+ generateInjection(sentence, 'an injection'),
54
+ ]
55
+
56
+ document.body.innerHTML = `<p>${sentence}</p>`
57
57
 
58
58
  const elements = Array.from(document.body.querySelectorAll('p'))
59
59
 
60
- const linkInjections = [{
61
- sid: '1',
62
- title: 'a sentence',
63
- sentence: 'This is a sentence with an injection.',
64
- playpilot_url: 'https://some-link.com/',
65
- poster: 'some-poster',
66
- key: 'some-key-1',
67
- title_details: title,
68
- }, {
69
- sid: '2',
70
- title: 'an injection',
71
- sentence: 'This is a sentence with an injection.',
72
- playpilot_url: 'https://some-link.com/',
73
- poster: 'some-poster',
74
- key: 'some-key-1',
75
- title_details: title,
76
- }]
77
-
78
- injectLinksInDocument(elements, linkInjections, () => null)
60
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
79
61
 
80
62
  const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
81
63
 
82
- expect(links[0].innerText).toBe('a sentence')
83
- expect(links[0].href).toBe('https://some-link.com/')
84
- expect(links[0].dataset.playpilotOriginalTitle).toBe(title.original_title)
64
+ expect(links[0].innerText).toBe(linkInjections[0].title)
65
+ expect(links[0].href).toBe(linkInjections[0].playpilot_url)
66
+ /** @ts-ignore It is defined */
67
+ expect(links[0].dataset.playpilotOriginalTitle).toBe(linkInjections[0].title_details.original_title)
85
68
 
86
- expect(links[1].innerText).toBe('an injection')
87
- expect(links[1].href).toBe('https://some-link.com/')
88
- expect(links[1].dataset.playpilotOriginalTitle).toBe(title.original_title)
69
+ expect(links[1].innerText).toBe(linkInjections[1].title)
70
+ expect(links[1].href).toBe(linkInjections[1].playpilot_url)
71
+ /** @ts-ignore It is defined */
72
+ expect(links[1].dataset.playpilotOriginalTitle).toBe(linkInjections[1].title_details.original_title)
89
73
  })
90
74
 
91
75
  it('Should ignore injections that are marked as inactive', () => {
92
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
76
+ const sentence = 'This is a sentence with an injection.'
77
+ const injection = generateInjection(sentence, 'an injection')
78
+ const linkInjections = [{ ...injection, inactive: true }]
79
+
80
+ document.body.innerHTML = `<p>${sentence}</p>`
93
81
 
94
82
  const elements = Array.from(document.body.querySelectorAll('p'))
95
83
 
96
- const linkInjections = [{
97
- sid: '1',
98
- title: 'an injection',
99
- sentence: 'This is a sentence with an injection.',
100
- playpilot_url: '',
101
- poster: 'some-poster',
102
- key: 'some-key',
103
- inactive: true,
104
- }]
84
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
105
85
 
106
- injectLinksInDocument(elements, linkInjections, () => null)
86
+ expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
87
+ })
88
+
89
+ it('Should ignore injections that are marked as removed', () => {
90
+ const sentence = 'This is a sentence with an injection.'
91
+ const injection = generateInjection(sentence, 'an injection')
92
+ const linkInjections = [{ ...injection, removed: true }]
107
93
 
108
- expect(document.body.innerHTML).toBe('<p>This is a sentence with an injection.</p>')
94
+ document.body.innerHTML = `<p>${sentence}</p>`
95
+
96
+ const elements = Array.from(document.body.querySelectorAll('p'))
97
+
98
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
99
+
100
+ expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
101
+ })
102
+
103
+ it('Should ignore AI injections that are marked as removed as a matching manual injections', () => {
104
+ const sentence = 'This is a sentence with an injection.'
105
+ const injection = generateInjection(sentence, 'an injection')
106
+
107
+ document.body.innerHTML = `<p>${sentence}</p>`
108
+
109
+ const elements = Array.from(document.body.querySelectorAll('p'))
110
+
111
+ const injections = {
112
+ aiInjections: [injection],
113
+ manualInjections: [{ ...injection, manual: true, removed: true }],
114
+ }
115
+
116
+ injectLinksInDocument(elements, () => null, injections)
117
+
118
+ expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
109
119
  })
110
120
 
111
121
  it('Should keep existing HTML elements intact', () => {
122
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
123
+ const linkInjections = [injection]
124
+
112
125
  document.body.innerHTML = '<p>This is a <button>sentence</button> with an injection.</p>'
113
126
 
114
127
  const elements = Array.from(document.body.querySelectorAll('p'))
115
128
 
116
- const linkInjections = [{
117
- sid: '1',
118
- title: 'an injection',
119
- sentence: 'This is a sentence with an injection.',
120
- playpilot_url: '',
121
- poster: 'some-poster',
122
- key: 'some-key',
123
- }]
124
-
125
- injectLinksInDocument(elements, linkInjections, () => null)
129
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
126
130
 
127
131
  const button = /** @type {HTMLButtonElement} */ (document.querySelector('button'))
128
132
 
@@ -133,56 +137,43 @@ describe('linkInjection.js', () => {
133
137
  document.body.innerHTML = '<h1>I am a title</h1><p>This is a sentence with an injection.</p>'
134
138
 
135
139
  const elements = Array.from(document.body.querySelectorAll('p'))
140
+ const injection = generateInjection('I am a title', 'a title')
136
141
 
137
- const linkInjections = [{
138
- sid: '1',
139
- title: 'a title',
140
- sentence: 'I am a title',
141
- playpilot_url: '',
142
- poster: 'some-poster',
143
- key: 'some-key',
144
- }]
142
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
145
143
 
146
- injectLinksInDocument(elements, linkInjections, () => null)
147
-
148
- expect(document.body.innerHTML.includes('I am a title')).toBeTruthy()
144
+ expect(document.body.innerHTML.includes(injection.sentence)).toBeTruthy()
149
145
  })
150
146
 
151
147
  it('Should ignore partial matches due to interfering elements', () => {
152
148
  document.body.innerHTML = '<p>This is a sentence with <strong>an</strong> injection.</p>'
153
149
 
154
150
  const elements = Array.from(document.body.querySelectorAll('p'))
151
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
155
152
 
156
- const linkInjections = [{
157
- sid: '1',
158
- title: 'an injection',
159
- sentence: 'This is a sentence with an injection.',
160
- playpilot_url: '',
161
- poster: 'some-poster',
162
- key: 'some-key',
163
- }]
164
-
165
- injectLinksInDocument(elements, linkInjections, () => null)
153
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
166
154
 
167
155
  expect(document.body.innerHTML.includes('an injection')).not.toBeTruthy()
168
156
  expect(document.body.innerHTML.includes('an')).toBeTruthy()
169
157
  })
170
158
 
159
+ it('Should ignore encoded characters in given sentences', () => {
160
+ document.body.innerHTML = '<p>This is a sentence & an injection.</p>'
161
+
162
+ const elements = Array.from(document.body.querySelectorAll('p'))
163
+ const injection = generateInjection('This is a sentence &amp; an injection.', 'an injection')
164
+
165
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
166
+
167
+ expect(document.querySelectorAll('a')).toHaveLength(1)
168
+ })
169
+
171
170
  it('Should ignore matches due to parent links', () => {
172
171
  document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
173
172
 
174
173
  const elements = Array.from(document.body.querySelectorAll('p'))
174
+ const injection = generateInjection('This is a sentence with an injection.', 'a sentence')
175
175
 
176
- const linkInjections = [{
177
- sid: '1',
178
- title: 'a sentence',
179
- sentence: 'This is a sentence with an injection.',
180
- playpilot_url: 'https://some-link.com/',
181
- poster: 'some-poster',
182
- key: 'some-key-1',
183
- }]
184
-
185
- injectLinksInDocument(elements, linkInjections, () => null)
176
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
186
177
 
187
178
  expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
188
179
  })
@@ -191,17 +182,9 @@ describe('linkInjection.js', () => {
191
182
  document.body.innerHTML = '<p>This is <a data-thing="some word">a sentence</a> with an injection.</p>'
192
183
 
193
184
  const elements = Array.from(document.body.querySelectorAll('p'))
185
+ const injection = generateInjection('This is a sentence with an injection.', 'some word')
194
186
 
195
- const linkInjections = [{
196
- sid: '1',
197
- title: 'some word',
198
- sentence: 'This is a sentence with an injection.',
199
- playpilot_url: 'https://some-link.com/',
200
- poster: 'some-poster',
201
- key: 'some-key-1',
202
- }]
203
-
204
- injectLinksInDocument(elements, linkInjections, () => null)
187
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
205
188
 
206
189
  expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
207
190
  })
@@ -210,17 +193,9 @@ describe('linkInjection.js', () => {
210
193
  document.body.innerHTML = '<p>This is <a>a word</a> with a word.</p>'
211
194
 
212
195
  const elements = Array.from(document.body.querySelectorAll('p'))
196
+ const injection = generateInjection('This is a word with a word.', 'a word')
213
197
 
214
- const linkInjections = [{
215
- sid: '1',
216
- title: 'a word',
217
- sentence: 'This is a word with a word.',
218
- playpilot_url: 'https://some-link.com/',
219
- poster: 'some-poster',
220
- key: 'some-key-1',
221
- }]
222
-
223
- injectLinksInDocument(elements, linkInjections, () => null)
198
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
224
199
 
225
200
  expect(document.querySelectorAll('a')).toHaveLength(2)
226
201
  })
@@ -229,17 +204,9 @@ describe('linkInjection.js', () => {
229
204
  document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
230
205
 
231
206
  const elements = Array.from(document.body.querySelectorAll('p'))
207
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
232
208
 
233
- const linkInjections = [{
234
- sid: '1',
235
- title: 'an injection',
236
- sentence: 'This is a sentence with an injection.',
237
- playpilot_url: 'https://some-link.com/',
238
- poster: 'some-poster',
239
- key: 'some-key-1',
240
- }]
241
-
242
- injectLinksInDocument(elements, linkInjections, () => null)
209
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
243
210
 
244
211
  expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
245
212
  })
@@ -252,7 +219,7 @@ describe('linkInjection.js', () => {
252
219
  /** @type {LinkInjection[]} */
253
220
  const linkInjections = []
254
221
 
255
- injectLinksInDocument(elements, linkInjections, () => null)
222
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
256
223
 
257
224
  expect(document.body.innerHTML.includes('This is a sentence with an injection.')).toBeTruthy()
258
225
  })
@@ -264,55 +231,37 @@ describe('linkInjection.js', () => {
264
231
  /** @type {LinkInjection[]} */
265
232
  const linkInjections = []
266
233
 
267
- expect(() => injectLinksInDocument(elements, linkInjections, () => null)).not.toThrow()
234
+ expect(() => injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })).not.toThrow()
268
235
  })
269
236
 
270
237
  it('Should fire given onclick function when clicked', async () => {
271
238
  document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
272
239
 
273
240
  const elements = Array.from(document.body.querySelectorAll('p'))
274
-
275
- const linkInjections = [{
276
- sid: '1',
277
- title: 'an injection',
278
- sentence: 'This is a sentence with an injection.',
279
- playpilot_url: 'https://some-link.com/',
280
- poster: 'some-poster',
281
- key: 'some-key',
282
- }]
241
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
283
242
 
284
243
  const mock = vi.fn()
285
- injectLinksInDocument(elements, linkInjections, mock)
244
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
286
245
 
287
246
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
288
247
  await fireEvent.click(link)
289
248
 
290
- expect(mock).toHaveBeenCalledWith(linkInjections[0])
249
+ expect(mock).toHaveBeenCalledWith(injection)
291
250
  })
292
251
 
293
252
  it('Should fire given onclick function when clicked for each link in a sentence if more than 1 injection is present', async () => {
294
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
253
+ const sentence = 'This is a sentence with an injection.'
254
+ document.body.innerHTML = `<p>${sentence}</p>`
295
255
 
296
256
  const elements = Array.from(document.body.querySelectorAll('p'))
297
257
 
298
- const linkInjections = [{
299
- sid: '1',
300
- title: 'a sentence',
301
- sentence: 'This is a sentence with an injection.',
302
- playpilot_url: 'https://some-link.com/',
303
- poster: 'some-poster',
304
- key: 'some-key-1',
305
- }, {
306
- sid: '2',
307
- title: 'an injection',
308
- sentence: 'This is a sentence with an injection.',
309
- playpilot_url: 'https://some-link.com/',
310
- poster: 'some-poster',
311
- key: 'some-key-2',
312
- }]
258
+ const linkInjections = [
259
+ generateInjection(sentence, 'a sentence'),
260
+ generateInjection(sentence, 'an injection'),
261
+ ]
313
262
 
314
263
  const mock = vi.fn()
315
- injectLinksInDocument(elements, linkInjections, mock)
264
+ injectLinksInDocument(elements, mock, { aiInjections: linkInjections, manualInjections: [] })
316
265
 
317
266
  const links = document.querySelectorAll('a')
318
267
  await fireEvent.click(links[0])
@@ -325,18 +274,10 @@ describe('linkInjection.js', () => {
325
274
  document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
326
275
 
327
276
  const elements = Array.from(document.body.querySelectorAll('p'))
328
-
329
- const linkInjections = [{
330
- sid: '1',
331
- title: 'an injection',
332
- sentence: 'This is a sentence with an injection.',
333
- playpilot_url: 'https://some-link.com/',
334
- poster: 'some-poster',
335
- key: 'some-key',
336
- }]
277
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
337
278
 
338
279
  const mock = vi.fn()
339
- injectLinksInDocument(elements, linkInjections, mock)
280
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
340
281
 
341
282
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
342
283
 
@@ -349,48 +290,30 @@ describe('linkInjection.js', () => {
349
290
  })
350
291
 
351
292
  it('Should return array with failed injections marked as such', () => {
352
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
293
+ const sentence = 'This is a sentence with an injection.'
294
+ document.body.innerHTML = `<p>${sentence}</p>`
353
295
 
354
296
  const elements = Array.from(document.body.querySelectorAll('p'))
355
297
 
356
- const linkInjections = [{
357
- sid: '1',
358
- title: 'a sentence',
359
- sentence: 'This is a sentence with an injection.',
360
- playpilot_url: 'https://some-link.com/',
361
- poster: 'some-poster',
362
- key: 'some-key-1',
363
- }, {
364
- sid: '2',
365
- title: 'not an injection',
366
- sentence: 'This is a sentence with an injection.',
367
- playpilot_url: 'https://some-link.com/',
368
- poster: 'some-poster',
369
- key: 'some-key-2',
370
- }]
371
-
372
- const results = injectLinksInDocument(elements, linkInjections, () => null)
298
+ const linkInjections = [
299
+ generateInjection(sentence, 'a sentence'),
300
+ generateInjection(sentence, 'not an injection'),
301
+ ]
302
+
303
+ const results = injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
373
304
 
374
- expect(results[1].failed).toBe(true)
375
305
  expect(results[0].failed).toBe(false)
306
+ expect(results[1].failed).toBe(true)
376
307
  })
377
308
 
378
309
  it('Should mount popover component when link is hovered and unmount when link is blurred', async () => {
379
310
  document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
380
311
 
381
312
  const elements = Array.from(document.body.querySelectorAll('p'))
382
-
383
- const linkInjections = [{
384
- sid: '1',
385
- title: 'an injection',
386
- sentence: 'This is a sentence with an injection.',
387
- playpilot_url: 'https://some-link.com/',
388
- poster: 'some-poster',
389
- key: 'some-key',
390
- }]
313
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
391
314
 
392
315
  const mock = vi.fn()
393
- injectLinksInDocument(elements, linkInjections, mock)
316
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
394
317
 
395
318
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
396
319
 
@@ -406,75 +329,66 @@ describe('linkInjection.js', () => {
406
329
 
407
330
  const elements = Array.from(document.querySelectorAll('p'))
408
331
 
409
- const linkInjections = [{
410
- sid: '1',
411
- title: 'injection',
412
- sentence: 'This is a sentence with an injection and another injection',
413
- playpilot_url: 'https://some-link.com/',
414
- poster: 'some-poster',
415
- key: 'some-key',
416
- }, {
417
- sid: '2',
418
- title: 'injection',
419
- sentence: 'This is a sentence with an injection and another injection',
420
- playpilot_url: 'https://some-link-2.com/',
421
- poster: 'some-poster',
422
- key: 'some-key-2',
423
- }]
424
-
425
- injectLinksInDocument(elements, linkInjections, () => null)
332
+ const sentence = 'This is a sentence with an injection and another injection'
333
+ const linkInjections = [
334
+ generateInjection(sentence, 'injection'),
335
+ generateInjection(sentence, 'injection'),
336
+ ]
337
+
338
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
426
339
 
427
340
  const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
428
341
 
429
342
  expect(links).toHaveLength(2)
430
- expect(links[0].dataset.playpilotInjectionKey).toBe('some-key')
431
- expect(links[1].dataset.playpilotInjectionKey).toBe('some-key-2')
343
+ expect(links[0].dataset.playpilotInjectionKey).toBe(linkInjections[0].key)
344
+ expect(links[1].dataset.playpilotInjectionKey).toBe(linkInjections[1].key)
432
345
  })
433
346
 
434
347
  it('Should not inject injections with in_text set to false', () => {
435
348
  document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
436
349
 
437
350
  const elements = Array.from(document.querySelectorAll('p'))
351
+ const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), in_text: false }
438
352
 
439
- const linkInjections = [{
440
- sid: '1',
441
- title: 'an injection',
442
- sentence: 'This is a sentence with an injection.',
443
- playpilot_url: 'https://some-link.com/',
444
- poster: 'some-poster',
445
- key: 'some-key',
446
- in_text: false,
447
- }]
448
-
449
- injectLinksInDocument(elements, linkInjections, () => null)
353
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
450
354
 
451
355
  expect(document.querySelector('a')).not.toBeTruthy()
452
356
  })
453
- })
454
357
 
455
- it('Should not mount popover if user uses touch', async () => {
456
- mockMatchMedia(true)
358
+ it('Should not mount popover if user uses touch', async () => {
359
+ mockMatchMedia(true)
457
360
 
458
- document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
361
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
362
+
363
+ const elements = Array.from(document.body.querySelectorAll('p'))
364
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
365
+
366
+ const mock = vi.fn()
367
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
368
+
369
+ const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
459
370
 
460
- const elements = Array.from(document.body.querySelectorAll('p'))
371
+ await fireEvent.mouseEnter(link)
372
+ expect(mount).not.toHaveBeenCalled()
373
+ })
461
374
 
462
- const linkInjections = [{
463
- sid: '1',
464
- title: 'an injection',
465
- sentence: 'This is a sentence with an injection.',
466
- playpilot_url: 'https://some-link.com/',
467
- poster: 'some-poster',
468
- key: 'some-key',
469
- }]
375
+ it('Should not call insertAfterArticlePlaylinks if injections only contain inactive or removed items', () => {
376
+ document.body.innerHTML = `<section>
377
+ <div>Some text</div>
378
+ <div>Some other text</div>
379
+ </section>
380
+ `
470
381
 
471
- const mock = vi.fn()
472
- injectLinksInDocument(elements, linkInjections, mock)
382
+ const elements = Array.from(document.body.querySelectorAll('div'))
383
+ const injection = generateInjection('Some sentence', 'an injection')
384
+ const linkInjections = [{ ...injection, after_article: true, inactive: true }, { ...injection, after_article: true, removed: true }]
473
385
 
474
- const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
386
+ const mock = vi.fn()
387
+ injectLinksInDocument(elements, mock, { aiInjections: [], manualInjections: linkInjections })
475
388
 
476
- await fireEvent.mouseEnter(link)
477
- expect(mount).not.toHaveBeenCalled()
389
+ expect(mount).not.toHaveBeenCalled()
390
+ expect(document.querySelector('[data-playpilot-after-article-playlinks]')).not.toBeTruthy()
391
+ })
478
392
  })
479
393
 
480
394
  describe('clearLinkInjections', () => {
@@ -679,17 +593,10 @@ describe('linkInjection.js', () => {
679
593
  </section>
680
594
  `
681
595
 
682
- const linkInjections = [{
683
- sid: '1',
684
- title: 'an injection',
685
- sentence: 'This is a sentence with an injection.',
686
- playpilot_url: 'https://some-link.com/',
687
- poster: 'some-poster',
688
- key: 'some-key',
689
- }]
596
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
690
597
 
691
598
  const elements = getLinkInjectionElements(document.body)
692
- insertAfterArticlePlaylinks(elements, linkInjections, () => null)
599
+ insertAfterArticlePlaylinks(elements, [injection], () => null)
693
600
 
694
601
  expect(mount).toHaveBeenCalled()
695
602
  expect(document.querySelector('[data-playpilot-after-article-playlinks]')).toBeTruthy()
@@ -754,4 +661,106 @@ describe('linkInjection.js', () => {
754
661
  expect(sortedInjections[2].key).toBe('a')
755
662
  })
756
663
  })
664
+
665
+ describe('isAvailableAsManualInjection', () => {
666
+ it('Should return true if the ai injection has a matching manual injection', () => {
667
+ const aiInjection = generateInjection('Some sentence', 'Some title')
668
+ const manualInjection = { ...aiInjection, manual: true }
669
+
670
+ expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection, manualInjection]))
671
+ })
672
+
673
+ it('Should return false if the ai injection has no matching manual injection', () => {
674
+ const aiInjection = generateInjection('Some sentence', 'Some title')
675
+
676
+ expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection]))
677
+ })
678
+
679
+ it('Should return false if the ai injection has a matching ai injection', () => {
680
+ const aiInjection = generateInjection('Some sentence', 'Some title')
681
+
682
+ expect(isAvailableAsManualInjection(aiInjection, 0, [aiInjection, aiInjection]))
683
+ })
684
+ })
685
+
686
+ describe('filterRemovedInjections', () => {
687
+ it('Should not return injections that are removed or have an removed manual equivalent', () => {
688
+ const aiInjection = generateInjection('Some sentence', 'Some title')
689
+ const manualInjection = { ...aiInjection, manual: true, removed: true }
690
+
691
+ expect(filterRemovedInjections([aiInjection, manualInjection])).toEqual([])
692
+ })
693
+
694
+ it('Should return ai injections that have no matching manual injection', () => {
695
+ const aiInjection = generateInjection('Some sentence', 'Some title')
696
+ const manualInjection = { ...generateInjection('Some other sentence', 'Some other title'), manual: true }
697
+
698
+ expect(filterRemovedInjections([aiInjection, manualInjection])).toEqual([aiInjection, manualInjection])
699
+ })
700
+
701
+ it('Should return manual injections that have been removed at one point, but a new injection for the same title was created', () => {
702
+ const manualInjection = { ...generateInjection('Some other sentence', 'Some other title'), manual: true }
703
+ const removedManualInjection = { ...manualInjection, removed: true }
704
+
705
+ expect(filterRemovedInjections([manualInjection, removedManualInjection])).toEqual([manualInjection])
706
+ })
707
+ })
708
+
709
+ describe('isEquivalentInjection', () => {
710
+ it('Should return true if injections have the same title and sentence', () => {
711
+ expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('a', 'b'))).toBe(true)
712
+ })
713
+
714
+ it('Should return false if injections have different titles', () => {
715
+ expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('a', 'c'))).toBe(false)
716
+ })
717
+
718
+ it('Should return false if injections have different sentences', () => {
719
+ expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('b', 'b'))).toBe(false)
720
+ })
721
+
722
+ it('Should return false if injections have both different titles and sentences', () => {
723
+ expect(isEquivalentInjection(generateInjection('a', 'b'), generateInjection('c', 'd'))).toBe(false)
724
+ })
725
+ })
726
+
727
+ describe('isValidInjection', () => {
728
+ it('Should only return true when the injection is valid', () => {
729
+ expect(isValidInjection({ ...generateInjection('a', 'b') })).toBe(true)
730
+ expect(isValidInjection({ ...generateInjection('a', 'b'), inactive: true })).toBe(false)
731
+ expect(isValidInjection({ ...generateInjection('a', 'b'), removed: true })).toBe(false)
732
+ expect(isValidInjection({ ...generateInjection('a', 'b'), duplicate: true })).toBe(false)
733
+ expect(isValidInjection({ ...generateInjection('a', 'b'), title_details: undefined })).toBe(false)
734
+ })
735
+ })
736
+
737
+ describe('filterInvalidInTextInjections', () => {
738
+ it('Should return injections that are valid', () => {
739
+ expect(filterInvalidInTextInjections([generateInjection('a', 'b')])).toHaveLength(1)
740
+ })
741
+
742
+ it('Should return not injections that inactive, removed, duplicate, have no title_details, or are not in_text', () => {
743
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), inactive: true }])).toHaveLength(0)
744
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), removed: true }])).toHaveLength(0)
745
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), duplicate: true }])).toHaveLength(0)
746
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), title_details: undefined }])).toHaveLength(0)
747
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: false }])).toHaveLength(0)
748
+
749
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: undefined }])).toHaveLength(1)
750
+ expect(filterInvalidInTextInjections([{ ...generateInjection('a', 'b'), in_text: true }])).toHaveLength(1)
751
+ })
752
+ })
753
+
754
+ describe('filterInvalidAfterArticleInjections', () => {
755
+ it('Should return not injections that inactive, removed, duplicate, have no title_details, or are not after_article', () => {
756
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), inactive: true }])).toHaveLength(0)
757
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), removed: true }])).toHaveLength(0)
758
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), duplicate: true }])).toHaveLength(0)
759
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), title_details: undefined }])).toHaveLength(0)
760
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: false }])).toHaveLength(0)
761
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: undefined }])).toHaveLength(0)
762
+
763
+ expect(filterInvalidAfterArticleInjections([{ ...generateInjection('a', 'b'), after_article: true }])).toHaveLength(1)
764
+ })
765
+ })
757
766
  })