@playpilot/tpi 3.3.3 → 3.4.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.
Files changed (35) hide show
  1. package/dist/link-injections.js +8 -8
  2. package/package.json +1 -1
  3. package/src/lib/api.ts +6 -9
  4. package/src/lib/hash.ts +4 -0
  5. package/src/lib/linkInjection.ts +15 -40
  6. package/src/lib/localization.ts +7 -7
  7. package/src/lib/scss/_mixins.scss +0 -13
  8. package/src/lib/scss/global.scss +0 -5
  9. package/src/lib/scss/variables.scss +1 -1
  10. package/src/lib/session.ts +78 -0
  11. package/src/lib/tracking.ts +1 -2
  12. package/src/lib/types/injection.d.ts +2 -0
  13. package/src/lib/types/session.d.ts +14 -0
  14. package/src/routes/+page.svelte +37 -7
  15. package/src/routes/components/AfterArticlePlaylinks.svelte +6 -5
  16. package/src/routes/components/Editorial/Editor.svelte +36 -26
  17. package/src/routes/components/Editorial/Session.svelte +97 -0
  18. package/src/routes/components/Modal.svelte +1 -3
  19. package/src/routes/components/Playlinks.svelte +4 -5
  20. package/src/routes/components/Popover.svelte +1 -3
  21. package/src/routes/components/Title.svelte +0 -5
  22. package/src/tests/lib/api.test.js +14 -14
  23. package/src/tests/lib/linkInjection.test.js +56 -51
  24. package/src/tests/lib/localization.test.js +0 -7
  25. package/src/tests/lib/session.test.js +95 -0
  26. package/src/tests/lib/tracking.test.js +0 -16
  27. package/src/tests/routes/+page.test.js +14 -4
  28. package/src/tests/routes/components/Editorial/Editor.test.js +17 -1
  29. package/src/tests/routes/components/Editorial/EditorItem.test.js +7 -7
  30. package/src/tests/routes/components/Editorial/Session.test.js +80 -0
  31. package/src/tests/setup.js +23 -5
  32. package/src/lib/event.ts +0 -6
  33. package/src/lib/viewTransition.ts +0 -25
  34. package/src/tests/lib/event.test.js +0 -22
  35. package/src/tests/lib/viewTransition.test.js +0 -13
@@ -3,7 +3,7 @@ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
3
3
 
4
4
  import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, getLinkInjectionElements, insertAfterArticlePlaylinks, getLinkInjectionsParentElement, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType } from '$lib/linkInjection'
5
5
  import { mount, unmount } from 'svelte'
6
- import { fakeFetch, generateInjection } from '../helpers'
6
+ import { generateInjection } from '../helpers'
7
7
 
