@playpilot/tpi 8.14.0 → 8.15.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 (29) hide show
  1. package/dist/editorial.mount.js +9 -9
  2. package/dist/link-injections.js +1 -1
  3. package/dist/mount.js +9 -9
  4. package/package.json +1 -1
  5. package/src/lib/api/externalPages.ts +0 -7
  6. package/src/lib/api/titles.ts +10 -0
  7. package/src/lib/data/translations.ts +5 -0
  8. package/src/lib/injection.ts +13 -3
  9. package/src/lib/routes.ts +4 -0
  10. package/src/lib/types/config.d.ts +5 -0
  11. package/src/lib/types/explore.d.ts +1 -0
  12. package/src/routes/components/Description.svelte +1 -0
  13. package/src/routes/components/Explore/ExploreRouter.svelte +38 -2
  14. package/src/routes/components/Explore/Routes/ExploreModal.svelte +38 -0
  15. package/src/routes/components/Explore/Routes/ExploreResults.svelte +12 -2
  16. package/src/routes/components/Explore/Routes/ExploreTitle.svelte +94 -0
  17. package/src/routes/components/Modals/Modal.svelte +3 -1
  18. package/src/routes/components/Modals/RailModal.svelte +4 -3
  19. package/src/routes/components/Modals/TitlesRailModal.svelte +5 -4
  20. package/src/routes/components/Playlinks/Playlinks.svelte +1 -0
  21. package/src/routes/components/Rails/TitlesRail.svelte +12 -5
  22. package/src/routes/components/Title.svelte +12 -4
  23. package/src/routes/components/Widgets/InjectionsWidgetRail.svelte +5 -1
  24. package/src/routes/explore/+page.svelte +4 -0
  25. package/src/tests/lib/api/titles.test.js +23 -1
  26. package/src/tests/lib/injection.test.js +44 -3
  27. package/src/tests/lib/routes.test.js +14 -2
  28. package/src/tests/routes/components/Explore/Routes/ExploreTitle.test.js +87 -0
  29. package/src/tests/routes/components/Rails/TitlesRail.test.js +10 -0
@@ -6,6 +6,7 @@ import { mount, unmount } from 'svelte'
6
6
  import { fakeFetch, generateInjection } from '../helpers'
7
7
  import { openModalForInjectedLink } from '$lib/modal'
8
8
  import { getLinkInjectionElements } from '$lib/injectionElements'
9
+ import { titleUrl } from '$lib/routes'
9
10
 
