@playpilot/tpi 5.33.0-beta.explore.6 → 5.33.0-beta.in-text.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 (50) hide show
  1. package/dist/link-injections.js +10 -10
  2. package/package.json +1 -1
  3. package/src/lib/api/ads.ts +1 -1
  4. package/src/lib/api/titles.ts +1 -13
  5. package/src/lib/color.ts +19 -0
  6. package/src/lib/data/translations.ts +0 -5
  7. package/src/lib/enums/SplitTest.ts +5 -0
  8. package/src/lib/fakeData.ts +0 -1
  9. package/src/lib/injection.ts +41 -0
  10. package/src/lib/modal.ts +6 -7
  11. package/src/lib/scss/global.scss +41 -0
  12. package/src/lib/types/config.d.ts +0 -12
  13. package/src/lib/types/title.d.ts +1 -4
  14. package/src/routes/+page.svelte +9 -8
  15. package/src/routes/components/Ads/TopScroll.svelte +18 -4
  16. package/src/routes/components/Debugger.svelte +8 -0
  17. package/src/routes/components/Icons/IconClose.svelte +1 -9
  18. package/src/routes/components/ListTitle.svelte +8 -7
  19. package/src/routes/components/Modal.svelte +24 -6
  20. package/src/routes/components/Share.svelte +23 -5
  21. package/src/routes/components/Title.svelte +22 -22
  22. package/src/routes/components/TitleModal.svelte +1 -4
  23. package/src/routes/elements/+page.svelte +2 -39
  24. package/src/tests/lib/api/ads.test.js +1 -0
  25. package/src/tests/routes/components/Share.test.js +12 -12
  26. package/src/tests/routes/components/Title.test.js +0 -13
  27. package/src/lib/explore.ts +0 -59
  28. package/src/lib/images/titles-list.webp +0 -0
  29. package/src/lib/trailer.ts +0 -22
  30. package/src/lib/types/api.d.ts +0 -6
  31. package/src/routes/components/Button.svelte +0 -73
  32. package/src/routes/components/Explore/Explore.svelte +0 -191
  33. package/src/routes/components/Explore/ExploreCallToAction.svelte +0 -58
  34. package/src/routes/components/Explore/ExploreModal.svelte +0 -15
  35. package/src/routes/components/Explore/Filter.svelte +0 -3
  36. package/src/routes/components/Explore/Search.svelte +0 -56
  37. package/src/routes/components/Icons/IconPlay.svelte +0 -3
  38. package/src/routes/components/Icons/IconSearch.svelte +0 -3
  39. package/src/routes/components/ListTitleSkeleton.svelte +0 -42
  40. package/src/routes/components/Trailer.svelte +0 -18
  41. package/src/routes/components/YouTubeEmbedOverlay.svelte +0 -96
  42. package/src/routes/explore/+page.svelte +0 -61
  43. package/src/tests/lib/api/titles.test.js +0 -55
  44. package/src/tests/lib/explore.test.js +0 -139
  45. package/src/tests/lib/trailer.test.js +0 -56
  46. package/src/tests/routes/components/Button.test.js +0 -28
  47. package/src/tests/routes/components/Explore/Explore.test.js +0 -133
  48. package/src/tests/routes/components/Explore/Search.test.js +0 -26
  49. package/src/tests/routes/components/Trailer.test.js +0 -20
  50. package/src/tests/routes/components/YouTubeEmbedOverlay.test.js +0 -31
