@furystack/shades-common-components 10.0.35 → 11.0.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/CHANGELOG.md +66 -0
- package/esm/components/animations.spec.d.ts +2 -0
- package/esm/components/animations.spec.d.ts.map +1 -0
- package/esm/components/animations.spec.js +201 -0
- package/esm/components/animations.spec.js.map +1 -0
- package/esm/components/app-bar-link.js +21 -20
- package/esm/components/app-bar-link.js.map +1 -1
- package/esm/components/app-bar-link.spec.d.ts +2 -0
- package/esm/components/app-bar-link.spec.d.ts.map +1 -0
- package/esm/components/app-bar-link.spec.js +252 -0
- package/esm/components/app-bar-link.spec.js.map +1 -0
- package/esm/components/app-bar.js +21 -21
- package/esm/components/app-bar.js.map +1 -1
- package/esm/components/app-bar.spec.d.ts +2 -0
- package/esm/components/app-bar.spec.d.ts.map +1 -0
- package/esm/components/app-bar.spec.js +117 -0
- package/esm/components/app-bar.spec.js.map +1 -0
- package/esm/components/avatar.d.ts.map +1 -1
- package/esm/components/avatar.js +15 -19
- package/esm/components/avatar.js.map +1 -1
- package/esm/components/avatar.spec.d.ts +2 -0
- package/esm/components/avatar.spec.d.ts.map +1 -0
- package/esm/components/avatar.spec.js +114 -0
- package/esm/components/avatar.spec.js.map +1 -0
- package/esm/components/button.d.ts.map +1 -1
- package/esm/components/button.js +145 -156
- package/esm/components/button.js.map +1 -1
- package/esm/components/button.spec.d.ts +2 -0
- package/esm/components/button.spec.d.ts.map +1 -0
- package/esm/components/button.spec.js +155 -0
- package/esm/components/button.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-input.js +18 -16
- package/esm/components/command-palette/command-palette-input.js.map +1 -1
- package/esm/components/command-palette/command-palette-input.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-input.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-input.spec.js +233 -0
- package/esm/components/command-palette/command-palette-input.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.js +362 -0
- package/esm/components/command-palette/command-palette-manager.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.js +42 -46
- package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js +376 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -0
- package/esm/components/command-palette/index.d.ts.map +1 -1
- package/esm/components/command-palette/index.js +100 -110
- package/esm/components/command-palette/index.js.map +1 -1
- package/esm/components/command-palette/index.spec.d.ts +2 -0
- package/esm/components/command-palette/index.spec.d.ts.map +1 -0
- package/esm/components/command-palette/index.spec.js +509 -0
- package/esm/components/command-palette/index.spec.js.map +1 -0
- package/esm/components/data-grid/body.js +1 -1
- package/esm/components/data-grid/body.js.map +1 -1
- package/esm/components/data-grid/body.spec.d.ts +2 -0
- package/esm/components/data-grid/body.spec.d.ts.map +1 -0
- package/esm/components/data-grid/body.spec.js +228 -0
- package/esm/components/data-grid/body.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid-row.js +49 -73
- package/esm/components/data-grid/data-grid-row.js.map +1 -1
- package/esm/components/data-grid/data-grid-row.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid-row.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid-row.spec.js +296 -0
- package/esm/components/data-grid/data-grid-row.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid.js +35 -28
- package/esm/components/data-grid/data-grid.js.map +1 -1
- package/esm/components/data-grid/data-grid.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid.spec.js +544 -0
- package/esm/components/data-grid/data-grid.spec.js.map +1 -0
- package/esm/components/data-grid/footer.js +21 -15
- package/esm/components/data-grid/footer.js.map +1 -1
- package/esm/components/data-grid/footer.spec.d.ts +2 -0
- package/esm/components/data-grid/footer.spec.d.ts.map +1 -0
- package/esm/components/data-grid/footer.spec.js +264 -0
- package/esm/components/data-grid/footer.spec.js.map +1 -0
- package/esm/components/data-grid/header.d.ts.map +1 -1
- package/esm/components/data-grid/header.js +55 -33
- package/esm/components/data-grid/header.js.map +1 -1
- package/esm/components/data-grid/header.spec.d.ts +2 -0
- package/esm/components/data-grid/header.spec.d.ts.map +1 -0
- package/esm/components/data-grid/header.spec.js +421 -0
- package/esm/components/data-grid/header.spec.js.map +1 -0
- package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
- package/esm/components/data-grid/selection-cell.js +13 -6
- package/esm/components/data-grid/selection-cell.js.map +1 -1
- package/esm/components/data-grid/selection-cell.spec.d.ts +2 -0
- package/esm/components/data-grid/selection-cell.spec.d.ts.map +1 -0
- package/esm/components/data-grid/selection-cell.spec.js +118 -0
- package/esm/components/data-grid/selection-cell.spec.js.map +1 -0
- package/esm/components/fab.d.ts.map +1 -1
- package/esm/components/fab.js +10 -1
- package/esm/components/fab.js.map +1 -1
- package/esm/components/fab.spec.d.ts +2 -0
- package/esm/components/fab.spec.d.ts.map +1 -0
- package/esm/components/fab.spec.js +95 -0
- package/esm/components/fab.spec.js.map +1 -0
- package/esm/components/form.spec.d.ts +2 -0
- package/esm/components/form.spec.d.ts.map +1 -0
- package/esm/components/form.spec.js +314 -0
- package/esm/components/form.spec.js.map +1 -0
- package/esm/components/grid.d.ts.map +1 -1
- package/esm/components/grid.js +40 -37
- package/esm/components/grid.js.map +1 -1
- package/esm/components/grid.spec.d.ts +2 -0
- package/esm/components/grid.spec.d.ts.map +1 -0
- package/esm/components/grid.spec.js +316 -0
- package/esm/components/grid.spec.js.map +1 -0
- package/esm/components/inputs/autocomplete.spec.d.ts +2 -0
- package/esm/components/inputs/autocomplete.spec.d.ts.map +1 -0
- package/esm/components/inputs/autocomplete.spec.js +194 -0
- package/esm/components/inputs/autocomplete.spec.js.map +1 -0
- package/esm/components/inputs/input.d.ts.map +1 -1
- package/esm/components/inputs/input.js +141 -109
- package/esm/components/inputs/input.js.map +1 -1
- package/esm/components/inputs/input.spec.d.ts +2 -0
- package/esm/components/inputs/input.spec.d.ts.map +1 -0
- package/esm/components/inputs/input.spec.js +577 -0
- package/esm/components/inputs/input.spec.js.map +1 -0
- package/esm/components/inputs/text-area.d.ts.map +1 -1
- package/esm/components/inputs/text-area.js +54 -58
- package/esm/components/inputs/text-area.js.map +1 -1
- package/esm/components/inputs/text-area.spec.d.ts +2 -0
- package/esm/components/inputs/text-area.spec.d.ts.map +1 -0
- package/esm/components/inputs/text-area.spec.js +214 -0
- package/esm/components/inputs/text-area.spec.js.map +1 -0
- package/esm/components/loader.js +1 -1
- package/esm/components/loader.js.map +1 -1
- package/esm/components/loader.spec.d.ts +2 -0
- package/esm/components/loader.spec.d.ts.map +1 -0
- package/esm/components/loader.spec.js +251 -0
- package/esm/components/loader.spec.js.map +1 -0
- package/esm/components/modal.d.ts.map +1 -1
- package/esm/components/modal.js +11 -9
- package/esm/components/modal.js.map +1 -1
- package/esm/components/modal.spec.d.ts +2 -0
- package/esm/components/modal.spec.d.ts.map +1 -0
- package/esm/components/modal.spec.js +227 -0
- package/esm/components/modal.spec.js.map +1 -0
- package/esm/components/noty-list.d.ts.map +1 -1
- package/esm/components/noty-list.js +39 -40
- package/esm/components/noty-list.js.map +1 -1
- package/esm/components/noty-list.spec.d.ts +2 -0
- package/esm/components/noty-list.spec.d.ts.map +1 -0
- package/esm/components/noty-list.spec.js +486 -0
- package/esm/components/noty-list.spec.js.map +1 -0
- package/esm/components/paper.d.ts.map +1 -1
- package/esm/components/paper.js +15 -12
- package/esm/components/paper.js.map +1 -1
- package/esm/components/paper.spec.d.ts +2 -0
- package/esm/components/paper.spec.d.ts.map +1 -0
- package/esm/components/paper.spec.js +63 -0
- package/esm/components/paper.spec.js.map +1 -0
- package/esm/components/skeleton.js +1 -1
- package/esm/components/skeleton.js.map +1 -1
- package/esm/components/skeleton.spec.d.ts +2 -0
- package/esm/components/skeleton.spec.d.ts.map +1 -0
- package/esm/components/skeleton.spec.js +159 -0
- package/esm/components/skeleton.spec.js.map +1 -0
- package/esm/components/styles.spec.d.ts +2 -0
- package/esm/components/styles.spec.d.ts.map +1 -0
- package/esm/components/styles.spec.js +56 -0
- package/esm/components/styles.spec.js.map +1 -0
- package/esm/components/suggest/index.d.ts.map +1 -1
- package/esm/components/suggest/index.js +74 -83
- package/esm/components/suggest/index.js.map +1 -1
- package/esm/components/suggest/index.spec.d.ts +2 -0
- package/esm/components/suggest/index.spec.d.ts.map +1 -0
- package/esm/components/suggest/index.spec.js +515 -0
- package/esm/components/suggest/index.spec.js.map +1 -0
- package/esm/components/suggest/suggest-input.d.ts.map +1 -1
- package/esm/components/suggest/suggest-input.js +16 -17
- package/esm/components/suggest/suggest-input.js.map +1 -1
- package/esm/components/suggest/suggest-input.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-input.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-input.spec.js +138 -0
- package/esm/components/suggest/suggest-input.spec.js.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.js +308 -0
- package/esm/components/suggest/suggest-manager.spec.js.map +1 -0
- package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
- package/esm/components/suggest/suggestion-list.js +43 -48
- package/esm/components/suggest/suggestion-list.js.map +1 -1
- package/esm/components/suggest/suggestion-list.spec.d.ts +2 -0
- package/esm/components/suggest/suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggestion-list.spec.js +252 -0
- package/esm/components/suggest/suggestion-list.spec.js.map +1 -0
- package/esm/components/tabs.d.ts.map +1 -1
- package/esm/components/tabs.js +32 -18
- package/esm/components/tabs.js.map +1 -1
- package/esm/components/tabs.spec.d.ts +2 -0
- package/esm/components/tabs.spec.d.ts.map +1 -0
- package/esm/components/tabs.spec.js +187 -0
- package/esm/components/tabs.spec.js.map +1 -0
- package/esm/components/wizard/index.d.ts.map +1 -1
- package/esm/components/wizard/index.js +10 -7
- package/esm/components/wizard/index.js.map +1 -1
- package/esm/components/wizard/index.spec.d.ts +2 -0
- package/esm/components/wizard/index.spec.d.ts.map +1 -0
- package/esm/components/wizard/index.spec.js +171 -0
- package/esm/components/wizard/index.spec.js.map +1 -0
- package/esm/services/collection-service.spec.js +391 -2
- package/esm/services/collection-service.spec.js.map +1 -1
- package/esm/services/css-variable-theme.d.ts.map +1 -1
- package/esm/services/css-variable-theme.js +21 -1
- package/esm/services/css-variable-theme.js.map +1 -1
- package/esm/services/css-variable-theme.spec.d.ts +2 -0
- package/esm/services/css-variable-theme.spec.d.ts.map +1 -0
- package/esm/services/css-variable-theme.spec.js +169 -0
- package/esm/services/css-variable-theme.spec.js.map +1 -0
- package/esm/services/default-palette.d.ts +4 -0
- package/esm/services/default-palette.d.ts.map +1 -1
- package/esm/services/default-palette.js +22 -0
- package/esm/services/default-palette.js.map +1 -1
- package/esm/services/theme-provider-service.d.ts +59 -1
- package/esm/services/theme-provider-service.d.ts.map +1 -1
- package/esm/services/theme-provider-service.js.map +1 -1
- package/esm/services/theme-provider-service.spec.d.ts +2 -0
- package/esm/services/theme-provider-service.spec.d.ts.map +1 -0
- package/esm/services/theme-provider-service.spec.js +166 -0
- package/esm/services/theme-provider-service.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/components/animations.spec.ts +299 -0
- package/src/components/app-bar-link.spec.tsx +341 -0
- package/src/components/app-bar-link.tsx +21 -21
- package/src/components/app-bar.spec.tsx +142 -0
- package/src/components/app-bar.tsx +22 -22
- package/src/components/avatar.spec.tsx +146 -0
- package/src/components/avatar.tsx +17 -20
- package/src/components/button.spec.tsx +193 -0
- package/src/components/button.tsx +162 -197
- package/src/components/command-palette/command-palette-input.spec.tsx +320 -0
- package/src/components/command-palette/command-palette-input.tsx +19 -22
- package/src/components/command-palette/command-palette-manager.spec.ts +470 -0
- package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +499 -0
- package/src/components/command-palette/command-palette-suggestion-list.tsx +42 -46
- package/src/components/command-palette/index.spec.tsx +684 -0
- package/src/components/command-palette/index.tsx +107 -136
- package/src/components/data-grid/body.spec.tsx +340 -0
- package/src/components/data-grid/body.tsx +1 -1
- package/src/components/data-grid/data-grid-row.spec.tsx +382 -0
- package/src/components/data-grid/data-grid-row.tsx +50 -82
- package/src/components/data-grid/data-grid.spec.tsx +939 -0
- package/src/components/data-grid/data-grid.tsx +38 -35
- package/src/components/data-grid/footer.spec.tsx +344 -0
- package/src/components/data-grid/footer.tsx +19 -19
- package/src/components/data-grid/header.spec.tsx +563 -0
- package/src/components/data-grid/header.tsx +53 -44
- package/src/components/data-grid/selection-cell.spec.tsx +150 -0
- package/src/components/data-grid/selection-cell.tsx +12 -6
- package/src/components/fab.spec.tsx +108 -0
- package/src/components/fab.tsx +10 -1
- package/src/components/form.spec.tsx +481 -0
- package/src/components/grid.spec.tsx +334 -0
- package/src/components/grid.tsx +57 -63
- package/src/components/inputs/autocomplete.spec.tsx +258 -0
- package/src/components/inputs/input.spec.tsx +808 -0
- package/src/components/inputs/input.tsx +153 -139
- package/src/components/inputs/text-area.spec.tsx +285 -0
- package/src/components/inputs/text-area.tsx +53 -79
- package/src/components/loader.spec.tsx +346 -0
- package/src/components/loader.tsx +1 -1
- package/src/components/modal.spec.tsx +304 -0
- package/src/components/modal.tsx +11 -9
- package/src/components/noty-list.spec.tsx +631 -0
- package/src/components/noty-list.tsx +39 -50
- package/src/components/paper.spec.tsx +72 -0
- package/src/components/paper.tsx +15 -13
- package/src/components/skeleton.spec.tsx +219 -0
- package/src/components/skeleton.tsx +1 -1
- package/src/components/styles.spec.ts +70 -0
- package/src/components/suggest/index.spec.tsx +861 -0
- package/src/components/suggest/index.tsx +74 -101
- package/src/components/suggest/suggest-input.spec.tsx +181 -0
- package/src/components/suggest/suggest-input.tsx +16 -24
- package/src/components/suggest/suggest-manager.spec.ts +409 -0
- package/src/components/suggest/suggestion-list.spec.tsx +334 -0
- package/src/components/suggest/suggestion-list.tsx +43 -48
- package/src/components/tabs.spec.tsx +236 -0
- package/src/components/tabs.tsx +33 -21
- package/src/components/wizard/index.spec.tsx +224 -0
- package/src/components/wizard/index.tsx +10 -9
- package/src/services/collection-service.spec.ts +492 -3
- package/src/services/css-variable-theme.spec.ts +204 -0
- package/src/services/css-variable-theme.ts +21 -1
- package/src/services/default-palette.ts +22 -0
- package/src/services/theme-provider-service.spec.ts +195 -0
- package/src/services/theme-provider-service.ts +60 -2
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
import { Injector } from '@furystack/inject'
|
|
2
|
+
import { createComponent, initializeShadeRoot } from '@furystack/shades'
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
|
+
import { Suggest } from './index.js'
|
|
5
|
+
import type { SuggestionResult } from './suggestion-result.js'
|
|
6
|
+
|
|
7
|
+
type TestEntry = { id: number; name: string }
|
|
8
|
+
|
|
9
|
+
describe('Suggest', () => {
|
|
10
|
+
let originalAnimate: typeof Element.prototype.animate
|
|
11
|
+
let animateCalls: Array<{ keyframes: unknown; options: unknown }>
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.useFakeTimers()
|
|
15
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
16
|
+
animateCalls = []
|
|
17
|
+
originalAnimate = Element.prototype.animate
|
|
18
|
+
|
|
19
|
+
Element.prototype.animate = vi.fn(
|
|
20
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
21
|
+
animateCalls.push({ keyframes, options })
|
|
22
|
+
const mockAnimation = {
|
|
23
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
24
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
25
|
+
cancel: vi.fn(),
|
|
26
|
+
play: vi.fn(),
|
|
27
|
+
pause: vi.fn(),
|
|
28
|
+
finish: vi.fn(),
|
|
29
|
+
addEventListener: vi.fn(),
|
|
30
|
+
removeEventListener: vi.fn(),
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return mockAnimation as unknown as Animation
|
|
34
|
+
},
|
|
35
|
+
) as typeof Element.prototype.animate
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
afterEach(async () => {
|
|
39
|
+
await vi.runAllTimersAsync()
|
|
40
|
+
const suggest = document.querySelector('shade-suggest')
|
|
41
|
+
suggest?.remove()
|
|
42
|
+
document.body.innerHTML = ''
|
|
43
|
+
Element.prototype.animate = originalAnimate
|
|
44
|
+
vi.useRealTimers()
|
|
45
|
+
vi.restoreAllMocks()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const advanceTimers = async (ms: number) => {
|
|
49
|
+
await vi.advanceTimersByTimeAsync(ms)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const createTestEntries = (): TestEntry[] => [
|
|
53
|
+
{ id: 1, name: 'First' },
|
|
54
|
+
{ id: 2, name: 'Second' },
|
|
55
|
+
{ id: 3, name: 'Third' },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
const getTestEntries = async (term: string): Promise<TestEntry[]> => {
|
|
59
|
+
const entries = createTestEntries()
|
|
60
|
+
if (!term) return entries
|
|
61
|
+
return entries.filter((e) => e.name.toLowerCase().includes(term.toLowerCase()))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const getSuggestionEntry = (entry: TestEntry): SuggestionResult => ({
|
|
65
|
+
element: <span data-testid={`suggestion-${entry.id}`}>{entry.name}</span>,
|
|
66
|
+
score: entry.id,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('rendering', () => {
|
|
70
|
+
it('should render with shadow DOM', async () => {
|
|
71
|
+
const injector = new Injector()
|
|
72
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
73
|
+
const onSelectSuggestion = vi.fn()
|
|
74
|
+
|
|
75
|
+
initializeShadeRoot({
|
|
76
|
+
injector,
|
|
77
|
+
rootElement,
|
|
78
|
+
jsxElement: (
|
|
79
|
+
<Suggest<TestEntry>
|
|
80
|
+
defaultPrefix="🔍"
|
|
81
|
+
getEntries={getTestEntries}
|
|
82
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
83
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
84
|
+
/>
|
|
85
|
+
),
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
await advanceTimers(50)
|
|
89
|
+
|
|
90
|
+
const suggest = document.querySelector('shade-suggest')
|
|
91
|
+
expect(suggest).not.toBeNull()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should render the default prefix', async () => {
|
|
95
|
+
const injector = new Injector()
|
|
96
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
97
|
+
const onSelectSuggestion = vi.fn()
|
|
98
|
+
|
|
99
|
+
initializeShadeRoot({
|
|
100
|
+
injector,
|
|
101
|
+
rootElement,
|
|
102
|
+
jsxElement: (
|
|
103
|
+
<Suggest<TestEntry>
|
|
104
|
+
defaultPrefix="Search:"
|
|
105
|
+
getEntries={getTestEntries}
|
|
106
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
107
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
108
|
+
/>
|
|
109
|
+
),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
await advanceTimers(50)
|
|
113
|
+
|
|
114
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
115
|
+
const termIcon = suggest?.querySelector('.term-icon')
|
|
116
|
+
expect(termIcon?.textContent).toBe('Search:')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('should render the input container', async () => {
|
|
120
|
+
const injector = new Injector()
|
|
121
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
122
|
+
const onSelectSuggestion = vi.fn()
|
|
123
|
+
|
|
124
|
+
initializeShadeRoot({
|
|
125
|
+
injector,
|
|
126
|
+
rootElement,
|
|
127
|
+
jsxElement: (
|
|
128
|
+
<Suggest<TestEntry>
|
|
129
|
+
defaultPrefix="🔍"
|
|
130
|
+
getEntries={getTestEntries}
|
|
131
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
132
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
133
|
+
/>
|
|
134
|
+
),
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
await advanceTimers(50)
|
|
138
|
+
|
|
139
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
140
|
+
const inputContainer = suggest?.querySelector('.input-container')
|
|
141
|
+
expect(inputContainer).not.toBeNull()
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('should apply custom styles', async () => {
|
|
145
|
+
const injector = new Injector()
|
|
146
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
147
|
+
const onSelectSuggestion = vi.fn()
|
|
148
|
+
|
|
149
|
+
initializeShadeRoot({
|
|
150
|
+
injector,
|
|
151
|
+
rootElement,
|
|
152
|
+
jsxElement: (
|
|
153
|
+
<Suggest<TestEntry>
|
|
154
|
+
defaultPrefix="🔍"
|
|
155
|
+
getEntries={getTestEntries}
|
|
156
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
157
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
158
|
+
style={{ backgroundColor: 'red' }}
|
|
159
|
+
/>
|
|
160
|
+
),
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
await advanceTimers(50)
|
|
164
|
+
|
|
165
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
166
|
+
const inputContainer = suggest?.querySelector('.input-container') as HTMLElement
|
|
167
|
+
expect(inputContainer?.style.backgroundColor).toBe('red')
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
describe('keyboard navigation', () => {
|
|
172
|
+
it('should handle ArrowDown to move selection down', async () => {
|
|
173
|
+
const injector = new Injector()
|
|
174
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
175
|
+
const onSelectSuggestion = vi.fn()
|
|
176
|
+
|
|
177
|
+
initializeShadeRoot({
|
|
178
|
+
injector,
|
|
179
|
+
rootElement,
|
|
180
|
+
jsxElement: (
|
|
181
|
+
<Suggest<TestEntry>
|
|
182
|
+
defaultPrefix="🔍"
|
|
183
|
+
getEntries={getTestEntries}
|
|
184
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
185
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
186
|
+
/>
|
|
187
|
+
),
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
await advanceTimers(50)
|
|
191
|
+
|
|
192
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
193
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
194
|
+
|
|
195
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
196
|
+
input.value = 'test'
|
|
197
|
+
|
|
198
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
199
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
200
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
201
|
+
|
|
202
|
+
await advanceTimers(300)
|
|
203
|
+
|
|
204
|
+
const arrowDownEvent = new KeyboardEvent('keyup', { key: 'ArrowDown', bubbles: true })
|
|
205
|
+
Object.defineProperty(arrowDownEvent, 'target', { value: input })
|
|
206
|
+
wrapper?.dispatchEvent(arrowDownEvent)
|
|
207
|
+
|
|
208
|
+
await advanceTimers(50)
|
|
209
|
+
|
|
210
|
+
const selectedItems = suggest?.querySelectorAll('.suggestion-item.selected')
|
|
211
|
+
expect(selectedItems?.length).toBeGreaterThanOrEqual(0)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('should handle ArrowUp to move selection up', async () => {
|
|
215
|
+
const injector = new Injector()
|
|
216
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
217
|
+
const onSelectSuggestion = vi.fn()
|
|
218
|
+
|
|
219
|
+
initializeShadeRoot({
|
|
220
|
+
injector,
|
|
221
|
+
rootElement,
|
|
222
|
+
jsxElement: (
|
|
223
|
+
<Suggest<TestEntry>
|
|
224
|
+
defaultPrefix="🔍"
|
|
225
|
+
getEntries={getTestEntries}
|
|
226
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
227
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
228
|
+
/>
|
|
229
|
+
),
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
await advanceTimers(50)
|
|
233
|
+
|
|
234
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
235
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
236
|
+
|
|
237
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
238
|
+
input.value = 'test'
|
|
239
|
+
|
|
240
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
241
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
242
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
243
|
+
|
|
244
|
+
await advanceTimers(300)
|
|
245
|
+
|
|
246
|
+
const arrowDownEvent = new KeyboardEvent('keyup', { key: 'ArrowDown', bubbles: true })
|
|
247
|
+
Object.defineProperty(arrowDownEvent, 'target', { value: input })
|
|
248
|
+
wrapper?.dispatchEvent(arrowDownEvent)
|
|
249
|
+
wrapper?.dispatchEvent(arrowDownEvent)
|
|
250
|
+
|
|
251
|
+
const arrowUpEvent = new KeyboardEvent('keyup', { key: 'ArrowUp', bubbles: true })
|
|
252
|
+
Object.defineProperty(arrowUpEvent, 'target', { value: input })
|
|
253
|
+
wrapper?.dispatchEvent(arrowUpEvent)
|
|
254
|
+
|
|
255
|
+
await advanceTimers(50)
|
|
256
|
+
|
|
257
|
+
expect(suggest).not.toBeNull()
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('should handle Enter to select current suggestion', async () => {
|
|
261
|
+
const injector = new Injector()
|
|
262
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
263
|
+
const onSelectSuggestion = vi.fn()
|
|
264
|
+
|
|
265
|
+
initializeShadeRoot({
|
|
266
|
+
injector,
|
|
267
|
+
rootElement,
|
|
268
|
+
jsxElement: (
|
|
269
|
+
<Suggest<TestEntry>
|
|
270
|
+
defaultPrefix="🔍"
|
|
271
|
+
getEntries={getTestEntries}
|
|
272
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
273
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
274
|
+
/>
|
|
275
|
+
),
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
await advanceTimers(50)
|
|
279
|
+
|
|
280
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
281
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
282
|
+
|
|
283
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
284
|
+
input.value = 'First'
|
|
285
|
+
|
|
286
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
287
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
288
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
289
|
+
|
|
290
|
+
await advanceTimers(300)
|
|
291
|
+
|
|
292
|
+
const enterEvent = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true })
|
|
293
|
+
Object.defineProperty(enterEvent, 'target', { value: input })
|
|
294
|
+
wrapper?.dispatchEvent(enterEvent)
|
|
295
|
+
|
|
296
|
+
await advanceTimers(50)
|
|
297
|
+
|
|
298
|
+
expect(onSelectSuggestion).toHaveBeenCalled()
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('should prevent default on Enter key', async () => {
|
|
302
|
+
const injector = new Injector()
|
|
303
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
304
|
+
const onSelectSuggestion = vi.fn()
|
|
305
|
+
|
|
306
|
+
initializeShadeRoot({
|
|
307
|
+
injector,
|
|
308
|
+
rootElement,
|
|
309
|
+
jsxElement: (
|
|
310
|
+
<Suggest<TestEntry>
|
|
311
|
+
defaultPrefix="🔍"
|
|
312
|
+
getEntries={getTestEntries}
|
|
313
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
314
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
315
|
+
/>
|
|
316
|
+
),
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
await advanceTimers(50)
|
|
320
|
+
|
|
321
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
322
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
323
|
+
|
|
324
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
325
|
+
input.value = 'First'
|
|
326
|
+
|
|
327
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
328
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
329
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
330
|
+
|
|
331
|
+
await advanceTimers(300)
|
|
332
|
+
|
|
333
|
+
const enterEvent = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true, cancelable: true })
|
|
334
|
+
Object.defineProperty(enterEvent, 'target', { value: input })
|
|
335
|
+
|
|
336
|
+
const preventDefaultSpy = vi.spyOn(enterEvent, 'preventDefault')
|
|
337
|
+
wrapper?.dispatchEvent(enterEvent)
|
|
338
|
+
|
|
339
|
+
expect(preventDefaultSpy).toHaveBeenCalled()
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('should prevent default on ArrowUp key', async () => {
|
|
343
|
+
const injector = new Injector()
|
|
344
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
345
|
+
const onSelectSuggestion = vi.fn()
|
|
346
|
+
|
|
347
|
+
initializeShadeRoot({
|
|
348
|
+
injector,
|
|
349
|
+
rootElement,
|
|
350
|
+
jsxElement: (
|
|
351
|
+
<Suggest<TestEntry>
|
|
352
|
+
defaultPrefix="🔍"
|
|
353
|
+
getEntries={getTestEntries}
|
|
354
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
355
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
356
|
+
/>
|
|
357
|
+
),
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
await advanceTimers(50)
|
|
361
|
+
|
|
362
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
363
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
364
|
+
|
|
365
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
366
|
+
|
|
367
|
+
const arrowUpEvent = new KeyboardEvent('keyup', { key: 'ArrowUp', bubbles: true, cancelable: true })
|
|
368
|
+
Object.defineProperty(arrowUpEvent, 'target', { value: input })
|
|
369
|
+
|
|
370
|
+
const preventDefaultSpy = vi.spyOn(arrowUpEvent, 'preventDefault')
|
|
371
|
+
wrapper?.dispatchEvent(arrowUpEvent)
|
|
372
|
+
|
|
373
|
+
expect(preventDefaultSpy).toHaveBeenCalled()
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
it('should prevent default on ArrowDown key', async () => {
|
|
377
|
+
const injector = new Injector()
|
|
378
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
379
|
+
const onSelectSuggestion = vi.fn()
|
|
380
|
+
|
|
381
|
+
initializeShadeRoot({
|
|
382
|
+
injector,
|
|
383
|
+
rootElement,
|
|
384
|
+
jsxElement: (
|
|
385
|
+
<Suggest<TestEntry>
|
|
386
|
+
defaultPrefix="🔍"
|
|
387
|
+
getEntries={getTestEntries}
|
|
388
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
389
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
390
|
+
/>
|
|
391
|
+
),
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
await advanceTimers(50)
|
|
395
|
+
|
|
396
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
397
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
398
|
+
|
|
399
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
400
|
+
|
|
401
|
+
const arrowDownEvent = new KeyboardEvent('keyup', { key: 'ArrowDown', bubbles: true, cancelable: true })
|
|
402
|
+
Object.defineProperty(arrowDownEvent, 'target', { value: input })
|
|
403
|
+
|
|
404
|
+
const preventDefaultSpy = vi.spyOn(arrowDownEvent, 'preventDefault')
|
|
405
|
+
wrapper?.dispatchEvent(arrowDownEvent)
|
|
406
|
+
|
|
407
|
+
expect(preventDefaultSpy).toHaveBeenCalled()
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
it('should not move selection below 0', async () => {
|
|
411
|
+
const injector = new Injector()
|
|
412
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
413
|
+
const onSelectSuggestion = vi.fn()
|
|
414
|
+
|
|
415
|
+
initializeShadeRoot({
|
|
416
|
+
injector,
|
|
417
|
+
rootElement,
|
|
418
|
+
jsxElement: (
|
|
419
|
+
<Suggest<TestEntry>
|
|
420
|
+
defaultPrefix="🔍"
|
|
421
|
+
getEntries={getTestEntries}
|
|
422
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
423
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
424
|
+
/>
|
|
425
|
+
),
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
await advanceTimers(50)
|
|
429
|
+
|
|
430
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
431
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
432
|
+
|
|
433
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
434
|
+
|
|
435
|
+
for (let i = 0; i < 5; i++) {
|
|
436
|
+
const arrowUpEvent = new KeyboardEvent('keyup', { key: 'ArrowUp', bubbles: true })
|
|
437
|
+
Object.defineProperty(arrowUpEvent, 'target', { value: input })
|
|
438
|
+
wrapper?.dispatchEvent(arrowUpEvent)
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
await advanceTimers(50)
|
|
442
|
+
|
|
443
|
+
expect(suggest).not.toBeNull()
|
|
444
|
+
})
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
describe('open/close behavior', () => {
|
|
448
|
+
it('should open when clicking term icon', async () => {
|
|
449
|
+
const injector = new Injector()
|
|
450
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
451
|
+
const onSelectSuggestion = vi.fn()
|
|
452
|
+
|
|
453
|
+
initializeShadeRoot({
|
|
454
|
+
injector,
|
|
455
|
+
rootElement,
|
|
456
|
+
jsxElement: (
|
|
457
|
+
<Suggest<TestEntry>
|
|
458
|
+
defaultPrefix="🔍"
|
|
459
|
+
getEntries={getTestEntries}
|
|
460
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
461
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
462
|
+
/>
|
|
463
|
+
),
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
await advanceTimers(50)
|
|
467
|
+
|
|
468
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
469
|
+
const termIcon = suggest?.querySelector('.term-icon') as HTMLElement
|
|
470
|
+
|
|
471
|
+
termIcon?.click()
|
|
472
|
+
|
|
473
|
+
await advanceTimers(50)
|
|
474
|
+
|
|
475
|
+
expect(suggest?.classList.contains('opened')).toBe(true)
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
it('should close when clicking close button', async () => {
|
|
479
|
+
const injector = new Injector()
|
|
480
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
481
|
+
const onSelectSuggestion = vi.fn()
|
|
482
|
+
|
|
483
|
+
initializeShadeRoot({
|
|
484
|
+
injector,
|
|
485
|
+
rootElement,
|
|
486
|
+
jsxElement: (
|
|
487
|
+
<Suggest<TestEntry>
|
|
488
|
+
defaultPrefix="🔍"
|
|
489
|
+
getEntries={getTestEntries}
|
|
490
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
491
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
492
|
+
/>
|
|
493
|
+
),
|
|
494
|
+
})
|
|
495
|
+
|
|
496
|
+
await advanceTimers(50)
|
|
497
|
+
|
|
498
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
499
|
+
const termIcon = suggest?.querySelector('.term-icon') as HTMLElement
|
|
500
|
+
termIcon?.click()
|
|
501
|
+
|
|
502
|
+
await advanceTimers(50)
|
|
503
|
+
|
|
504
|
+
const closeButton = suggest?.querySelector('.close-suggestions') as HTMLElement
|
|
505
|
+
closeButton?.click()
|
|
506
|
+
|
|
507
|
+
await advanceTimers(50)
|
|
508
|
+
|
|
509
|
+
expect(suggest?.classList.contains('opened')).toBe(false)
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
it('should trigger animation when opening', async () => {
|
|
513
|
+
const injector = new Injector()
|
|
514
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
515
|
+
const onSelectSuggestion = vi.fn()
|
|
516
|
+
|
|
517
|
+
initializeShadeRoot({
|
|
518
|
+
injector,
|
|
519
|
+
rootElement,
|
|
520
|
+
jsxElement: (
|
|
521
|
+
<Suggest<TestEntry>
|
|
522
|
+
defaultPrefix="🔍"
|
|
523
|
+
getEntries={getTestEntries}
|
|
524
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
525
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
526
|
+
/>
|
|
527
|
+
),
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
await advanceTimers(50)
|
|
531
|
+
|
|
532
|
+
const initialAnimationCount = animateCalls.length
|
|
533
|
+
|
|
534
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
535
|
+
const termIcon = suggest?.querySelector('.term-icon') as HTMLElement
|
|
536
|
+
termIcon?.click()
|
|
537
|
+
|
|
538
|
+
await advanceTimers(50)
|
|
539
|
+
|
|
540
|
+
expect(animateCalls.length).toBeGreaterThan(initialAnimationCount)
|
|
541
|
+
})
|
|
542
|
+
|
|
543
|
+
it('should trigger animation when closing', async () => {
|
|
544
|
+
const injector = new Injector()
|
|
545
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
546
|
+
const onSelectSuggestion = vi.fn()
|
|
547
|
+
|
|
548
|
+
initializeShadeRoot({
|
|
549
|
+
injector,
|
|
550
|
+
rootElement,
|
|
551
|
+
jsxElement: (
|
|
552
|
+
<Suggest<TestEntry>
|
|
553
|
+
defaultPrefix="🔍"
|
|
554
|
+
getEntries={getTestEntries}
|
|
555
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
556
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
557
|
+
/>
|
|
558
|
+
),
|
|
559
|
+
})
|
|
560
|
+
|
|
561
|
+
await advanceTimers(50)
|
|
562
|
+
|
|
563
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
564
|
+
const termIcon = suggest?.querySelector('.term-icon') as HTMLElement
|
|
565
|
+
termIcon?.click()
|
|
566
|
+
|
|
567
|
+
await advanceTimers(50)
|
|
568
|
+
|
|
569
|
+
const animationCountAfterOpen = animateCalls.length
|
|
570
|
+
|
|
571
|
+
const closeButton = suggest?.querySelector('.close-suggestions') as HTMLElement
|
|
572
|
+
closeButton?.click()
|
|
573
|
+
|
|
574
|
+
await advanceTimers(50)
|
|
575
|
+
|
|
576
|
+
expect(animateCalls.length).toBeGreaterThan(animationCountAfterOpen)
|
|
577
|
+
})
|
|
578
|
+
})
|
|
579
|
+
|
|
580
|
+
describe('suggestions loading', () => {
|
|
581
|
+
it('should fetch suggestions when typing', async () => {
|
|
582
|
+
const injector = new Injector()
|
|
583
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
584
|
+
const onSelectSuggestion = vi.fn()
|
|
585
|
+
const getEntriesSpy = vi.fn(getTestEntries)
|
|
586
|
+
|
|
587
|
+
initializeShadeRoot({
|
|
588
|
+
injector,
|
|
589
|
+
rootElement,
|
|
590
|
+
jsxElement: (
|
|
591
|
+
<Suggest<TestEntry>
|
|
592
|
+
defaultPrefix="🔍"
|
|
593
|
+
getEntries={getEntriesSpy}
|
|
594
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
595
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
596
|
+
/>
|
|
597
|
+
),
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
await advanceTimers(50)
|
|
601
|
+
|
|
602
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
603
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
604
|
+
|
|
605
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
606
|
+
input.value = 'First'
|
|
607
|
+
|
|
608
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
609
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
610
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
611
|
+
|
|
612
|
+
await advanceTimers(300)
|
|
613
|
+
|
|
614
|
+
expect(getEntriesSpy).toHaveBeenCalledWith('First')
|
|
615
|
+
})
|
|
616
|
+
|
|
617
|
+
it('should show loader animation while loading', async () => {
|
|
618
|
+
const injector = new Injector()
|
|
619
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
620
|
+
const onSelectSuggestion = vi.fn()
|
|
621
|
+
|
|
622
|
+
const resolveHolder: { resolve: ((entries: TestEntry[]) => void) | null } = { resolve: null }
|
|
623
|
+
const slowGetEntries = () =>
|
|
624
|
+
new Promise<TestEntry[]>((resolve) => {
|
|
625
|
+
resolveHolder.resolve = resolve
|
|
626
|
+
})
|
|
627
|
+
|
|
628
|
+
initializeShadeRoot({
|
|
629
|
+
injector,
|
|
630
|
+
rootElement,
|
|
631
|
+
jsxElement: (
|
|
632
|
+
<Suggest<TestEntry>
|
|
633
|
+
defaultPrefix="🔍"
|
|
634
|
+
getEntries={slowGetEntries}
|
|
635
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
636
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
637
|
+
/>
|
|
638
|
+
),
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
await advanceTimers(50)
|
|
642
|
+
|
|
643
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
644
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
645
|
+
|
|
646
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
647
|
+
input.value = 'test'
|
|
648
|
+
|
|
649
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
650
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
651
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
652
|
+
|
|
653
|
+
await advanceTimers(300)
|
|
654
|
+
|
|
655
|
+
const loader = suggest?.querySelector('shade-loader')
|
|
656
|
+
expect(loader).not.toBeNull()
|
|
657
|
+
|
|
658
|
+
resolveHolder.resolve?.(createTestEntries())
|
|
659
|
+
await advanceTimers(50)
|
|
660
|
+
})
|
|
661
|
+
|
|
662
|
+
it('should render suggestions after loading', async () => {
|
|
663
|
+
const injector = new Injector()
|
|
664
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
665
|
+
const onSelectSuggestion = vi.fn()
|
|
666
|
+
|
|
667
|
+
initializeShadeRoot({
|
|
668
|
+
injector,
|
|
669
|
+
rootElement,
|
|
670
|
+
jsxElement: (
|
|
671
|
+
<Suggest<TestEntry>
|
|
672
|
+
defaultPrefix="🔍"
|
|
673
|
+
getEntries={getTestEntries}
|
|
674
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
675
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
676
|
+
/>
|
|
677
|
+
),
|
|
678
|
+
})
|
|
679
|
+
|
|
680
|
+
await advanceTimers(50)
|
|
681
|
+
|
|
682
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
683
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
684
|
+
|
|
685
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
686
|
+
input.value = 'test'
|
|
687
|
+
|
|
688
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
689
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
690
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
691
|
+
|
|
692
|
+
await advanceTimers(300)
|
|
693
|
+
|
|
694
|
+
const suggestionList = suggest?.querySelector('shade-suggest-suggestion-list')
|
|
695
|
+
expect(suggestionList).not.toBeNull()
|
|
696
|
+
})
|
|
697
|
+
})
|
|
698
|
+
|
|
699
|
+
describe('suggestion selection', () => {
|
|
700
|
+
it('should call onSelectSuggestion when selecting via Enter', async () => {
|
|
701
|
+
const injector = new Injector()
|
|
702
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
703
|
+
const onSelectSuggestion = vi.fn()
|
|
704
|
+
|
|
705
|
+
initializeShadeRoot({
|
|
706
|
+
injector,
|
|
707
|
+
rootElement,
|
|
708
|
+
jsxElement: (
|
|
709
|
+
<Suggest<TestEntry>
|
|
710
|
+
defaultPrefix="🔍"
|
|
711
|
+
getEntries={getTestEntries}
|
|
712
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
713
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
714
|
+
/>
|
|
715
|
+
),
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
await advanceTimers(50)
|
|
719
|
+
|
|
720
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
721
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
722
|
+
|
|
723
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
724
|
+
input.value = 'First'
|
|
725
|
+
|
|
726
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
727
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
728
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
729
|
+
|
|
730
|
+
await advanceTimers(300)
|
|
731
|
+
|
|
732
|
+
const enterEvent = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true })
|
|
733
|
+
Object.defineProperty(enterEvent, 'target', { value: input })
|
|
734
|
+
wrapper?.dispatchEvent(enterEvent)
|
|
735
|
+
|
|
736
|
+
await advanceTimers(50)
|
|
737
|
+
|
|
738
|
+
expect(onSelectSuggestion).toHaveBeenCalledWith(expect.objectContaining({ name: 'First' }))
|
|
739
|
+
})
|
|
740
|
+
|
|
741
|
+
it('should close after selecting a suggestion', async () => {
|
|
742
|
+
const injector = new Injector()
|
|
743
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
744
|
+
const onSelectSuggestion = vi.fn()
|
|
745
|
+
|
|
746
|
+
initializeShadeRoot({
|
|
747
|
+
injector,
|
|
748
|
+
rootElement,
|
|
749
|
+
jsxElement: (
|
|
750
|
+
<Suggest<TestEntry>
|
|
751
|
+
defaultPrefix="🔍"
|
|
752
|
+
getEntries={getTestEntries}
|
|
753
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
754
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
755
|
+
/>
|
|
756
|
+
),
|
|
757
|
+
})
|
|
758
|
+
|
|
759
|
+
await advanceTimers(50)
|
|
760
|
+
|
|
761
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
762
|
+
const wrapper = suggest?.querySelector('.suggest-wrapper') as HTMLElement
|
|
763
|
+
|
|
764
|
+
const input = suggest?.querySelector('input') as HTMLInputElement
|
|
765
|
+
input.value = 'First'
|
|
766
|
+
|
|
767
|
+
const keyupEvent = new KeyboardEvent('keyup', { key: 'a', bubbles: true })
|
|
768
|
+
Object.defineProperty(keyupEvent, 'target', { value: input })
|
|
769
|
+
wrapper?.dispatchEvent(keyupEvent)
|
|
770
|
+
|
|
771
|
+
await advanceTimers(300)
|
|
772
|
+
|
|
773
|
+
expect(suggest?.classList.contains('opened')).toBe(true)
|
|
774
|
+
|
|
775
|
+
const enterEvent = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true })
|
|
776
|
+
Object.defineProperty(enterEvent, 'target', { value: input })
|
|
777
|
+
wrapper?.dispatchEvent(enterEvent)
|
|
778
|
+
|
|
779
|
+
await advanceTimers(50)
|
|
780
|
+
|
|
781
|
+
expect(suggest?.classList.contains('opened')).toBe(false)
|
|
782
|
+
})
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
describe('sub-components', () => {
|
|
786
|
+
it('should render SuggestInput component', async () => {
|
|
787
|
+
const injector = new Injector()
|
|
788
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
789
|
+
const onSelectSuggestion = vi.fn()
|
|
790
|
+
|
|
791
|
+
initializeShadeRoot({
|
|
792
|
+
injector,
|
|
793
|
+
rootElement,
|
|
794
|
+
jsxElement: (
|
|
795
|
+
<Suggest<TestEntry>
|
|
796
|
+
defaultPrefix="🔍"
|
|
797
|
+
getEntries={getTestEntries}
|
|
798
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
799
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
800
|
+
/>
|
|
801
|
+
),
|
|
802
|
+
})
|
|
803
|
+
|
|
804
|
+
await advanceTimers(50)
|
|
805
|
+
|
|
806
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
807
|
+
const suggestInput = suggest?.querySelector('shades-suggest-input')
|
|
808
|
+
expect(suggestInput).not.toBeNull()
|
|
809
|
+
})
|
|
810
|
+
|
|
811
|
+
it('should render SuggestionList component', async () => {
|
|
812
|
+
const injector = new Injector()
|
|
813
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
814
|
+
const onSelectSuggestion = vi.fn()
|
|
815
|
+
|
|
816
|
+
initializeShadeRoot({
|
|
817
|
+
injector,
|
|
818
|
+
rootElement,
|
|
819
|
+
jsxElement: (
|
|
820
|
+
<Suggest<TestEntry>
|
|
821
|
+
defaultPrefix="🔍"
|
|
822
|
+
getEntries={getTestEntries}
|
|
823
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
824
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
825
|
+
/>
|
|
826
|
+
),
|
|
827
|
+
})
|
|
828
|
+
|
|
829
|
+
await advanceTimers(50)
|
|
830
|
+
|
|
831
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
832
|
+
const suggestionList = suggest?.querySelector('shade-suggest-suggestion-list')
|
|
833
|
+
expect(suggestionList).not.toBeNull()
|
|
834
|
+
})
|
|
835
|
+
|
|
836
|
+
it('should render Loader component', async () => {
|
|
837
|
+
const injector = new Injector()
|
|
838
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
839
|
+
const onSelectSuggestion = vi.fn()
|
|
840
|
+
|
|
841
|
+
initializeShadeRoot({
|
|
842
|
+
injector,
|
|
843
|
+
rootElement,
|
|
844
|
+
jsxElement: (
|
|
845
|
+
<Suggest<TestEntry>
|
|
846
|
+
defaultPrefix="🔍"
|
|
847
|
+
getEntries={getTestEntries}
|
|
848
|
+
getSuggestionEntry={getSuggestionEntry}
|
|
849
|
+
onSelectSuggestion={onSelectSuggestion}
|
|
850
|
+
/>
|
|
851
|
+
),
|
|
852
|
+
})
|
|
853
|
+
|
|
854
|
+
await advanceTimers(50)
|
|
855
|
+
|
|
856
|
+
const suggest = document.querySelector('shade-suggest') as HTMLElement
|
|
857
|
+
const loader = suggest?.querySelector('shade-loader')
|
|
858
|
+
expect(loader).not.toBeNull()
|
|
859
|
+
})
|
|
860
|
+
})
|
|
861
|
+
})
|