10
11
  vi.mock('svelte', () => ({
11
12
  mount: vi.fn(),
@@ -64,8 +65,9 @@ describe('injection.ts', () => {
64
65
 
65
66
  const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
66
67
 
68
+ // @ts-ignore
69
+ expect(link.href).toBe(titleUrl(injection.title_details))
67
70
  expect(link.innerText).toBe(injection.title)
68
- expect(link.href).toBe(injection.playpilot_url)
69
71
  })
70
72
 
71
73
  it('Should replace given words as expected when more than 1 injection per sentence is present', () => {
@@ -83,11 +85,13 @@ describe('injection.ts', () => {
83
85
 
84
86
  const links = /** @type {HTMLAnchorElement[]} */ (Array.from(document.querySelectorAll('a')))
85
87
 
88
+ // @ts-ignore
89
+ expect(links[0].href).toBe(titleUrl(linkInjections[0].title_details))
86
90
  expect(links[0].innerText).toBe(linkInjections[0].title)
87
- expect(links[0].href).toBe(linkInjections[0].playpilot_url)
88
91
 
92
+ // @ts-ignore
93
+ expect(links[1].href).toBe(titleUrl(linkInjections[1].title_details))
89
94
  expect(links[1].innerText).toBe(linkInjections[1].title)
90
- expect(links[1].href).toBe(linkInjections[1].playpilot_url)
91
95
  })
92
96
 
93
97
  it('Should ignore injections that are marked as inactive', () => {
@@ -946,6 +950,43 @@ describe('injection.ts', () => {
946
950
 
947
951
  expect(document.querySelector('a')?.closest('[data-playpilot-injection-key]')).toBeTruthy()
948
952
  })
953
+
954
+ describe('config.open_tpi_links_in_explore', () => {
955
+ beforeEach(() => {
956
+ window.PlayPilotLinkInjections.config = {
957
+ open_tpi_links_in_explore: true,
958
+ explore_navigation_path: 'https://some-path.com/explore',
959
+ }
960
+ })
961
+
962
+ it('Should use href with explore links if open_tpi_links_in_explore is true', () => {
963
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
964
+
965
+ document.body.innerHTML = `<p>${injection.sentence}</p>`
966
+
967
+ const elements = Array.from(document.querySelectorAll('p'))
968
+
969
+ injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
970
+
971
+ const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
972
+ expect(link.href).toBe(window.PlayPilotLinkInjections.config.explore_navigation_path + `?route=modal&sid=${injection.title_details?.sid}`)
973
+ expect(link.target).not.toBeTruthy()
974
+ })
975
+
976
+ it('Should not open modal when link is clicked when open_tpi_links_in_explore is true', async () => {
977
+ document.body.innerHTML = '<p>This is a sentence with an injection.</p>'
978
+
979
+ const elements = Array.from(document.body.querySelectorAll('p'))
980
+ const injection = generateInjection('This is a sentence with an injection.', 'an injection')
981
+
982
+ injectLinksInDocument(elements, { aiInjections: [injection], manualInjections: [] })
983
+
984
+ const link = /** @type {HTMLAnchorElement} */ (document.querySelector('a'))
985
+ await fireEvent.click(link)
986
+
987
+ expect(openModalForInjectedLink).not.toHaveBeenCalled()
988
+ })
989
+ })
949
990
  })
950
991
 
951
992
  describe('clearLinkInjections', () => {
@@ -1,9 +1,10 @@
1
1
  import { describe, it, expect } from 'vitest'
2
- import { titleUrl } from '$lib/routes'
2
+ import { exploreTitleUrl, titleUrl } from '$lib/routes'
3
3
  import { playPilotBaseUrl } from '$lib/constants'
4
+ import { title } from '$lib/fakeData'
4
5
 
5
6
  describe('$lib/routes', () => {
6
- describe('mergePlaylinks', () => {
7
+ describe('titleUrl', () => {
7
8
  it('Should return url for given title', () => {
8
9
  // @ts-ignore
9
10
  expect(titleUrl({ type: 'series', slug: 'some-slug' })).toBe(`${playPilotBaseUrl}/series/some-slug/`)
@@ -12,4 +13,15 @@ describe('$lib/routes', () => {
12
13
  expect(titleUrl({ type: 'movie', slug: 'some-other-slug' })).toBe(`${playPilotBaseUrl}/movie/some-other-slug/`)
13
14
  })
14
15
  })
16
+
17
+ describe('exploreTitleUrl', () => {
18
+ it('Should return url for given title', () => {
19
+ window.PlayPilotLinkInjections.config = {
20
+ open_tpi_links_in_explore: true,
21
+ explore_navigation_path: 'https://some-path.com/explore',
22
+ }
23
+
24
+ expect(exploreTitleUrl(title)).toBe(`https://some-path.com/explore?route=modal&sid=${title.sid}`)
25
+ })
26
+ })
15
27
  })
@@ -0,0 +1,87 @@
1
+ import { render, waitFor, fireEvent } from '@testing-library/svelte'
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
3
+
4
+ import TitleDetail from '../../../../../routes/components/Explore/Routes/ExploreTitle.svelte'
5
+ import { fetchTitleBySid } from '$lib/api/titles'
6
+ import { title } from '$lib/fakeData'
7
+
8
+ vi.mock('$lib/api/titles', () => ({
9
+ fetchTitleBySid: vi.fn(),
10
+ }))
11
+
12
+ vi.mock('/src/routes/components/Title.svelte', () => ({
13
+ default: vi.fn(),
14
+ }))
15
+
16
+ describe('ExploreTitle.svelte', () => {
17
+ beforeEach(() => {
18
+ vi.resetAllMocks()
19
+ vi.mocked(fetchTitleBySid).mockResolvedValue(title)
20
+
21
+ history.pushState({}, '', '/')
22
+ })
23
+
24
+ it('Should render empty state when no sid is in the URL', async () => {
25
+ const { getByText } = render(TitleDetail)
26
+
27
+ await waitFor(() => {
28
+ expect(getByText('Page not found')).toBeTruthy()
29
+ })
30
+ })
31
+
32
+ it('Should call fetchTitleBySid with sid from URL', async () => {
33
+ history.pushState({}, '', '?sid=some-sid')
34
+
35
+ render(TitleDetail)
36
+
37
+ expect(fetchTitleBySid).toHaveBeenCalledWith('some-sid')
38
+ })
39
+
40
+ it('Should render loading state while fetching', async () => {
41
+ history.pushState({}, '', '?sid=some-sid')
42
+ vi.mocked(fetchTitleBySid).mockReturnValue(new Promise(() => {}))
43
+
44
+ const { getByText } = render(TitleDetail)
45
+
46
+ expect(getByText('Loading...')).toBeTruthy()
47
+ })
48
+
49
+ it('Should render the title when fetchTitleBySid resolves', async () => {
50
+ history.pushState({}, '', '?sid=some-sid')
51
+
52
+ const { getByTestId } = render(TitleDetail)
53
+
54
+ await waitFor(() => {
55
+ expect(getByTestId('title')).toBeTruthy()
56
+ })
57
+ })
58
+
59
+ it('Should render empty state when fetchTitleBySid rejects', async () => {
60
+ history.pushState({}, '', '?sid=some-sid')
61
+ vi.mocked(fetchTitleBySid).mockRejectedValue(new Error('Not found'))
62
+
63
+ const { getByText } = render(TitleDetail)
64
+
65
+ await waitFor(() => {
66
+ expect(getByText('Page not found')).toBeTruthy()
67
+ })
68
+ })
69
+
70
+ it('Should call navigate with "home" when back button is clicked', async () => {
71
+ history.pushState({}, '', '?sid=some-sid')
72
+
73
+ const navigate = vi.fn()
74
+
75
+ const { getByText } = render(TitleDetail, { navigate })
76
+
77
+ await fireEvent.click(getByText('Home'))
78
+
79
+ expect(navigate).toHaveBeenCalledWith('home')
80
+ })
81
+
82
+ it('Should not call fetchTitleBySid when no sid is in the URL', async () => {
83
+ render(TitleDetail)
84
+
85
+ expect(fetchTitleBySid).not.toHaveBeenCalled()
86
+ })
87
+ })
@@ -213,4 +213,14 @@ describe('TitlesRail.svelte', () => {
213
213
 
214
214
  expect(container.querySelector('.titles .slider')).toBeTruthy()
215
215
  })
216
+
217
+ it('Should navigate to explore page rather than open modal when navigateToExplore is true', async () => {
218
+ const { getAllByRole } = render(TitlesRail, { titles: [title], navigateToExplore: true })
219
+
220
+ await fireEvent.click(getAllByRole('link')[0])
221
+
222
+ expect(getAllByRole('link')[0].getAttribute('href')).toContain(`?route=modal&sid=${title.sid}`)
223
+ expect(window.location.href).toContain(`?route=modal&sid=${title.sid}`)
224
+ expect(openModal).not.toHaveBeenCalledWith()
225
+ })
216
226
  })