8
8
  vi.mock('svelte', () => ({
9
9
  mount: vi.fn(),
@@ -23,11 +23,7 @@ function mockMatchMedia(matches = false) {
23
23
  describe('linkInjection.js', () => {
24
24
  beforeEach(() => {
25
25
  vi.resetAllMocks()
26
- clearLinkInjections()
27
-
28
26
  mockMatchMedia()
29
- fakeFetch()
30
- vi.mocked(mount).mockReturnValueOnce({})
31
27
 
32
28
  // @ts-ignore
33
29
  window.PlayPilotLinkInjections = {}
@@ -46,7 +42,7 @@ describe('linkInjection.js', () => {
46
42
 
47
43
  const elements = Array.from(document.querySelectorAll('p'))
48
44
 
49
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
45
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
50
46
 
51
47
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
52
48
 
@@ -65,7 +61,7 @@ describe('linkInjection.js', () => {
65
61
 
66
62
  const elements = Array.from(document.body.querySelectorAll('p'))
67
63
 
68
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
64
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
69
65
 
70
66
  const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
71
67
 
@@ -89,7 +85,7 @@ describe('linkInjection.js', () => {
89
85
 
90
86
  const elements = Array.from(document.body.querySelectorAll('p'))
91
87
 
92
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
88
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
93
89
 
94
90
  expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
95
91
  })
@@ -103,7 +99,7 @@ describe('linkInjection.js', () => {
103
99
 
104
100
  const elements = Array.from(document.body.querySelectorAll('p'))
105
101
 
106
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
102
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
107
103
 
108
104
  expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
109
105
  })
@@ -121,7 +117,7 @@ describe('linkInjection.js', () => {
121
117
  manualInjections: [{ ...injection, manual: true, removed: true }],
122
118
  }
123
119
 
124
- injectLinksInDocument(elements, injections)
120
+ injectLinksInDocument(elements, () => null, injections)
125
121
 
126
122
  expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
127
123
  })
@@ -139,7 +135,7 @@ describe('linkInjection.js', () => {
139
135
  manualInjections: [{ ...injection, manual: true, inactive: true }],
140
136
  }
141
137
 
142
- injectLinksInDocument(elements, injections)
138
+ injectLinksInDocument(elements, () => null, injections)
143
139
 
144
140
  expect(document.body.innerHTML).toBe(`<p>${sentence}</p>`)
145
141
  })
@@ -152,7 +148,7 @@ describe('linkInjection.js', () => {
152
148
 
153
149
  const elements = Array.from(document.body.querySelectorAll('p'))
154
150
 
155
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
151
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
156
152
 
157
153
  const button = /** @type {HTMLButtonElement} */ (document.querySelector('button'))
158
154
 
@@ -165,7 +161,7 @@ describe('linkInjection.js', () => {
165
161
  const elements = Array.from(document.body.querySelectorAll('p'))
166
162
  const injection = generateInjection('I am a title', 'a title')
167
163
 
168
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
164
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
169
165
 
170
166
  expect(document.body.innerHTML.includes(injection.sentence)).toBeTruthy()
171
167
  })
@@ -176,7 +172,7 @@ describe('linkInjection.js', () => {
176
172
  const elements = Array.from(document.body.querySelectorAll('p'))
177
173
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
178
174
 
179
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
175
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
180
176
 
181
177
  expect(document.body.innerHTML.includes('an injection')).not.toBeTruthy()
182
178
  expect(document.body.innerHTML.includes('an')).toBeTruthy()
@@ -188,7 +184,7 @@ describe('linkInjection.js', () => {
188
184
  const elements = Array.from(document.body.querySelectorAll('p'))
189
185
  const injection = generateInjection('This is a sentence &amp; an injection.', 'an injection')
190
186
 
191
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
187
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
192
188
 
193
189
  expect(document.querySelectorAll('a')).toHaveLength(1)
194
190
  })
@@ -199,7 +195,7 @@ describe('linkInjection.js', () => {
199
195
  const elements = Array.from(document.body.querySelectorAll('p'))
200
196
  const injection = generateInjection('This is a sentence with an injection.', 'a sentence')
201
197
 
202
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
198
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
203
199
 
204
200
  expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
205
201
  })
@@ -210,7 +206,7 @@ describe('linkInjection.js', () => {
210
206
  const elements = Array.from(document.body.querySelectorAll('p'))
211
207
  const injection = generateInjection('This is a sentence with an injection.', 'some word')
212
208
 
213
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
209
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
214
210
 
215
211
  expect(document.querySelector('[data-playpilot-injection-key]')).not.toBeTruthy()
216
212
  })
@@ -221,7 +217,7 @@ describe('linkInjection.js', () => {
221
217
  const elements = Array.from(document.body.querySelectorAll('p'))
222
218
  const injection = generateInjection('This is a word with a word.', 'a word')
223
219
 
224
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
220
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
225
221
 
226
222
  expect(document.querySelectorAll('a')).toHaveLength(2)
227
223
  expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
@@ -233,7 +229,7 @@ describe('linkInjection.js', () => {
233
229
  const elements = Array.from(document.body.querySelectorAll('p'))
234
230
  const injection = generateInjection('This is a word with a word.', 'a word')
235
231
 
236
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
232
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
237
233
 
238
234
  expect(document.querySelectorAll('a')).toHaveLength(2)
239
235
  expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
@@ -245,7 +241,7 @@ describe('linkInjection.js', () => {
245
241
  const elements = Array.from(document.body.querySelectorAll('p'))
246
242
  const injection = generateInjection('this is a word with a word.', 'a word')
247
243
 
248
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
244
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
249
245
 
250
246
  expect(document.querySelectorAll('a')).toHaveLength(2)
251
247
  expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
@@ -258,7 +254,7 @@ describe('linkInjection.js', () => {
258
254
  const elements = Array.from(document.body.querySelectorAll('p'))
259
255
  const injection = generateInjection('But this sentence is a match.', 'a match')
260
256
 
261
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
257
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
262
258
 
263
259
  expect(document.body.innerHTML).toContain('This is a match')
264
260
  expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
@@ -270,7 +266,7 @@ describe('linkInjection.js', () => {
270
266
  const elements = Array.from(document.body.querySelectorAll('p'))
271
267
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
272
268
 
273
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
269
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
274
270
 
275
271
  expect(document.querySelector('[data-playpilot-injection-key]')).toBeTruthy()
276
272
  })
@@ -283,7 +279,7 @@ describe('linkInjection.js', () => {
283
279
  /** @type {import('$lib/types/injection').LinkInjection[]} */
284
280
  const linkInjections = []
285
281
 
286
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
282
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
287
283
 
288
284
  expect(document.body.innerHTML.includes('This is a sentence with an injection.')).toBeTruthy()
289
285
  })
@@ -295,24 +291,25 @@ describe('linkInjection.js', () => {
295
291
  /** @type {import('$lib/types/injection').LinkInjection[]} */
296
292
  const linkInjections = []
297
293
 
298
- expect(() => injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })).not.toThrow()
294
+ expect(() => injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })).not.toThrow()
299
295
  })
300
296
 
301
- it('Should mount modal when clicked', async () => {
297
+ it('Should fire given onclick function when clicked', async () => {
302
298
  document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
303
299
 
304
300
  const elements = Array.from(document.body.querySelectorAll('p'))
305
301
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
306
302
 
307
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
303
+ const mock = vi.fn()
304
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
308
305
 
309
306
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
310
307
  await fireEvent.click(link)
311
308
 
312
- expect(mount).toHaveBeenCalled()
309
+ expect(mock).toHaveBeenCalledWith(injection)
313
310
  })
314
311
 
315
- it('Should not mount modal multiple times if modal is already open', async () => {
312
+ it('Should fire given onclick function when clicked for each link in a sentence if more than 1 injection is present', async () => {
316
313
  const sentence = 'This is a sentence with an injection.'
317
314
  document.body.innerHTML = `<p>${sentence}</p>`
318
315
 
@@ -323,13 +320,14 @@ describe('linkInjection.js', () => {
323
320
  generateInjection(sentence, 'an injection'),
324
321
  ]
325
322
 
326
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
323
+ const mock = vi.fn()
324
+ injectLinksInDocument(elements, mock, { aiInjections: linkInjections, manualInjections: [] })
327
325
 
328
326
  const links = document.querySelectorAll('a')
329
327
  await fireEvent.click(links[0])
330
328
  await fireEvent.click(links[1])
331
329
 
332
- expect(mount).toHaveBeenCalledTimes(1)
330
+ expect(mock).toHaveBeenCalledTimes(2)
333
331
  })
334
332
 
335
333
  it('Should not fire given onclick function when clicked with modifier keys or not left click', async () => {
@@ -339,7 +337,7 @@ describe('linkInjection.js', () => {
339
337
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
340
338
 
341
339
  const mock = vi.fn()
342
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
340
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
343
341
 
344
342
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
345
343
 
@@ -362,7 +360,7 @@ describe('linkInjection.js', () => {
362
360
  generateInjection(sentence, 'not an injection'),
363
361
  ]
364
362
 
365
- const results = injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
363
+ const results = injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
366
364
 
367
365
  expect(results[0].failed).toBe(false)
368
366
  expect(results[1].failed).toBe(true)
@@ -379,7 +377,7 @@ describe('linkInjection.js', () => {
379
377
  generateInjection('Some unknown sentence', 'nothing'),
380
378
  ]
381
379
 
382
- const results = injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
380
+ const results = injectLinksInDocument(elements, () => null, { aiInjections: [], manualInjections: linkInjections })
383
381
 
384
382
  expect(results[0].failed_message).toBe('Given text is already inside of a link.')
385
383
  expect(results[1].failed_message).toBe('Given sentence was not found in the article.')
@@ -391,7 +389,8 @@ describe('linkInjection.js', () => {
391
389
  const elements = Array.from(document.body.querySelectorAll('p'))
392
390
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
393
391
 
394
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
392
+ const mock = vi.fn()
393
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
395
394
 
396
395
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
397
396
 
@@ -411,7 +410,8 @@ describe('linkInjection.js', () => {
411
410
  const elements = Array.from(document.body.querySelectorAll('p'))
412
411
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
413
412
 
414
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
413
+ const mock = vi.fn()
414
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
415
415
 
416
416
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
417
417
 
@@ -432,7 +432,8 @@ describe('linkInjection.js', () => {
432
432
  const elements = Array.from(document.body.querySelectorAll('p'))
433
433
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
434
434
 
435
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
435
+ const mock = vi.fn()
436
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
436
437
 
437
438
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
438
439
 
@@ -452,7 +453,8 @@ describe('linkInjection.js', () => {
452
453
  const elements = Array.from(document.body.querySelectorAll('p'))
453
454
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
454
455
 
455
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
456
+ const mock = vi.fn()
457
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
456
458
 
457
459
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('[data-playpilot-injection-key]'))
458
460
 
@@ -479,7 +481,7 @@ describe('linkInjection.js', () => {
479
481
  generateInjection(sentence, 'injection'),
480
482
  ]
481
483
 
482
- injectLinksInDocument(elements, { aiInjections: linkInjections, manualInjections: [] })
484
+ injectLinksInDocument(elements, () => null, { aiInjections: linkInjections, manualInjections: [] })
483
485
 
484
486
  const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('[data-playpilot-injection-key]')))
485
487
 
@@ -494,7 +496,7 @@ describe('linkInjection.js', () => {
494
496
  const elements = Array.from(document.querySelectorAll('p'))
495
497
  const injection = { ...generateInjection('This is a sentence with an injection.', 'an injection'), in_text: false }
496
498
 
497
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
499
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
498
500
 
499
501
  expect(document.querySelector('a')).not.toBeTruthy()
500
502
  })
@@ -507,7 +509,8 @@ describe('linkInjection.js', () => {
507
509
  const elements = Array.from(document.body.querySelectorAll('p'))
508
510
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
509
511
 
510
- injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
512
+ const mock = vi.fn()
513
+ injectLinksInDocument(elements, mock, { aiInjections: [injection], manualInjections: [] })
511
514
 
512
515
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
513
516
 
@@ -526,7 +529,8 @@ describe('linkInjection.js', () => {
526
529
  const injection = generateInjection('Some sentence', 'an injection')
527
530
  const linkInjections = [{ ...injection, after_article: true, inactive: true }, { ...injection, after_article: true, removed: true }]
528
531
 
529
- injectLinksInDocument(elements, { aiInjections: [], manualInjections: linkInjections })
532
+ const mock = vi.fn()
533
+ injectLinksInDocument(elements, mock, { aiInjections: [], manualInjections: linkInjections })
530
534
 
531
535
  expect(mount).not.toHaveBeenCalled()
532
536
  expect(document.querySelector('[data-playpilot-after-article-playlinks]')).not.toBeTruthy()
@@ -549,7 +553,8 @@ describe('linkInjection.js', () => {
549
553
  generateInjection('Some fourthtext', 'Some'),
550
554
  ]
551
555
 
552
- injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
556
+ const mock = vi.fn()
557
+ injectLinksInDocument(elements, mock, { aiInjections: [], manualInjections: injections })
553
558
 
554
559
  expect(document.querySelectorAll('a')).toHaveLength(4)
555
560
  })
@@ -569,7 +574,8 @@ describe('linkInjection.js', () => {
569
574
  generateInjection('Somethird text', 'Some'),
570
575
  ]
571
576
 
572
- injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
577
+ const mock = vi.fn()
578
+ injectLinksInDocument(elements, mock, { aiInjections: [], manualInjections: injections })
573
579
 
574
580
  expect(document.querySelectorAll('a')).toHaveLength(3)
575
581
  })
@@ -593,7 +599,7 @@ describe('linkInjection.js', () => {
593
599
  generateInjection('First Title Some other title', 'Fourth'),
594
600
  ]
595
601
 
596
- injectLinksInDocument(elements, { aiInjections: [], manualInjections: injections })
602
+ injectLinksInDocument(elements, () => null, { aiInjections: [], manualInjections: injections })
597
603
 
598
604
  expect(document.querySelectorAll('a')).toHaveLength(4)
599
605
  })
@@ -696,7 +702,7 @@ describe('linkInjection.js', () => {
696
702
  expect(getLinkInjectionElements(parent)[1].tagName).toBe('OL')
697
703
  })
698
704
 
699
- it('Should ignore links, buttons, script tags, style tags, iframes, headers, and more', () => {
705
+ it('Should ignore links, buttons, script tags, style tags, iframes, and headers', () => {
700
706
  document.body.innerHTML = `<section>
701
707
  <h1>Some header</h1>
702
708
  <h4>Some smaller header</h4>
@@ -708,7 +714,6 @@ describe('linkInjection.js', () => {
708
714
  <style>I am styling</style>
709
715
  <iframe>I am an iframe</iframe>
710
716
  <noscript>I am noscript</noscript>
711
- <figcaption>I am a figcaption</figcaption>
712
717
 
713
718
  <div>
714
719
  <a>I am another link</a>
@@ -817,7 +822,7 @@ describe('linkInjection.js', () => {
817
822
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
818
823
 
819
824
  const elements = getLinkInjectionElements(document.body)
820
- insertAfterArticlePlaylinks(elements, [injection])
825
+ insertAfterArticlePlaylinks(elements, [injection], () => null)
821
826
 
822
827
  expect(mount).toHaveBeenCalled()
823
828
  expect(document.querySelector('p:last-of-type + [data-playpilot-after-article-playlinks]')).toBeTruthy()
@@ -831,7 +836,7 @@ describe('linkInjection.js', () => {
831
836
  `
832
837
 
833
838
  const elements = getLinkInjectionElements(document.body)
834
- insertAfterArticlePlaylinks(elements, [])
839
+ insertAfterArticlePlaylinks(elements, [], () => null)
835
840
 
836
841
  expect(mount).not.toHaveBeenCalled()
837
842
  expect(document.querySelector('[data-playpilot-after-article-playlinks]')).not.toBeTruthy()
@@ -849,7 +854,7 @@ describe('linkInjection.js', () => {
849
854
 
850
855
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
851
856
  const elements = getLinkInjectionElements(document.body)
852
- insertAfterArticlePlaylinks(elements, [injection])
857
+ insertAfterArticlePlaylinks(elements, [injection], () => null)
853
858
 
854
859
  expect(document.querySelector('hr + [data-playpilot-after-article-playlinks]')).toBeTruthy()
855
860
  })
@@ -866,7 +871,7 @@ describe('linkInjection.js', () => {
866
871
 
867
872
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
868
873
  const elements = getLinkInjectionElements(document.body)
869
- insertAfterArticlePlaylinks(elements, [injection])
874
+ insertAfterArticlePlaylinks(elements, [injection], () => null)
870
875
 
871
876
  expect(document.querySelector('hr + [data-playpilot-after-article-playlinks]')).toBeTruthy()
872
877
  })
@@ -884,7 +889,7 @@ describe('linkInjection.js', () => {
884
889
 
885
890
  const injection = generateInjection('This is a sentence with an injection.', 'an injection')
886
891
  const elements = getLinkInjectionElements(document.body)
887
- insertAfterArticlePlaylinks(elements, [injection])
892
+ insertAfterArticlePlaylinks(elements, [injection], () => null)
888
893
 
889
894
  expect(document.querySelector('[data-playpilot-after-article-playlinks] + hr')).toBeTruthy()
890
895
  })
@@ -53,13 +53,6 @@ describe('localization.js', () => {
53
53
  expect(getLanguage()).toBe('sv-SE')
54
54
  })
55
55
 
56
- it('Should return the language given as document language even when using shorthand', () => {
57
- const html = /** @type {HTMLElement} */ (document.querySelector('html'))
58
- html.setAttribute('lang', 'sv')
59
-
60
- expect(getLanguage()).toBe('sv-SE')
61
- })
62
-
63
56
  it('Should return the default language when document language is invalid', () => {
64
57
  const html = /** @type {HTMLElement} */ (document.querySelector('html'))
65
58
  html.setAttribute('lang', 'no')
@@ -0,0 +1,95 @@
1
+ import { describe, it, expect, afterEach, vi } from 'vitest'
2
+ import { fetchAsSession, getSessionId, isAllowedToEdit, sessionKey, setSessionId } from '$lib/session'
3
+ import { fetchLinkInjections } from '$lib/api'
4
+ import { waitFor } from '@testing-library/svelte'
5
+
6
+ vi.mock('$lib/api', () => ({
7
+ fetchLinkInjections: vi.fn(() => {}),
8
+ }))
9
+
10
+ describe('session.ts', () => {
11
+ afterEach(() => {
12
+ sessionStorage.clear()
13
+ vi.resetAllMocks()
14
+ })
15
+
16
+ describe('fetchAsSession', () => {
17
+ it('Should fetch and fetch again when user is allowed to edit', async() => {
18
+ // @ts-ignore
19
+ vi.mocked(fetchLinkInjections).mockResolvedValue({ session_id: 'a', session_last_ping: null })
20
+
21
+ fetchAsSession('abc')
22
+
23
+ await waitFor(() => {
24
+ expect(fetchLinkInjections).toHaveBeenCalledTimes(2)
25
+ })
26
+ })
27
+
28
+ it('Should fetch only once if user is not allowed to edit', async() => {
29
+ // @ts-ignore
30
+ vi.mocked(fetchLinkInjections).mockResolvedValue({ session_id: 'a', session_last_ping: Date.now().toString() })
31
+
32
+ fetchAsSession('abc')
33
+
34
+ await new Promise(res => setTimeout(res, 100)) // Await potential fetch
35
+
36
+ expect(fetchLinkInjections).toHaveBeenCalledOnce()
37
+ })
38
+ })
39
+
40
+ describe('isAllowedToEdit', () => {
41
+ it('Should return true if either argument is null or empty', () => {
42
+ expect(isAllowedToEdit('a', null)).toBe(true)
43
+ expect(isAllowedToEdit('a', '')).toBe(true)
44
+
45
+ expect(isAllowedToEdit(null, Date.now().toString())).toBe(true)
46
+ expect(isAllowedToEdit('', Date.now().toString())).toBe(true)
47
+ })
48
+
49
+ it('Should return true if session id is given and last ping is more than 10 seconds ago', () => {
50
+ expect(isAllowedToEdit('a', '2020-10-10')).toBe(true)
51
+ expect(isAllowedToEdit('a', '0')).toBe(true)
52
+ expect(isAllowedToEdit('a', new Date(Date.now() - 11000).toString())).toBe(true)
53
+ })
54
+
55
+ it('Should return false if session id equals current session id regardless of last ping', () => {
56
+ sessionStorage.setItem(sessionKey, 'me')
57
+
58
+ expect(isAllowedToEdit('me', '2020-10-10')).toBe(true)
59
+ expect(isAllowedToEdit('me', Date.now().toString())).toBe(true)
60
+ })
61
+ })
62
+
63
+ describe('getSessionId', () => {
64
+ it('Should get the item stored in session storage', () => {
65
+ sessionStorage.setItem(sessionKey, 'abc')
66
+ expect(getSessionId()).toBe('abc')
67
+ })
68
+
69
+ it('Should set a new item if no value is stored in session storage', () => {
70
+ sessionStorage.setItem(sessionKey, 'abc')
71
+
72
+ const result = getSessionId()
73
+
74
+ expect(result).toEqual(expect.any(String))
75
+ expect(sessionStorage.getItem(sessionKey)).toBe(result)
76
+ })
77
+ })
78
+
79
+ describe('setSessionId', () => {
80
+ it('Should set a new item in session storage when no previous value is set', () => {
81
+ const result = setSessionId()
82
+
83
+ expect(result).toEqual(expect.any(String))
84
+ expect(sessionStorage.getItem(sessionKey)).toBe(result)
85
+ })
86
+
87
+ it('Should return existing item in session storage when set', () => {
88
+ sessionStorage.setItem(sessionKey, 'abc')
89
+ const result = setSessionId()
90
+
91
+ expect(result).toBe('abc')
92
+ expect(sessionStorage.getItem(sessionKey)).toBe('abc')
93
+ })
94
+ })
95
+ })
@@ -4,7 +4,6 @@ import { setTrackingSids, track } from '$lib/tracking'
4
4
  import { title } from '$lib/fakeData'
5
5
  import { get } from 'svelte/store'
6
6
  import { currentDomainSid, currentOrganizationSid } from '$lib/stores/organization'
7
- import { getFullUrlPath } from '$lib/url'
8
7
 
9
8
  global.fetch = vi.fn()
10
9
 
@@ -41,21 +40,6 @@ describe('$lib/tracking', () => {
41
40
  )
42
41
  })
43
42
 
44
- it('Should strip url to full path only', () => {
45
- window.location.href = 'https://some-url.com/page?key=value'
46
-
47
- track('Some event')
48
-
49
- expect(global.fetch).toHaveBeenCalledWith(
50
- expect.any(String),
51
- expect.objectContaining({
52
- body: expect.stringMatching(
53
- new RegExp(`"url":"${getFullUrlPath()}"`),
54
- ),
55
- }),
56
- )
57
- })
58
-
59
43
  it('Should include domain sid in request', () => {
60
44
  currentDomainSid.set('some-domain')
61
45
 
@@ -11,10 +11,20 @@ import { injectLinksInDocument } from '$lib/linkInjection'
11
11
  import { isCrawler } from '$lib/crawler'
12
12
 
13
13
  vi.mock('$lib/api', () => ({
14
+ fetchLinkInjections: vi.fn(() => {}),
14
15
  pollLinkInjections: vi.fn(() => {}),
15
16
  fetchConfig: vi.fn(),
16
17
  }))
17
18
 
19
+ // @ts-ignore
20
+ vi.mock(import('$lib/session'), async (importOriginal) => {
21
+ const actual = await importOriginal()
22
+ return {
23
+ ...actual,
24
+ fetchAsSession: vi.fn(() => {}),
25
+ }
26
+ })
27
+
18
28
  vi.mock(import('$lib/linkInjection'), async (importOriginal) => {
19
29
  const actual = await importOriginal()
20
30
  return {
@@ -80,8 +90,8 @@ describe('$routes/+page.svelte', () => {
80
90
  render(page)
81
91
 
82
92
  await waitFor(() => {
83
- expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), expect.any(String), { maxTries: 1 })
84
- expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), expect.any(String), { requireCompletedResult: true, onpoll: expect.any(Function) })
93
+ expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), { maxTries: 1 })
94
+ expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), { requireCompletedResult: true, onpoll: expect.any(Function) })
85
95
  })
86
96
  })
87
97
 
@@ -104,7 +114,7 @@ describe('$routes/+page.svelte', () => {
104
114
  })
105
115
 
106
116
  await waitFor(() => {
107
- expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), expect.any(String), { requireCompletedResult: true, onpoll: expect.any(Function) })
117
+ expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), { requireCompletedResult: true, onpoll: expect.any(Function) })
108
118
  })
109
119
 
110
120
  expect(pollLinkInjections).toHaveBeenCalledTimes(2)
@@ -167,7 +177,7 @@ describe('$routes/+page.svelte', () => {
167
177
  render(page)
168
178
 
169
179
  await waitFor(() => {
170
- expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), '<p>Here</p>', { maxTries: 1 })
180
+ expect(pollLinkInjections).toHaveBeenCalledWith('<p>Here</p>', { maxTries: 1 })
171
181
  })
172
182
  })
173
183
 
@@ -1,21 +1,37 @@
1
1
  import { fireEvent, render } from '@testing-library/svelte'
2
- import { describe, expect, it, vi } from 'vitest'
2
+ import { beforeAll, describe, expect, it, vi } from 'vitest'
3
3
 
4
4
  import Editor from '../../../../routes/components/Editorial/Editor.svelte'
5
5
  import { title } from '$lib/fakeData'
6
6
  import { generateInjection } from '../../../helpers'
7
7
  import { track } from '$lib/tracking'
8
8
  import { TrackingEvent } from '$lib/enums/TrackingEvent'
9
+ import { fetchLinkInjections } from '$lib/api'
9
10
 
10
11
  vi.mock('$lib/api', () => ({
11
12
  saveLinkInjections: vi.fn(),
13
+ fetchLinkInjections: vi.fn(() => {}),
12
14
  }))
13
15
 
16
+ // @ts-ignore
17
+ vi.mock(import('$lib/session'), async (importOriginal) => {
18
+ const actual = await importOriginal()
19
+ return {
20
+ ...actual,
21
+ isAllowedToEdit: vi.fn(() => true),
22
+ }
23
+ })
24
+
14
25
  vi.mock('$lib/tracking', () => ({
15
26
  track: vi.fn(),
16
27
  }))
17
28
 
18
29
  describe('Editor.svelte', () => {
30
+ beforeAll(() => {
31
+ // @ts-ignore
32
+ vi.mocked(fetchLinkInjections).mockResolvedValue({})
33
+ })
34
+
19
35
  /** @type {import('$lib/types/injection').LinkInjection[]} */
20
36
  const linkInjections = [
21
37
  generateInjection('This is a sentence with an injection.', 'an injection'),