@@ -1,15 +0,0 @@
1
-
2
- <script lang="ts">
3
- import Modal from '../Modal.svelte'
4
- import Explore from './Explore.svelte'
5
-
6
- interface Props {
7
- initialScrollPosition?: number
8
- }
9
-
10
- const { initialScrollPosition = 0 }: Props = $props()
11
- </script>
12
-
13
- <Modal {initialScrollPosition} closeButtonStyle="flat">
14
- <Explore />
15
- </Modal>
@@ -1,3 +0,0 @@
1
- <div class="filter" role="navigation">
2
- Filter
3
- </div>
@@ -1,56 +0,0 @@
1
- <script lang="ts">
2
- import IconSearch from '../Icons/IconSearch.svelte'
3
-
4
- interface Props {
5
- // eslint-disable-next-line no-unused-vars
6
- oninput: (query: string) => void
7
- }
8
-
9
- const { oninput }: Props = $props()
10
-
11
- let query = $state('')
12
- </script>
13
-
14
- <div class="search" role="search">
15
- <div class="icon">
16
- <IconSearch />
17
- </div>
18
-
19
- <input bind:value={query} oninput={() => oninput(query)} class="input" type="search" placeholder="Search movies and shows" />
20
- </div>
21
-
22
- <style lang="scss">
23
- .search {
24
- position: relative;
25
- }
26
-
27
- .icon {
28
- display: flex;
29
- align-items: center;
30
- position: absolute;
31
- height: 100%;
32
- left: margin(1);
33
- color: theme(text-color-alt);
34
- opacity: 0.75;
35
- }
36
-
37
- .input {
38
- width: 100%;
39
- padding: margin(0.75) margin(1) margin(0.75) margin(3);
40
- border: 0;
41
- border-radius: theme(border-radius);
42
- background: theme(content);
43
- color: theme(text-color-alt);
44
- font-size: theme(font-size-base);
45
- font-family: theme(font-family);
46
-
47
- &:focus {
48
- outline: 1px solid white;
49
- }
50
-
51
- &::placeholder {
52
- color: theme(text-color-alt);
53
- opacity: 0.75;
54
- }
55
- }
56
- </style>
@@ -1,3 +0,0 @@
1
- <svg width="24px" height="24px" viewBox="0 -960 960 960">
2
- <path fill="currentColor" d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>
3
- </svg>
@@ -1,3 +0,0 @@
1
- <svg width="18" height="18" viewBox="0 0 19 19">
2
- <path fill="currentColor" d="M16.593,2.407a8.155,8.155,0,0,0-11.569,0A8.166,8.166,0,0,0,4.18,12.983L.38,16.8a1.3,1.3,0,0,0,0,1.837A1.372,1.372,0,0,0,1.288,19a1.3,1.3,0,0,0,.908-.38L6.017,14.8A8.172,8.172,0,0,0,16.593,2.407ZM15.327,12.688A6.4,6.4,0,1,1,17.184,8.17,6.324,6.324,0,0,1,15.327,12.688Z" />
3
- </svg>
@@ -1,42 +0,0 @@
1
- <div class="skeleton" data-testid="skeleton">
2
- <div class="poster"></div>
3
-
4
- <div class="lines">
5
- <div class="line" style:width="40%"></div>
6
- <div class="line" style:width="60%"></div>
7
- <div class="line" style:width="80%"></div>
8
- </div>
9
- </div>
10
-
11
- <style lang="scss">
12
- .skeleton {
13
- display: flex;
14
- align-items: center;
15
- width: 100%;
16
- gap: margin(1);
17
- }
18
-
19
- .poster {
20
- flex: 0 0 auto;
21
- height: auto;
22
- align-self: start;
23
- width: margin(4.125);
24
- aspect-ratio: 2/3;
25
- border-radius: theme(detail-image-border-radius, border-radius);
26
- background: theme(content);
27
- }
28
-
29
- .lines {
30
- display: flex;
31
- flex-direction: column;
32
- gap: margin(0.5);
33
- width: 100%;
34
- }
35
-
36
- .line {
37
- width: 60%;
38
- height: theme(font-size-base);
39
- background: theme(content);
40
- border-radius: 5rem;
41
- }
42
- </style>
@@ -1,18 +0,0 @@
1
- <script lang="ts">
2
- import { t } from '$lib/localization'
3
- import { openTrailerOverlay } from '$lib/trailer'
4
- import type { TitleData } from '$lib/types/title'
5
- import Button from './Button.svelte'
6
- import IconPlay from './Icons/IconPlay.svelte'
7
-
8
- interface Props {
9
- title: TitleData
10
- }
11
-
12
- const { title }: Props = $props()
13
- </script>
14
-
15
- <Button onclick={() => openTrailerOverlay(title)}>
16
- <IconPlay />
17
- {t('Watch Trailer')}
18
- </Button>
@@ -1,96 +0,0 @@
1
- <script lang="ts">
2
- import { fade } from 'svelte/transition'
3
- import IconClose from './Icons/IconClose.svelte'
4
-
5
- interface Props {
6
- embeddable_url: string,
7
- onclose: () => void
8
- }
9
-
10
- const { embeddable_url, onclose }: Props = $props()
11
-
12
- const videoId = $derived(getVideoId(embeddable_url))
13
-
14
- // Gets the YouTube ID from a url, can be a large number of differnet formats
15
- // https://stackoverflow.com/a/54200105/1665157
16
- function getVideoId(url: string): string | null {
17
- const regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/
18
- const match = url.match(regExp)
19
-
20
- return match?.[7] || null
21
- }
22
- </script>
23
-
24
- <div class="overlay" transition:fade={{ duration: 100 }}>
25
- {#if videoId}
26
- <iframe width="600" height="338" src="https://www.youtube.com/embed/{videoId}?autoplay=true" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
27
- {:else}
28
- Something went wrong
29
- {/if}
30
-
31
- <!-- svelte-ignore a11y_click_events_have_key_events -->
32
- <!-- svelte-ignore a11y_no_static_element_interactions -->
33
- <div class="backdrop" onclick={onclose} data-testid="backdrop"></div>
34
-
35
- <button class="close" onclick={onclose} aria-label="Close">
36
- <IconClose size={24} />
37
- </button>
38
- </div>
39
-
40
- <style lang="scss">
41
- iframe {
42
- z-index: 1;
43
- position: relative;
44
- display: block;
45
- width: 95vmin;
46
- height: auto;
47
- aspect-ratio: 16/9;
48
- box-shadow: 0 0 margin(4) rgba(255, 255, 255, 0.15);
49
- background: black;
50
- }
51
-
52
- .overlay {
53
- z-index: 2147483647; // As high as she goes
54
- box-sizing: border-box;
55
- display: flex;
56
- align-items: center;
57
- justify-content: center;
58
- position: fixed;
59
- top: 0;
60
- right: 0;
61
- bottom: 0;
62
- left: 0;
63
- background: theme(detail-backdrop, rgba(0, 0, 0, 0.95));
64
- }
65
-
66
- .backdrop {
67
- z-index: 0;
68
- position: fixed;
69
- top: 0;
70
- right: 0;
71
- bottom: 0;
72
- left: 0;
73
- }
74
-
75
- .close {
76
- appearance: none;
77
- z-index: 1;
78
- position: fixed;
79
- top: margin(2);
80
- right: margin(2);
81
- padding: 0;
82
- margin: 0;
83
- border: 0;
84
- background: transparent;
85
- color: white;
86
- cursor: pointer;
87
-
88
- &:hover {
89
- transform: scale(1.1);
90
- }
91
-
92
- &:active {
93
- transform: scale(1);
94
- }
95
- }
96
- </style>
@@ -1,61 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * This is an example page for inserting the explore component into a page. The script will be loaded on this page,
4
- * but before the script is loaded some loading state needs to display. This will be supplied to the third party
5
- * implementing the tag, and will be different for each third party.
6
- */
7
-
8
- import { browser } from '$app/environment'
9
- import { insertExplore, insertExploreIntoNavigation } from '$lib/explore'
10
-
11
- if (browser) {
12
- // @ts-ignore
13
- window.PlayPilotLinkInjections = {
14
- token: 'ZoAL14yqzevMyQiwckbvyetOkeIUeEDN',
15
- config: {
16
- explore_navigation_selector: 'nav a:last-child',
17
- explore_navigation_label: 'Streaming guide',
18
- explore_navigation_path: '/explore',
19
- },
20
- }
21
- }
22
-
23
- insertExploreIntoNavigation()
24
- // Pretend there is some loading time, as there would be on a real page
25
- setTimeout(insertExplore, 1500)
26
- </script>
27
-
28
- <main>
29
- <!--
30
- This is an example of the sort of tag we'd give a partner to insert on their page.
31
- This exists soley as a loading state while the script is has not loaded.
32
- The exact styling and what not will be different per partner.
33
- -->
34
- <div data-playpilot-explore>
35
- <div style="padding: 16px 32px; min-height: 100vh; color: white">
36
- <div style="display: flex; justify-content: center; gap: 8px; margin: 16px 0; font-size: 14px;">
37
- <strong>Site Name</strong>
38
- <div style="width: 2px; height: 0.5lh; margin-top: 0.25lh; background: currentColor;"></div>
39
- Streaming Guide
40
- </div>
41
-
42
- <div role="status" aria-live="polite" style="display: flex; flex-direction: column; align-items: center; margin: 0 auto;">
43
- <svg stroke="currentColor" width="72" viewBox="0 0 24 24"><g><circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3" stroke-linecap="round"><animate attributeName="stroke-dasharray" dur="1.5s" calcMode="spline" values="0 150;42 150;42 150;42 150" keyTimes="0;0.475;0.95;1" keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1" repeatCount="indefinite"/><animate attributeName="stroke-dashoffset" dur="1.5s" calcMode="spline" values="0;-16;-59;-59" keyTimes="0;0.475;0.95;1" keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1" repeatCount="indefinite"/></circle><animateTransform attributeName="transform" type="rotate" dur="2s" values="0 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
44
- <div style="margin: 12px 0;">Loading…</div>
45
- <noscript>Sorry, this page requires JavaScript to be enabled.</noscript>
46
- </div>
47
- </div>
48
- </div>
49
- </main>
50
-
51
- <style lang="scss">
52
- @import url('$lib/scss/global.scss');
53
-
54
- main {
55
- --playpilot-font-family: "Georgia", serif;
56
- margin: margin(2) margin(-2) margin(-2);
57
- padding: 0 margin(2);
58
- background: theme(light);
59
- }
60
- </style>
61
-
@@ -1,55 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest'
2
-
3
- import { api } from '$lib/api/api'
4
- import { fetchSimilarTitles, fetchTitles } from '$lib/api/titles'
5
- import { title } from '$lib/fakeData'
6
- import { getApiToken } from '$lib/token'
7
-
8
- vi.mock('$lib/token', () => ({
9
- getApiToken: vi.fn(),
10
- }))
11
-
12
- vi.mock('$lib/api/api', () => ({
13
- api: vi.fn(),
14
- }))
15
-
16
- describe('$lib/api/ads', () => {
17
- beforeEach(() => {
18
- vi.resetAllMocks()
19
- vi.mocked(getApiToken).mockReturnValue('some-token')
20
- })
21
-
22
- describe('fetchTitles', () => {
23
- it('Should call api with given parameters and return response', async () => {
24
- vi.mocked(api).mockResolvedValueOnce({ results: [title] })
25
-
26
- const response = await fetchTitles({ some: 'thing' })
27
-
28
- expect(api).toHaveBeenCalledWith('/titles/browse?api-token=some-token&some=thing')
29
- expect(response).toEqual({ results: [title] })
30
- })
31
-
32
- it('Should throw when api returns error', async () => {
33
- vi.mocked(api).mockRejectedValueOnce({ error: 'message' })
34
-
35
- await expect(async () => await fetchTitles()).rejects.toThrow()
36
- })
37
- })
38
-
39
- describe('fetchSimilarTitles', () => {
40
- it('Should call api with with sid for given title and return array of titles', async () => {
41
- vi.mocked(api).mockResolvedValueOnce({ results: [title] })
42
-
43
- const response = await fetchSimilarTitles(title)
44
-
45
- expect(api).toHaveBeenCalledWith(`/titles/browse?api-token=some-token&related_to_sid=${title.sid}`)
46
- expect(response).toEqual([title])
47
- })
48
-
49
- it('Should throw when api returns error', async () => {
50
- vi.mocked(api).mockRejectedValueOnce({ error: 'message' })
51
-
52
- await expect(async () => await fetchSimilarTitles(title)).rejects.toThrow()
53
- })
54
- })
55
- })
@@ -1,139 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest'
2
- import { destroyExplore, insertExplore, insertExploreIntoNavigation } from '$lib/explore'
3
- import { mount, unmount } from 'svelte'
4
- vi.mock('svelte', () => ({
5
- mount: vi.fn(() => true),
6
- unmount: vi.fn(),
7
- }))
8
-
9
- describe('explore.js', () => {
10
- beforeEach(() => {
11
- destroyExplore()
12
-
13
- vi.resetAllMocks()
14
- vi.mocked(mount).mockReturnValue({})
15
- })
16
-
17
- describe('insertExplore', () => {
18
- it('Should not call mount when no target element is found', () => {
19
- insertExplore()
20
-
21
- expect(mount).not.toHaveBeenCalled()
22
- })
23
-
24
- it('Should call mount when target is found', () => {
25
- document.body.innerHTML = '<div data-playpilot-explore></div>'
26
-
27
- insertExplore()
28
-
29
- expect(mount).toHaveBeenCalled()
30
- })
31
-
32
- it('Should clear any html inside of the element before mount', () => {
33
- document.body.innerHTML = '<div data-playpilot-explore><span></span></div>'
34
-
35
- insertExplore()
36
-
37
- expect(document.querySelector('span')).not.toBeTruthy()
38
- })
39
- })
40
-
41
- describe('destroyExplore', () => {
42
- it('Should not call unmount if component was not previously mounted', () => {
43
- destroyExplore()
44
-
45
- expect(unmount).not.toHaveBeenCalled()
46
- })
47
-
48
- it('Should call unmount if component was previously mounted', () => {
49
- insertExplore()
50
- destroyExplore()
51
-
52
- expect(unmount).toHaveBeenCalled()
53
- })
54
- })
55
-
56
- describe('insertExploreIntoNavigation', () => {
57
- beforeEach(() => {
58
- document.body.innerHTML = ''
59
-
60
- // @ts-ignore
61
- window.PlayPilotLinkInjections = {}
62
- })
63
-
64
- it('Should not insert if config object is not present', () => {
65
- expect(insertExploreIntoNavigation()).toBe(false)
66
-
67
- expect(document.body.innerHTML).toBe('')
68
- })
69
-
70
- it('Should not insert if config object is present but explore_navigation_selector is not given', () => {
71
- window.PlayPilotLinkInjections.config = {
72
- explore_navigation_selector: null,
73
- }
74
-
75
- expect(insertExploreIntoNavigation()).toBe(false)
76
- })
77
-
78
- it('Should not insert if explore_navigation_selector is given but selector captures nothing', () => {
79
- document.body.innerHTML = '<nav></nav>'
80
-
81
- window.PlayPilotLinkInjections.config = {
82
- explore_navigation_selector: 'a',
83
- }
84
-
85
- expect(insertExploreIntoNavigation()).toBe(false)
86
- })
87
-
88
- it('Should insert if explore_navigation_selector is given and selector is valid', () => {
89
- document.body.innerHTML = '<nav><a></a></nav>'
90
-
91
- window.PlayPilotLinkInjections.config = {
92
- explore_navigation_selector: 'a',
93
- }
94
-
95
- expect(insertExploreIntoNavigation()).toBe(true)
96
- })
97
-
98
- it('Should copy element matching given selector with the given path', () => {
99
- document.body.innerHTML = '<nav><a></a></nav>'
100
-
101
- window.PlayPilotLinkInjections.config = {
102
- explore_navigation_selector: 'a',
103
- explore_navigation_path: '/explore',
104
- }
105
-
106
- insertExploreIntoNavigation()
107
-
108
- expect(document.body.innerHTML).toBe('<nav><a></a><a class="" href="/explore" data-playpilot-explore-navigation-element="true">Streaming Guide</a></nav>')
109
- })
110
-
111
- it('Should copy element matching given selector with text equal to explore_navigation_label', () => {
112
- document.body.innerHTML = '<nav><a></a></nav>'
113
-
114
- window.PlayPilotLinkInjections.config = {
115
- explore_navigation_selector: 'a',
116
- explore_navigation_label: 'Some label',
117
- }
118
-
119
- insertExploreIntoNavigation()
120
-
121
- const link = document.querySelector('[data-playpilot-explore-navigation-element]')
122
- // @ts-ignore
123
- expect(link.innerText).toBe('Some label')
124
- })
125
-
126
- it('Should copy element and change link inside of element if the selector was not a link', () => {
127
- document.body.innerHTML = '<ul><li><a>Link</a></li></ul>'
128
-
129
- window.PlayPilotLinkInjections.config = {
130
- explore_navigation_selector: 'li',
131
- explore_navigation_path: '/explore',
132
- }
133
-
134
- insertExploreIntoNavigation()
135
-
136
- expect(document.body.innerHTML).toBe('<ul><li><a>Link</a></li><li data-playpilot-explore-navigation-element="true"><a class="" href="/explore">Streaming Guide</a></li></ul>')
137
- })
138
- })
139
- })
@@ -1,56 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest'
2
- import { closeCurrentModal, destroyAllModals, destroyCurrentModal, getAllModals, getPreviousModal, goBackToPreviousModal, openModal } from '$lib/modal'
3
- import { linkInjections, title } from '$lib/fakeData'
4
- import { mount, unmount } from 'svelte'
5
- import ParticipantModal from '../../routes/components/ParticipantModal.svelte'
6
- import TitleModal from '../../routes/components/TitleModal.svelte'
7
- import { closeTrailerOverlay, openTrailerOverlay } from '$lib/trailer'
8
-
9
- vi.mock('svelte', () => ({
10
- mount: vi.fn(),
11
- unmount: vi.fn(),
12
- }))
13
-
14
- const titleWithTrailer = { ...title, embeddable_url: 'abc' }
15
-
16
- describe('modal.js', () => {
17
- beforeEach(() => {
18
- vi.resetAllMocks()
19
- })
20
-
21
- describe('openTrailerOverlay', () => {
22
- it('Should call mount with given title embeddable_url', () => {
23
- openTrailerOverlay(titleWithTrailer)
24
-
25
- expect(mount).toHaveBeenCalledWith(
26
- expect.any(Function),
27
- expect.objectContaining({
28
- target: expect.anything(),
29
- props: expect.objectContaining({
30
- onclose: expect.any(Function),
31
- embeddable_url: titleWithTrailer.embeddable_url,
32
- }),
33
- }),
34
- )
35
- })
36
- })
37
-
38
- describe('closeTrailerOverlay', () => {
39
- it('Should call unmount if component was previously mounted', () => {
40
- vi.mocked(mount).mockReturnValueOnce({})
41
-
42
- openTrailerOverlay(titleWithTrailer)
43
- closeTrailerOverlay()
44
-
45
- expect(unmount).toHaveBeenCalled()
46
- })
47
-
48
- it('Should not call unmount if component was not previously mounted', () => {
49
- vi.mocked(mount).mockReturnValueOnce({})
50
-
51
- closeTrailerOverlay()
52
-
53
- expect(unmount).not.toHaveBeenCalled()
54
- })
55
- })
56
- })
@@ -1,28 +0,0 @@
1
- import { render, fireEvent } from '@testing-library/svelte'
2
- import { describe, expect, it, vi } from 'vitest'
3
-
4
- import Button from '../../../routes/components/Button.svelte'
5
-
6
- describe('Button.svelte', () => {
7
- it('Should use filled class by default', () => {
8
- const { getByRole } = render(Button)
9
-
10
- expect(getByRole('button').classList).toContain('filled')
11
- })
12
-
13
- it('Should use border class when border variant is given', () => {
14
- const { getByRole } = render(Button, { variant: 'border' })
15
-
16
- expect(getByRole('button').classList).not.toContain('filled')
17
- expect(getByRole('button').classList).toContain('border')
18
- })
19
-
20
- it('Should fire given onclick function on click', async () => {
21
- const onclick = vi.fn()
22
- const { getByRole } = render(Button, { onclick })
23
-
24
- await fireEvent.click(getByRole('button'))
25
-
26
- expect(onclick).toHaveBeenCalled()
27
- })
28
- })