@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.
- package/dist/link-injections.js +8 -8
- package/package.json +1 -1
- package/src/lib/actions/heading.ts +11 -0
- package/src/lib/linkInjection.ts +2 -1
- package/src/lib/scss/_mixins.scss +8 -0
- package/src/lib/types/injection.d.ts +2 -0
- package/src/routes/+page.svelte +20 -13
- package/src/routes/components/Description.svelte +2 -3
- package/src/routes/components/Editorial/AIIndicator.svelte +80 -94
- package/src/routes/components/Editorial/Editor.svelte +40 -46
- package/src/routes/components/Editorial/ManualInjection.svelte +10 -9
- package/src/routes/components/Editorial/Search/TitleSearchItem.svelte +1 -1
- package/src/routes/components/Modal.svelte +2 -0
- package/src/routes/components/Playlinks.svelte +12 -11
- package/src/routes/components/Popover.svelte +2 -0
- package/src/routes/components/Title.svelte +3 -2
- package/src/tests/lib/linkInjection.test.js +13 -5
- package/src/tests/routes/+page.test.js +73 -0
- package/src/tests/routes/components/Editorial/AiIndicator.test.js +21 -42
- package/src/tests/routes/components/Title.test.js +2 -2
- package/svelte.config.js +1 -0
|
@@ -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
|
-
<
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
2
|
-
import { describe, expect, it
|
|
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
|
|
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
|
|
16
|
-
const { getByText, getByTestId } = render(AIIndicator, {
|
|
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
|
|
23
|
-
const {
|
|
21
|
+
it('Should not show animator or loading bar if aiRunning is false', () => {
|
|
22
|
+
const { queryByTestId } = render(AIIndicator, { aiRunning: false })
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
46
|
-
const { getByText
|
|
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
|
-
|
|
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
|
|
56
|
-
const
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
expect(getByTestId('loading-bar').style.width).toBe('25%')
|
|
38
|
+
expect(getByText('25%')).toBeTruthy()
|
|
39
|
+
})
|
|
62
40
|
|
|
63
|
-
|
|
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(
|
|
66
|
-
expect(
|
|
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 {
|
|
64
|
+
const { getAllByRole } = render(Title, { title, small: true })
|
|
65
65
|
|
|
66
|
-
expect(
|
|
66
|
+
expect(getAllByRole('heading')[0].classList).toContain('truncate')
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
it('Should render given description', () => {
|