@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,631 @@
|
|
|
1
|
+
import { Injector } from '@furystack/inject'
|
|
2
|
+
import { createComponent, initializeShadeRoot } from '@furystack/shades'
|
|
3
|
+
import { sleepAsync, usingAsync } from '@furystack/utils'
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
+
import { defaultDarkTheme } from '../services/default-dark-theme.js'
|
|
6
|
+
import type { NotyModel } from '../services/noty-service.js'
|
|
7
|
+
import { NotyService } from '../services/noty-service.js'
|
|
8
|
+
import { ThemeProviderService } from '../services/theme-provider-service.js'
|
|
9
|
+
import { getDefaultNotyTimeouts, NotyComponent, NotyList } from './noty-list.js'
|
|
10
|
+
|
|
11
|
+
describe('getDefaultNotyTimeouts', () => {
|
|
12
|
+
it('should return 0 for error type', () => {
|
|
13
|
+
expect(getDefaultNotyTimeouts('error')).toBe(0)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should return 0 for warning type', () => {
|
|
17
|
+
expect(getDefaultNotyTimeouts('warning')).toBe(0)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should return 5000 for success type', () => {
|
|
21
|
+
expect(getDefaultNotyTimeouts('success')).toBe(5000)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should return 20000 for info type', () => {
|
|
25
|
+
expect(getDefaultNotyTimeouts('info')).toBe(20000)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should return 0 for unknown type', () => {
|
|
29
|
+
expect(getDefaultNotyTimeouts('unknown' as NotyModel['type'])).toBe(0)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('NotyComponent', () => {
|
|
34
|
+
let originalAnimate: typeof Element.prototype.animate
|
|
35
|
+
let animateCalls: Array<{ keyframes: unknown; options: unknown }>
|
|
36
|
+
|
|
37
|
+
const setupTheme = (injector: Injector) => {
|
|
38
|
+
const themeProvider = injector.getInstance(ThemeProviderService)
|
|
39
|
+
themeProvider.setAssignedTheme(defaultDarkTheme)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
44
|
+
animateCalls = []
|
|
45
|
+
originalAnimate = Element.prototype.animate
|
|
46
|
+
|
|
47
|
+
Element.prototype.animate = vi.fn(
|
|
48
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
49
|
+
animateCalls.push({ keyframes, options })
|
|
50
|
+
const mockAnimation = {
|
|
51
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
52
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
53
|
+
cancel: vi.fn(),
|
|
54
|
+
play: vi.fn(),
|
|
55
|
+
pause: vi.fn(),
|
|
56
|
+
finish: vi.fn(),
|
|
57
|
+
addEventListener: vi.fn(),
|
|
58
|
+
removeEventListener: vi.fn(),
|
|
59
|
+
}
|
|
60
|
+
return mockAnimation as unknown as Animation
|
|
61
|
+
},
|
|
62
|
+
) as typeof Element.prototype.animate
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
document.body.innerHTML = ''
|
|
67
|
+
Element.prototype.animate = originalAnimate
|
|
68
|
+
vi.restoreAllMocks()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('should render the shade-noty custom element', async () => {
|
|
72
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
73
|
+
setupTheme(injector)
|
|
74
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
75
|
+
const model: NotyModel = { type: 'info', title: 'Test', body: 'Test body' }
|
|
76
|
+
|
|
77
|
+
initializeShadeRoot({
|
|
78
|
+
injector,
|
|
79
|
+
rootElement,
|
|
80
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await sleepAsync(50)
|
|
84
|
+
|
|
85
|
+
const noty = document.querySelector('shade-noty')
|
|
86
|
+
expect(noty).not.toBeNull()
|
|
87
|
+
expect(noty?.tagName.toLowerCase()).toBe('shade-noty')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('should render title and body content', async () => {
|
|
92
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
93
|
+
setupTheme(injector)
|
|
94
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
95
|
+
const model: NotyModel = { type: 'success', title: 'Success Title', body: 'Success message body' }
|
|
96
|
+
|
|
97
|
+
initializeShadeRoot({
|
|
98
|
+
injector,
|
|
99
|
+
rootElement,
|
|
100
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
await sleepAsync(50)
|
|
104
|
+
|
|
105
|
+
expect(document.body.innerHTML).toContain('Success Title')
|
|
106
|
+
expect(document.body.innerHTML).toContain('Success message body')
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('should apply noty class with type on the element', async () => {
|
|
111
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
112
|
+
setupTheme(injector)
|
|
113
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
114
|
+
const model: NotyModel = { type: 'error', title: 'Error', body: 'Error occurred' }
|
|
115
|
+
|
|
116
|
+
initializeShadeRoot({
|
|
117
|
+
injector,
|
|
118
|
+
rootElement,
|
|
119
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
await sleepAsync(50)
|
|
123
|
+
|
|
124
|
+
const noty = document.querySelector('shade-noty') as HTMLElement
|
|
125
|
+
expect(noty).not.toBeNull()
|
|
126
|
+
expect(noty.classList.contains('noty')).toBe(true)
|
|
127
|
+
expect(noty.classList.contains('error')).toBe(true)
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('should render dismiss button', async () => {
|
|
132
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
133
|
+
setupTheme(injector)
|
|
134
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
135
|
+
const model: NotyModel = { type: 'warning', title: 'Warning', body: 'Warning message' }
|
|
136
|
+
|
|
137
|
+
initializeShadeRoot({
|
|
138
|
+
injector,
|
|
139
|
+
rootElement,
|
|
140
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
await sleepAsync(50)
|
|
144
|
+
|
|
145
|
+
const dismissButton = document.querySelector('button[is="shade-button"]')
|
|
146
|
+
expect(dismissButton).not.toBeNull()
|
|
147
|
+
expect(dismissButton?.textContent).toContain('✖')
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it('should call onDismiss when dismiss button is clicked', async () => {
|
|
152
|
+
const onDismiss = vi.fn()
|
|
153
|
+
|
|
154
|
+
Element.prototype.animate = vi.fn(
|
|
155
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
156
|
+
animateCalls.push({ keyframes, options })
|
|
157
|
+
const mockAnimation = {
|
|
158
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
159
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
160
|
+
cancel: vi.fn(),
|
|
161
|
+
play: vi.fn(),
|
|
162
|
+
pause: vi.fn(),
|
|
163
|
+
finish: vi.fn(),
|
|
164
|
+
addEventListener: vi.fn(),
|
|
165
|
+
removeEventListener: vi.fn(),
|
|
166
|
+
}
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
mockAnimation.onfinish?.({} as AnimationPlaybackEvent)
|
|
169
|
+
}, 10)
|
|
170
|
+
return mockAnimation as unknown as Animation
|
|
171
|
+
},
|
|
172
|
+
) as typeof Element.prototype.animate
|
|
173
|
+
|
|
174
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
175
|
+
setupTheme(injector)
|
|
176
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
177
|
+
const model: NotyModel = { type: 'info', title: 'Info', body: 'Info message' }
|
|
178
|
+
|
|
179
|
+
initializeShadeRoot({
|
|
180
|
+
injector,
|
|
181
|
+
rootElement,
|
|
182
|
+
jsxElement: <NotyComponent model={model} onDismiss={onDismiss} />,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
await sleepAsync(50)
|
|
186
|
+
|
|
187
|
+
const dismissButton = document.querySelector('button[is="shade-button"]') as HTMLButtonElement
|
|
188
|
+
expect(dismissButton).not.toBeNull()
|
|
189
|
+
dismissButton.click()
|
|
190
|
+
|
|
191
|
+
await sleepAsync(50)
|
|
192
|
+
|
|
193
|
+
expect(onDismiss).toHaveBeenCalled()
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('should start fade-in animation on mount', async () => {
|
|
198
|
+
vi.useFakeTimers()
|
|
199
|
+
|
|
200
|
+
const injector = new Injector()
|
|
201
|
+
setupTheme(injector)
|
|
202
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
203
|
+
const model: NotyModel = { type: 'success', title: 'Success', body: 'Success message' }
|
|
204
|
+
|
|
205
|
+
initializeShadeRoot({
|
|
206
|
+
injector,
|
|
207
|
+
rootElement,
|
|
208
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// Wait for render
|
|
212
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
213
|
+
|
|
214
|
+
// The constructed hook schedules the animation via setTimeout
|
|
215
|
+
await vi.advanceTimersByTimeAsync(10)
|
|
216
|
+
|
|
217
|
+
const fadeInCall = animateCalls.find(
|
|
218
|
+
(call) =>
|
|
219
|
+
Array.isArray(call.keyframes) && call.keyframes.some((kf: Keyframe) => 'opacity' in kf && 'height' in kf),
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
expect(fadeInCall).toBeDefined()
|
|
223
|
+
expect((fadeInCall?.options as KeyframeAnimationOptions)?.duration).toBe(700)
|
|
224
|
+
expect((fadeInCall?.options as KeyframeAnimationOptions)?.fill).toBe('forwards')
|
|
225
|
+
|
|
226
|
+
vi.useRealTimers()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it('should auto-dismiss after timeout for success type', async () => {
|
|
230
|
+
vi.useFakeTimers()
|
|
231
|
+
const onDismiss = vi.fn()
|
|
232
|
+
|
|
233
|
+
Element.prototype.animate = vi.fn(
|
|
234
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
235
|
+
animateCalls.push({ keyframes, options })
|
|
236
|
+
const mockAnimation = {
|
|
237
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
238
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
239
|
+
cancel: vi.fn(),
|
|
240
|
+
play: vi.fn(),
|
|
241
|
+
pause: vi.fn(),
|
|
242
|
+
finish: vi.fn(),
|
|
243
|
+
addEventListener: vi.fn(),
|
|
244
|
+
removeEventListener: vi.fn(),
|
|
245
|
+
}
|
|
246
|
+
setTimeout(() => {
|
|
247
|
+
mockAnimation.onfinish?.({} as AnimationPlaybackEvent)
|
|
248
|
+
}, 10)
|
|
249
|
+
return mockAnimation as unknown as Animation
|
|
250
|
+
},
|
|
251
|
+
) as typeof Element.prototype.animate
|
|
252
|
+
|
|
253
|
+
const injector = new Injector()
|
|
254
|
+
setupTheme(injector)
|
|
255
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
256
|
+
const model: NotyModel = { type: 'success', title: 'Success', body: 'Success message' }
|
|
257
|
+
|
|
258
|
+
initializeShadeRoot({
|
|
259
|
+
injector,
|
|
260
|
+
rootElement,
|
|
261
|
+
jsxElement: <NotyComponent model={model} onDismiss={onDismiss} />,
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
265
|
+
expect(onDismiss).not.toHaveBeenCalled()
|
|
266
|
+
|
|
267
|
+
// Success timeout is 5000ms
|
|
268
|
+
await vi.advanceTimersByTimeAsync(5000)
|
|
269
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
270
|
+
|
|
271
|
+
expect(onDismiss).toHaveBeenCalled()
|
|
272
|
+
|
|
273
|
+
vi.useRealTimers()
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
it('should use custom timeout when provided', async () => {
|
|
277
|
+
vi.useFakeTimers()
|
|
278
|
+
const onDismiss = vi.fn()
|
|
279
|
+
|
|
280
|
+
Element.prototype.animate = vi.fn(
|
|
281
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
282
|
+
animateCalls.push({ keyframes, options })
|
|
283
|
+
const mockAnimation = {
|
|
284
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
285
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
286
|
+
cancel: vi.fn(),
|
|
287
|
+
play: vi.fn(),
|
|
288
|
+
pause: vi.fn(),
|
|
289
|
+
finish: vi.fn(),
|
|
290
|
+
addEventListener: vi.fn(),
|
|
291
|
+
removeEventListener: vi.fn(),
|
|
292
|
+
}
|
|
293
|
+
setTimeout(() => {
|
|
294
|
+
mockAnimation.onfinish?.({} as AnimationPlaybackEvent)
|
|
295
|
+
}, 10)
|
|
296
|
+
return mockAnimation as unknown as Animation
|
|
297
|
+
},
|
|
298
|
+
) as typeof Element.prototype.animate
|
|
299
|
+
|
|
300
|
+
const injector = new Injector()
|
|
301
|
+
setupTheme(injector)
|
|
302
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
303
|
+
// Info default timeout is 20000, but we set custom 1000
|
|
304
|
+
const model: NotyModel = { type: 'info', title: 'Info', body: 'Info message', timeout: 1000 }
|
|
305
|
+
|
|
306
|
+
initializeShadeRoot({
|
|
307
|
+
injector,
|
|
308
|
+
rootElement,
|
|
309
|
+
jsxElement: <NotyComponent model={model} onDismiss={onDismiss} />,
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
313
|
+
expect(onDismiss).not.toHaveBeenCalled()
|
|
314
|
+
|
|
315
|
+
await vi.advanceTimersByTimeAsync(1000)
|
|
316
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
317
|
+
|
|
318
|
+
expect(onDismiss).toHaveBeenCalled()
|
|
319
|
+
|
|
320
|
+
vi.useRealTimers()
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('should not auto-dismiss for error type (timeout 0)', async () => {
|
|
324
|
+
vi.useFakeTimers()
|
|
325
|
+
const onDismiss = vi.fn()
|
|
326
|
+
|
|
327
|
+
const injector = new Injector()
|
|
328
|
+
setupTheme(injector)
|
|
329
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
330
|
+
const model: NotyModel = { type: 'error', title: 'Error', body: 'Error message' }
|
|
331
|
+
|
|
332
|
+
initializeShadeRoot({
|
|
333
|
+
injector,
|
|
334
|
+
rootElement,
|
|
335
|
+
jsxElement: <NotyComponent model={model} onDismiss={onDismiss} />,
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
339
|
+
await vi.advanceTimersByTimeAsync(30000)
|
|
340
|
+
|
|
341
|
+
expect(onDismiss).not.toHaveBeenCalled()
|
|
342
|
+
|
|
343
|
+
vi.useRealTimers()
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it('should render all noty types with appropriate styling', async () => {
|
|
347
|
+
const types: Array<NotyModel['type']> = ['error', 'warning', 'info', 'success']
|
|
348
|
+
|
|
349
|
+
for (const type of types) {
|
|
350
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
351
|
+
|
|
352
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
353
|
+
setupTheme(injector)
|
|
354
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
355
|
+
const model: NotyModel = { type, title: `${type} Title`, body: `${type} body` }
|
|
356
|
+
|
|
357
|
+
initializeShadeRoot({
|
|
358
|
+
injector,
|
|
359
|
+
rootElement,
|
|
360
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
await sleepAsync(50)
|
|
364
|
+
|
|
365
|
+
const noty = document.querySelector('shade-noty') as HTMLElement
|
|
366
|
+
expect(noty).not.toBeNull()
|
|
367
|
+
expect(noty.classList.contains('noty')).toBe(true)
|
|
368
|
+
expect(noty.classList.contains(type)).toBe(true)
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
it('should apply background color from theme', async () => {
|
|
374
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
375
|
+
setupTheme(injector)
|
|
376
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
377
|
+
const model: NotyModel = { type: 'success', title: 'Success', body: 'Message' }
|
|
378
|
+
|
|
379
|
+
initializeShadeRoot({
|
|
380
|
+
injector,
|
|
381
|
+
rootElement,
|
|
382
|
+
jsxElement: <NotyComponent model={model} onDismiss={() => {}} />,
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
await sleepAsync(50)
|
|
386
|
+
|
|
387
|
+
const noty = document.querySelector('shade-noty') as HTMLElement
|
|
388
|
+
expect(noty).not.toBeNull()
|
|
389
|
+
// The component sets backgroundColor via style
|
|
390
|
+
expect(noty.style.backgroundColor).toBeTruthy()
|
|
391
|
+
})
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
describe('NotyList', () => {
|
|
396
|
+
let originalAnimate: typeof Element.prototype.animate
|
|
397
|
+
let animateCalls: Array<{ keyframes: unknown; options: unknown }>
|
|
398
|
+
|
|
399
|
+
const setupTheme = (injector: Injector) => {
|
|
400
|
+
const themeProvider = injector.getInstance(ThemeProviderService)
|
|
401
|
+
themeProvider.setAssignedTheme(defaultDarkTheme)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
beforeEach(() => {
|
|
405
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
406
|
+
animateCalls = []
|
|
407
|
+
originalAnimate = Element.prototype.animate
|
|
408
|
+
|
|
409
|
+
Element.prototype.animate = vi.fn(
|
|
410
|
+
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
411
|
+
animateCalls.push({ keyframes, options })
|
|
412
|
+
const mockAnimation = {
|
|
413
|
+
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
414
|
+
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
415
|
+
cancel: vi.fn(),
|
|
416
|
+
play: vi.fn(),
|
|
417
|
+
pause: vi.fn(),
|
|
418
|
+
finish: vi.fn(),
|
|
419
|
+
addEventListener: vi.fn(),
|
|
420
|
+
removeEventListener: vi.fn(),
|
|
421
|
+
}
|
|
422
|
+
return mockAnimation as unknown as Animation
|
|
423
|
+
},
|
|
424
|
+
) as typeof Element.prototype.animate
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
afterEach(() => {
|
|
428
|
+
document.body.innerHTML = ''
|
|
429
|
+
Element.prototype.animate = originalAnimate
|
|
430
|
+
vi.restoreAllMocks()
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
it('should render the shade-noty-list custom element', async () => {
|
|
434
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
435
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
436
|
+
|
|
437
|
+
initializeShadeRoot({
|
|
438
|
+
injector,
|
|
439
|
+
rootElement,
|
|
440
|
+
jsxElement: <NotyList />,
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
await sleepAsync(50)
|
|
444
|
+
|
|
445
|
+
const notyList = document.querySelector('shade-noty-list')
|
|
446
|
+
expect(notyList).not.toBeNull()
|
|
447
|
+
expect(notyList?.tagName.toLowerCase()).toBe('shade-noty-list')
|
|
448
|
+
})
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
it('should have fixed positioning styles', async () => {
|
|
452
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
453
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
454
|
+
|
|
455
|
+
initializeShadeRoot({
|
|
456
|
+
injector,
|
|
457
|
+
rootElement,
|
|
458
|
+
jsxElement: <NotyList />,
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
await sleepAsync(50)
|
|
462
|
+
|
|
463
|
+
const notyList = document.querySelector('shade-noty-list') as HTMLElement
|
|
464
|
+
expect(notyList).not.toBeNull()
|
|
465
|
+
|
|
466
|
+
const computedStyle = window.getComputedStyle(notyList)
|
|
467
|
+
expect(computedStyle.position).toBe('fixed')
|
|
468
|
+
expect(computedStyle.display).toBe('flex')
|
|
469
|
+
expect(computedStyle.flexDirection).toBe('column')
|
|
470
|
+
})
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
it('should render existing notys from NotyService', async () => {
|
|
474
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
475
|
+
setupTheme(injector)
|
|
476
|
+
const notyService = injector.getInstance(NotyService)
|
|
477
|
+
const noty1: NotyModel = { type: 'info', title: 'Info 1', body: 'Info body 1' }
|
|
478
|
+
const noty2: NotyModel = { type: 'success', title: 'Success 1', body: 'Success body 1' }
|
|
479
|
+
|
|
480
|
+
notyService.emit('onNotyAdded', noty1)
|
|
481
|
+
notyService.emit('onNotyAdded', noty2)
|
|
482
|
+
|
|
483
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
484
|
+
|
|
485
|
+
initializeShadeRoot({
|
|
486
|
+
injector,
|
|
487
|
+
rootElement,
|
|
488
|
+
jsxElement: <NotyList />,
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
await sleepAsync(50)
|
|
492
|
+
|
|
493
|
+
const notys = document.querySelectorAll('shade-noty')
|
|
494
|
+
expect(notys.length).toBe(2)
|
|
495
|
+
})
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
it('should add new noty when NotyService emits onNotyAdded', async () => {
|
|
499
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
500
|
+
setupTheme(injector)
|
|
501
|
+
const notyService = injector.getInstance(NotyService)
|
|
502
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
503
|
+
|
|
504
|
+
initializeShadeRoot({
|
|
505
|
+
injector,
|
|
506
|
+
rootElement,
|
|
507
|
+
jsxElement: <NotyList />,
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
await sleepAsync(50)
|
|
511
|
+
|
|
512
|
+
let notys = document.querySelectorAll('shade-noty')
|
|
513
|
+
expect(notys.length).toBe(0)
|
|
514
|
+
|
|
515
|
+
const newNoty: NotyModel = { type: 'warning', title: 'Warning', body: 'Warning message' }
|
|
516
|
+
notyService.emit('onNotyAdded', newNoty)
|
|
517
|
+
|
|
518
|
+
await sleepAsync(50)
|
|
519
|
+
|
|
520
|
+
notys = document.querySelectorAll('shade-noty')
|
|
521
|
+
expect(notys.length).toBe(1)
|
|
522
|
+
})
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
it('should remove noty when NotyService emits onNotyRemoved', async () => {
|
|
526
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
527
|
+
setupTheme(injector)
|
|
528
|
+
const notyService = injector.getInstance(NotyService)
|
|
529
|
+
const noty: NotyModel = { type: 'error', title: 'Error', body: 'Error message' }
|
|
530
|
+
|
|
531
|
+
notyService.emit('onNotyAdded', noty)
|
|
532
|
+
|
|
533
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
534
|
+
|
|
535
|
+
initializeShadeRoot({
|
|
536
|
+
injector,
|
|
537
|
+
rootElement,
|
|
538
|
+
jsxElement: <NotyList />,
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
await sleepAsync(50)
|
|
542
|
+
|
|
543
|
+
let notys = document.querySelectorAll('shade-noty')
|
|
544
|
+
expect(notys.length).toBe(1)
|
|
545
|
+
|
|
546
|
+
notyService.emit('onNotyRemoved', noty)
|
|
547
|
+
|
|
548
|
+
await sleepAsync(50)
|
|
549
|
+
|
|
550
|
+
notys = document.querySelectorAll('shade-noty')
|
|
551
|
+
expect(notys.length).toBe(0)
|
|
552
|
+
})
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
it('should handle multiple notys being added and removed', async () => {
|
|
556
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
557
|
+
setupTheme(injector)
|
|
558
|
+
const notyService = injector.getInstance(NotyService)
|
|
559
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
560
|
+
|
|
561
|
+
initializeShadeRoot({
|
|
562
|
+
injector,
|
|
563
|
+
rootElement,
|
|
564
|
+
jsxElement: <NotyList />,
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
await sleepAsync(50)
|
|
568
|
+
|
|
569
|
+
const noty1: NotyModel = { type: 'info', title: 'Info 1', body: 'Body 1' }
|
|
570
|
+
const noty2: NotyModel = { type: 'success', title: 'Success 1', body: 'Body 2' }
|
|
571
|
+
const noty3: NotyModel = { type: 'warning', title: 'Warning 1', body: 'Body 3' }
|
|
572
|
+
|
|
573
|
+
notyService.emit('onNotyAdded', noty1)
|
|
574
|
+
notyService.emit('onNotyAdded', noty2)
|
|
575
|
+
notyService.emit('onNotyAdded', noty3)
|
|
576
|
+
|
|
577
|
+
await sleepAsync(50)
|
|
578
|
+
|
|
579
|
+
let notys = document.querySelectorAll('shade-noty')
|
|
580
|
+
expect(notys.length).toBe(3)
|
|
581
|
+
|
|
582
|
+
notyService.emit('onNotyRemoved', noty2)
|
|
583
|
+
|
|
584
|
+
await sleepAsync(50)
|
|
585
|
+
|
|
586
|
+
notys = document.querySelectorAll('shade-noty')
|
|
587
|
+
expect(notys.length).toBe(2)
|
|
588
|
+
|
|
589
|
+
notyService.emit('onNotyRemoved', noty1)
|
|
590
|
+
notyService.emit('onNotyRemoved', noty3)
|
|
591
|
+
|
|
592
|
+
await sleepAsync(50)
|
|
593
|
+
|
|
594
|
+
notys = document.querySelectorAll('shade-noty')
|
|
595
|
+
expect(notys.length).toBe(0)
|
|
596
|
+
})
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
it('should only remove the specific noty that was requested', async () => {
|
|
600
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
601
|
+
setupTheme(injector)
|
|
602
|
+
const notyService = injector.getInstance(NotyService)
|
|
603
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
604
|
+
|
|
605
|
+
const noty1: NotyModel = { type: 'info', title: 'Keep this', body: 'Body 1' }
|
|
606
|
+
const noty2: NotyModel = { type: 'error', title: 'Remove this', body: 'Body 2' }
|
|
607
|
+
|
|
608
|
+
notyService.emit('onNotyAdded', noty1)
|
|
609
|
+
notyService.emit('onNotyAdded', noty2)
|
|
610
|
+
|
|
611
|
+
initializeShadeRoot({
|
|
612
|
+
injector,
|
|
613
|
+
rootElement,
|
|
614
|
+
jsxElement: <NotyList />,
|
|
615
|
+
})
|
|
616
|
+
|
|
617
|
+
await sleepAsync(50)
|
|
618
|
+
|
|
619
|
+
notyService.emit('onNotyRemoved', noty2)
|
|
620
|
+
|
|
621
|
+
await sleepAsync(50)
|
|
622
|
+
|
|
623
|
+
const notys = document.querySelectorAll('shade-noty')
|
|
624
|
+
expect(notys.length).toBe(1)
|
|
625
|
+
|
|
626
|
+
// Check that the remaining noty is the correct one
|
|
627
|
+
expect(document.body.innerHTML).toContain('Keep this')
|
|
628
|
+
expect(document.body.innerHTML).not.toContain('Remove this')
|
|
629
|
+
})
|
|
630
|
+
})
|
|
631
|
+
})
|