@playpilot/tpi 3.2.0-beta.1 → 3.2.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.
@@ -6,6 +6,7 @@
6
6
  import IconIMDb from './Icons/IconIMDb.svelte'
7
7
  import { t } from '$lib/localization'
8
8
  import type { TitleData } from '$lib/types/title'
9
+ import { heading } from '$lib/actions/heading'
9
10
 
10
11
  interface Props {
11
12
  title: TitleData
@@ -33,7 +34,7 @@
33
34
  </div>
34
35
  {/if}
35
36
 
36
- <h1 class:truncate={small}>{title.title}</h1>
37
+ <div class="heading" use:heading class:truncate={small}>{title.title}</div>
37
38
 
38
39
  <div class="info">
39
40
  <div class="imdb">
@@ -78,7 +79,7 @@
78
79
  </div>
79
80
 
80
81
  <style lang="scss">
81
- h1 {
82
+ .heading {
82
83
  margin: margin(0.5) 0;
83
84
  color: var(--playpilot-detail-title-text-color, #fff);
84
85
  font-family: var(--playpilot-detail-title-font-family, inherit);
@@ -1,7 +1,7 @@
1
1
  import { fireEvent } from '@testing-library/svelte'
2
2
  import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
3
3
 
4
- import { injectLinksInDocument, clearLinkInjections, clearLinkInjection, getLinkInjectionElements, insertAfterArticlePlaylinks, getLinkInjectionsParentElement, sortLinkInjectionsByRange, isAvailableAsManualInjection, filterRemovedAndInactiveInjections, isEquivalentInjection, filterInvalidInTextInjections, filterInvalidAfterArticleInjections, isValidInjection, isValidPlaylinkType } from '$lib/linkInjection'
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
6
  import { generateInjection } from '../helpers'
7
7
 
@@ -219,8 +219,6 @@ describe('linkInjection.js', () => {
219
219
 
220
220
  injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
221
221
 
222
- console.log(document.body.innerHTML)
223
-
224
222
  expect(document.querySelectorAll('a')).toHaveLength(2)
225
223
  expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
226
224
  })
@@ -233,8 +231,6 @@ describe('linkInjection.js', () => {
233
231
 
234
232
  injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
235
233
 
236
- console.log(document.body.innerHTML)
237
-
238
234
  expect(document.querySelectorAll('a')).toHaveLength(2)
239
235
  expect(Array.from(document.querySelectorAll('a')).filter(a => a.innerText === 'a word')).toHaveLength(2)
240
236
  })
@@ -252,6 +248,18 @@ describe('linkInjection.js', () => {
252
248
  expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
253
249
  })
254
250
 
251
+ it('Should inject into correct sentence when element contains other sentences with the same matching title', () => {
252
+ document.body.innerHTML = '<p>This is a match. But this sentence is a match.</p>'
253
+
254
+ const elements = Array.from(document.body.querySelectorAll('p'))
255
+ const injection = generateInjection('But this sentence is a match.', 'a match')
256
+
257
+ injectLinksInDocument(elements, () => null, { aiInjections: [injection], manualInjections: [] })
258
+
259
+ expect(document.body.innerHTML).toContain('This is a match')
260
+ expect(document.querySelectorAll('[data-playpilot-injection-key]')).toHaveLength(1)
261
+ })
262
+
255
263
  it('Should inject properly when sentence contains element that are not part of the match', () => {
256
264
  document.body.innerHTML = '<p>This is <a>a sentence</a> with an injection.</p>'
257
265
 
@@ -84,6 +84,79 @@ describe('$routes/+page.svelte', () => {
84
84
  })
85
85
  })
86
86
 
87
+ it('Should continue response while in editorial mode and ai_running and automation_enabled are true', async () => {
88
+ // @ts-ignore
89
+ window.PlayPilotLinkInjections = { editorial_token: 'some-token' }
90
+
91
+ // @ts-ignore
92
+ vi.mocked(pollLinkInjections).mockImplementationOnce(async () => {
93
+ await new Promise(res => setTimeout(res, 100))
94
+ return { ai_injections: [], link_injections: [], ai_running: true, automation_enabled: true }
95
+ })
96
+
97
+ render(page)
98
+
99
+ // @ts-ignore
100
+ vi.mocked(pollLinkInjections).mockImplementationOnce(async () => {
101
+ await new Promise(res => setTimeout(res, 100))
102
+ return { ai_injections: ['a'], link_injections: ['b'], ai_running: true, automation_enabled: true }
103
+ })
104
+
105
+ await waitFor(() => {
106
+ expect(pollLinkInjections).toHaveBeenCalledWith(expect.any(String), expect.any(String), { requireCompletedResult: true })
107
+ })
108
+
109
+ expect(pollLinkInjections).toHaveBeenCalledTimes(2)
110
+ expect(injectLinksInDocument).toHaveBeenCalledOnce()
111
+ })
112
+
113
+ it('Should not continue response while in editorial mode but ai_running or automation_enabled are not true', async () => {
114
+ // @ts-ignore
115
+ window.PlayPilotLinkInjections = { editorial_token: 'some-token' }
116
+
117
+ // @ts-ignore
118
+ vi.mocked(pollLinkInjections).mockImplementationOnce(async () => {
119
+ await new Promise(res => setTimeout(res, 100))
120
+ return { ai_injections: [], link_injections: [], ai_running: false, automation_enabled: false }
121
+ })
122
+
123
+ render(page)
124
+
125
+ await new Promise(res => setTimeout(res, 500)) // Await possible response
126
+
127
+ expect(pollLinkInjections).toHaveBeenCalledTimes(1)
128
+ })
129
+
130
+ it('Should not continue response or inject while not in editorial mode and ai_running and automation_enabled are true', async () => {
131
+ // @ts-ignore
132
+ vi.mocked(pollLinkInjections).mockImplementationOnce(async () => {
133
+ await new Promise(res => setTimeout(res, 100))
134
+ return { ai_injections: [], link_injections: [], ai_running: true, automation_enabled: true }
135
+ })
136
+
137
+ render(page)
138
+
139
+ await new Promise(res => setTimeout(res, 500)) // Await possible response
140
+
141
+ expect(pollLinkInjections).toHaveBeenCalledTimes(1)
142
+ expect(injectLinksInDocument).not.toHaveBeenCalled()
143
+ })
144
+
145
+ it('Should not continue response but should inject while not in editorial mode and ai_running is false', async () => {
146
+ // @ts-ignore
147
+ vi.mocked(pollLinkInjections).mockImplementationOnce(async () => {
148
+ await new Promise(res => setTimeout(res, 100))
149
+ return { ai_injections: [], link_injections: [], ai_running: false, automation_enabled: true }
150
+ })
151
+
152
+ render(page)
153
+
154
+ await new Promise(res => setTimeout(res, 500)) // Await possible response
155
+
156
+ expect(pollLinkInjections).toHaveBeenCalledTimes(1)
157
+ expect(injectLinksInDocument).toHaveBeenCalled()
158
+ })
159
+
87
160
  it('Should use the given selector when present', async () => {
88
161
  document.body.innerHTML = '<div class="some-element"><p>Here</p></div> <p>Not here</p>'
89
162
 
@@ -1,68 +1,47 @@
1
- import { fireEvent, render, waitFor } from '@testing-library/svelte'
2
- import { describe, expect, it, vi } from 'vitest'
1
+ import { render } from '@testing-library/svelte'
2
+ import { describe, expect, it } from 'vitest'
3
3
 
4
4
  import AIIndicator from '../../../../routes/components/Editorial/AIIndicator.svelte'
5
- import { generateInjection } from '../../../helpers'
6
5
 
7
6
  describe('AIIndicator.svelte', () => {
8
7
  it('Should show disabled state by default', () => {
9
- const { getByText, queryByTestId } = render(AIIndicator, { onadd: () => null })
8
+ const { getByText, queryByTestId } = render(AIIndicator)
10
9
 
11
10
  expect(getByText('AI processing is disabled', { exact: false })).toBeTruthy()
12
11
  expect(queryByTestId('loading-bar')).not.toBeTruthy()
13
12
  })
14
13
 
15
- it('Should should running state if automation is enabled', () => {
16
- const { getByText, getByTestId } = render(AIIndicator, { onadd: () => null, automationEnabled: true })
14
+ it('Should show running when aiRunning and automationEnabled are true', () => {
15
+ const { getByText, getByTestId } = render(AIIndicator, { aiRunning: true, automationEnabled: true })
17
16
 
18
17
  expect(getByText('AI links are currently processing.', { exact: false })).toBeTruthy()
19
18
  expect(getByTestId('loading-bar')).toBeTruthy()
20
19
  })
21
20
 
22
- it('Should show completed state with text depending on length of given array', async () => {
23
- const { getByText, component, queryByTestId } = render(AIIndicator, { onadd: () => null, automationEnabled: true })
21
+ it('Should not show animator or loading bar if aiRunning is false', () => {
22
+ const { queryByTestId } = render(AIIndicator, { aiRunning: false })
24
23
 
25
- component.notifyUserOfNewState([generateInjection('Some sentence', 'Some title')])
26
- await waitFor(() => {
27
- expect(getByText('AI links are ready.', { exact: false })).toBeTruthy()
28
- expect(getByText('1 New link was found.')).toBeTruthy()
29
- expect(queryByTestId('loading-bar')).not.toBeTruthy()
30
- })
31
-
32
- component.notifyUserOfNewState([generateInjection('Some sentence', 'Some title'), generateInjection('Some sentence', 'Some title')])
33
- await waitFor(() => {
34
- expect(getByText('AI links are ready.', { exact: false })).toBeTruthy()
35
- expect(getByText('2 New links were found.')).toBeTruthy()
36
- })
37
-
38
- component.notifyUserOfNewState([])
39
- await waitFor(() => {
40
- expect(getByText('AI links finished running, but no new links were found.')).toBeTruthy()
41
- expect(queryByTestId('loading-bar')).not.toBeTruthy()
42
- })
24
+ expect(queryByTestId('loading-bar')).not.toBeTruthy()
25
+ expect(queryByTestId('animator')).not.toBeTruthy()
43
26
  })
44
27
 
45
- it('Should close element when dismiss button is clicked', async () => {
46
- const { getByText, component, container } = render(AIIndicator, { onadd: () => null, automationEnabled: true })
28
+ it('Should show given message if aiRunning is true', () => {
29
+ const { getByText } = render(AIIndicator, { aiRunning: true, automationEnabled: true, message: 'Some message' })
47
30
 
48
- component.notifyUserOfNewState([])
49
- await waitFor(() => getByText('Dismiss'))
50
-
51
- await fireEvent.click(getByText('Dismiss'))
52
- expect(container.querySelector('.ai-indicator')).not.toBeTruthy()
31
+ expect(getByText('Some message')).toBeTruthy()
53
32
  })
54
33
 
55
- it('Should close element and call onadd when Add AI links button is clicked', async () => {
56
- const onadd = vi.fn()
57
- const { getByText, component, container } = render(AIIndicator, { onadd, automationEnabled: true })
34
+ it('Should set progress bar to given progress percentage', () => {
35
+ const { getByText, getByTestId } = render(AIIndicator, { aiRunning: true, automationEnabled: true, percentage: 25 })
58
36
 
59
- const injection = generateInjection('Some sentence', 'Some title')
60
- component.notifyUserOfNewState([injection])
61
- await waitFor(() => getByText('Add AI links'))
37
+ expect(getByTestId('loading-bar').style.width).toBe('25%')
38
+ expect(getByText('25%')).toBeTruthy()
39
+ })
62
40
 
63
- await fireEvent.click(getByText('Add AI links'))
41
+ it('Should limit progress to minimum value in loading bar style only', () => {
42
+ const { getByText, getByTestId } = render(AIIndicator, { aiRunning: true, automationEnabled: true, percentage: 0 })
64
43
 
65
- expect(onadd).toHaveBeenCalledWith([injection])
66
- expect(container.querySelector('.ai-indicator')).not.toBeTruthy()
44
+ expect(getByTestId('loading-bar').style.width).toBe('3%')
45
+ expect(getByText('0%')).toBeTruthy()
67
46
  })
68
47
  })
@@ -61,9 +61,9 @@ describe('Title.svelte', () => {
61
61
  })
62
62
 
63
63
  it('Should truncate title when small prop is given', () => {
64
- const { container } = render(Title, { title, small: true })
64
+ const { getAllByRole } = render(Title, { title, small: true })
65
65
 
66
- expect(container.querySelector('h1.truncate')).toBeTruthy()
66
+ expect(getAllByRole('heading')[0].classList).toContain('truncate')
67
67
  })
68
68
 
69
69
  it('Should render given description', () => {
package/svelte.config.js CHANGED
@@ -8,6 +8,7 @@ const config = {
8
8
  includePaths: ['src'],
9
9
  prependData: `
10
10
  @use "src/lib/scss/_functions.scss" as *;
11
+ @use "src/lib/scss/_mixins.scss" as *;
11
12
  `,
12
13
  },
13
14
  }),