@oslokommune/punkt-elements 13.5.2 → 13.5.4
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 +34 -0
- package/dist/{alert-DQNBDKjT.cjs → alert-7rUOhlNi.cjs} +2 -1
- package/dist/{alert-B07oUpkq.js → alert-cUBtwi2k.js} +12 -11
- package/dist/{loader-CHPxY9c6.cjs → loader-DNidjwH-.cjs} +6 -1
- package/dist/{loader-Da4IOk_T.js → loader-h3d-3D7s.js} +6 -1
- package/dist/{messagebox-DwGdcdm7.js → messagebox-C8KQgCl_.js} +14 -13
- package/dist/{messagebox-CqUBJs_D.cjs → messagebox-CjPtPPrW.cjs} +1 -0
- package/dist/pkt-alert.cjs +1 -1
- package/dist/pkt-alert.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +3 -3
- package/dist/pkt-loader.cjs +1 -1
- package/dist/pkt-loader.js +1 -1
- package/dist/pkt-messagebox.cjs +1 -1
- package/dist/pkt-messagebox.js +1 -1
- package/package.json +6 -2
- package/src/components/alert/alert.test.ts +64 -79
- package/src/components/alert/alert.ts +1 -0
- package/src/components/backlink/backlink.test.ts +50 -96
- package/src/components/button/button.test.ts +211 -249
- package/src/components/calendar/calendar.accessibility.test.ts +30 -43
- package/src/components/card/card.test.ts +71 -121
- package/src/components/checkbox/checkbox.test.ts +231 -156
- package/src/components/consent/consent.test.ts +87 -91
- package/src/components/icon/icon.test.ts +368 -0
- package/src/components/input-wrapper/input-wrapper.test.ts +505 -0
- package/src/components/link/link.test.ts +224 -0
- package/src/components/linkcard/linkcard.test.ts +14 -12
- package/src/components/listbox/listbox.test.ts +225 -0
- package/src/components/loader/loader.test.ts +257 -0
- package/src/components/loader/loader.ts +6 -1
- package/src/components/messagebox/messagebox.test.ts +241 -0
- package/src/components/messagebox/messagebox.ts +1 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
3
|
+
import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
|
|
4
|
+
import { CustomElementFor } from '../../tests/component-registry'
|
|
5
|
+
import { type IPktLoader } from './loader'
|
|
6
|
+
import './loader'
|
|
7
|
+
|
|
8
|
+
export interface LoaderTestConfig extends Partial<IPktLoader>, BaseTestConfig {}
|
|
9
|
+
|
|
10
|
+
// Use shared framework
|
|
11
|
+
export const createLoaderTest = async (config: LoaderTestConfig = {}) => {
|
|
12
|
+
const { container, element } = await createElementTest<
|
|
13
|
+
CustomElementFor<'pkt-loader'>,
|
|
14
|
+
LoaderTestConfig
|
|
15
|
+
>('pkt-loader', { ...config, isLoading: undefined })
|
|
16
|
+
|
|
17
|
+
// Set boolean properties directly on the element after creation
|
|
18
|
+
if (config.isLoading !== undefined) {
|
|
19
|
+
element.isLoading = config.isLoading
|
|
20
|
+
await element.updateComplete
|
|
21
|
+
}
|
|
22
|
+
if (config.inline !== undefined) {
|
|
23
|
+
element.inline = config.inline
|
|
24
|
+
await element.updateComplete
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
container,
|
|
29
|
+
loader: element,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
expect.extend(toHaveNoViolations)
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
document.body.innerHTML = ''
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
describe('PktLoader', () => {
|
|
40
|
+
describe('Rendering and basic functionality', () => {
|
|
41
|
+
test('renders without errors', async () => {
|
|
42
|
+
const { loader } = await createLoaderTest()
|
|
43
|
+
|
|
44
|
+
expect(loader).toBeInTheDocument()
|
|
45
|
+
expect(loader).toBeTruthy()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('renders loading state by default', async () => {
|
|
49
|
+
const { loader } = await createLoaderTest()
|
|
50
|
+
|
|
51
|
+
expect(loader.isLoading).toBe(true)
|
|
52
|
+
const spinner = loader.querySelector('.pkt-loader__spinner')
|
|
53
|
+
expect(spinner).toBeInTheDocument()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('renders content when not loading', async () => {
|
|
57
|
+
const { loader } = await createLoaderTest({
|
|
58
|
+
content: '<p>Content</p>',
|
|
59
|
+
isLoading: false,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
expect(loader.isLoading).toBe(false)
|
|
63
|
+
const content = loader.querySelector('.pkt-contents')
|
|
64
|
+
expect(content).toBeInTheDocument()
|
|
65
|
+
expect(content?.classList.contains('pkt-hide')).toBe(false)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('renders with slot content', async () => {
|
|
69
|
+
const { loader } = await createLoaderTest({
|
|
70
|
+
content: '<p>Test content</p>',
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const content = loader.querySelector('p')
|
|
74
|
+
expect(content).toBeInTheDocument()
|
|
75
|
+
expect(content?.textContent).toBe('Test content')
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
describe('Properties and attributes', () => {
|
|
80
|
+
test('applies default properties correctly', async () => {
|
|
81
|
+
const { loader } = await createLoaderTest()
|
|
82
|
+
|
|
83
|
+
expect(loader.isLoading).toBe(true)
|
|
84
|
+
expect(loader.inline).toBe(false)
|
|
85
|
+
expect(loader.size).toBe('medium')
|
|
86
|
+
expect(loader.variant).toBe('shapes')
|
|
87
|
+
expect(loader.delay).toBe(0)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('sets properties correctly', async () => {
|
|
91
|
+
const { loader } = await createLoaderTest({
|
|
92
|
+
size: 'small',
|
|
93
|
+
variant: 'blue',
|
|
94
|
+
delay: 100,
|
|
95
|
+
isLoading: false,
|
|
96
|
+
inline: true,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
expect(loader.isLoading).toBe(false)
|
|
100
|
+
expect(loader.inline).toBe(true)
|
|
101
|
+
expect(loader.size).toBe('small')
|
|
102
|
+
expect(loader.variant).toBe('blue')
|
|
103
|
+
expect(loader.delay).toBe(100)
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
describe('Size variants', () => {
|
|
108
|
+
test('applies small size correctly', async () => {
|
|
109
|
+
const { loader } = await createLoaderTest({ size: 'small' })
|
|
110
|
+
|
|
111
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
112
|
+
expect(loaderDiv?.classList.contains('pkt-loader--small')).toBe(true)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('applies medium size correctly', async () => {
|
|
116
|
+
const { loader } = await createLoaderTest({ size: 'medium' })
|
|
117
|
+
|
|
118
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
119
|
+
expect(loaderDiv?.classList.contains('pkt-loader--medium')).toBe(true)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('applies large size correctly', async () => {
|
|
123
|
+
const { loader } = await createLoaderTest({ size: 'large' })
|
|
124
|
+
|
|
125
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
126
|
+
expect(loaderDiv?.classList.contains('pkt-loader--large')).toBe(true)
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
describe('Loader variants', () => {
|
|
131
|
+
test('applies shapes variant correctly', async () => {
|
|
132
|
+
const { loader } = await createLoaderTest({ variant: 'shapes' })
|
|
133
|
+
|
|
134
|
+
const icon = loader.querySelector('pkt-icon')
|
|
135
|
+
expect(icon?.getAttribute('name')).toBe('loader')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('applies blue variant correctly', async () => {
|
|
139
|
+
const { loader } = await createLoaderTest({ variant: 'blue' })
|
|
140
|
+
|
|
141
|
+
const icon = loader.querySelector('pkt-icon')
|
|
142
|
+
expect(icon?.getAttribute('name')).toBe('spinner-blue')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('applies rainbow variant correctly', async () => {
|
|
146
|
+
const { loader } = await createLoaderTest({ variant: 'rainbow' })
|
|
147
|
+
|
|
148
|
+
const icon = loader.querySelector('pkt-icon')
|
|
149
|
+
expect(icon?.getAttribute('name')).toBe('spinner')
|
|
150
|
+
})
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
describe('Inline mode', () => {
|
|
154
|
+
test('applies box class when inline is false', async () => {
|
|
155
|
+
const { loader } = await createLoaderTest({ inline: false })
|
|
156
|
+
|
|
157
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
158
|
+
expect(loaderDiv?.classList.contains('pkt-loader--box')).toBe(true)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('applies inline class when inline is true', async () => {
|
|
162
|
+
const { loader } = await createLoaderTest({ inline: true })
|
|
163
|
+
|
|
164
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
165
|
+
expect(loaderDiv?.classList.contains('pkt-loader--inline')).toBe(true)
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
describe('Message functionality', () => {
|
|
170
|
+
test('renders message when provided', async () => {
|
|
171
|
+
const { loader } = await createLoaderTest({ message: 'Loading data...' })
|
|
172
|
+
|
|
173
|
+
const message = loader.querySelector('p')
|
|
174
|
+
expect(message).toBeInTheDocument()
|
|
175
|
+
expect(message?.textContent).toBe('Loading data...')
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test('does not render message when not provided', async () => {
|
|
179
|
+
const { loader } = await createLoaderTest()
|
|
180
|
+
|
|
181
|
+
const message = loader.querySelector('p')
|
|
182
|
+
expect(message).not.toBeInTheDocument()
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
describe('Delay functionality', () => {
|
|
187
|
+
test('handles delay correctly', async () => {
|
|
188
|
+
const { loader } = await createLoaderTest({ delay: 100 })
|
|
189
|
+
|
|
190
|
+
// Initially should not show spinner due to delay
|
|
191
|
+
let spinner = loader.querySelector('.pkt-loader__spinner')
|
|
192
|
+
expect(spinner).not.toBeInTheDocument()
|
|
193
|
+
|
|
194
|
+
// Wait for delay to pass
|
|
195
|
+
await new Promise((resolve) => setTimeout(resolve, 150))
|
|
196
|
+
await loader.updateComplete
|
|
197
|
+
|
|
198
|
+
// Now spinner should be visible
|
|
199
|
+
spinner = loader.querySelector('.pkt-loader__spinner')
|
|
200
|
+
expect(spinner).toBeInTheDocument()
|
|
201
|
+
}, 300)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
describe('Content visibility', () => {
|
|
205
|
+
test('hides content when loading', async () => {
|
|
206
|
+
const { loader } = await createLoaderTest({
|
|
207
|
+
isLoading: true,
|
|
208
|
+
content: '<p>Content</p>',
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
const content = loader.querySelector('.pkt-contents')
|
|
212
|
+
expect(content?.classList.contains('pkt-hide')).toBe(true)
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test('shows content when not loading', async () => {
|
|
216
|
+
const { loader } = await createLoaderTest({
|
|
217
|
+
isLoading: false,
|
|
218
|
+
content: '<p>Content</p>',
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const content = loader.querySelector('.pkt-contents')
|
|
222
|
+
expect(content?.classList.contains('pkt-hide')).toBe(false)
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
describe('ARIA and accessibility', () => {
|
|
227
|
+
test('has correct ARIA attributes', async () => {
|
|
228
|
+
const { loader } = await createLoaderTest()
|
|
229
|
+
|
|
230
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
231
|
+
expect(loaderDiv?.getAttribute('role')).toBe('status')
|
|
232
|
+
expect(loaderDiv?.getAttribute('aria-live')).toBe('polite')
|
|
233
|
+
// Check the aria-busy attribute
|
|
234
|
+
expect(loaderDiv?.getAttribute('aria-busy')).toBe('true')
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
test('updates aria-busy when loading state changes', async () => {
|
|
238
|
+
const { loader } = await createLoaderTest({ isLoading: false })
|
|
239
|
+
|
|
240
|
+
const loaderDiv = loader.querySelector('.pkt-loader')
|
|
241
|
+
// Check the aria-busy attribute
|
|
242
|
+
expect(loaderDiv?.getAttribute('aria-busy')).toBe('false')
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
describe('Accessibility', () => {
|
|
247
|
+
test('loader is accessible', async () => {
|
|
248
|
+
const { container } = await createLoaderTest({
|
|
249
|
+
message: 'Loading content',
|
|
250
|
+
content: '<p>Content</p>',
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
const results = await axe(container)
|
|
254
|
+
expect(results).toHaveNoViolations()
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
})
|
|
@@ -94,7 +94,12 @@ export class PktLoader extends PktElement implements IPktLoader {
|
|
|
94
94
|
'pkt-hide': this.isLoading,
|
|
95
95
|
})
|
|
96
96
|
|
|
97
|
-
return html`<div
|
|
97
|
+
return html`<div
|
|
98
|
+
role="status"
|
|
99
|
+
aria-live="polite"
|
|
100
|
+
aria-busy=${this.isLoading ? 'true' : 'false'}
|
|
101
|
+
class=${classes}
|
|
102
|
+
>
|
|
98
103
|
${this.isLoading && this._shouldDisplayLoader
|
|
99
104
|
? html`<div class="pkt-loader__spinner">
|
|
100
105
|
<pkt-icon
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
3
|
+
import { fireEvent } from '@testing-library/dom'
|
|
4
|
+
import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
|
|
5
|
+
import { CustomElementFor } from '../../tests/component-registry'
|
|
6
|
+
import { type IPktMessagebox } from './messagebox'
|
|
7
|
+
import './messagebox'
|
|
8
|
+
|
|
9
|
+
export interface MessageboxTestConfig extends Partial<IPktMessagebox>, BaseTestConfig {}
|
|
10
|
+
|
|
11
|
+
// Use shared framework
|
|
12
|
+
export const createMessageboxTest = async (config: MessageboxTestConfig = {}) => {
|
|
13
|
+
const { container, element } = await createElementTest<
|
|
14
|
+
CustomElementFor<'pkt-messagebox'>,
|
|
15
|
+
MessageboxTestConfig
|
|
16
|
+
>('pkt-messagebox', config)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
container,
|
|
20
|
+
messagebox: element,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
expect.extend(toHaveNoViolations)
|
|
25
|
+
|
|
26
|
+
// Cleanup after each test
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
document.body.innerHTML = ''
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('PktMessagebox', () => {
|
|
32
|
+
describe('Rendering and basic functionality', () => {
|
|
33
|
+
test('renders without errors', async () => {
|
|
34
|
+
const { messagebox } = await createMessageboxTest()
|
|
35
|
+
|
|
36
|
+
expect(messagebox).toBeInTheDocument()
|
|
37
|
+
expect(messagebox).toBeTruthy()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('renders with basic structure', async () => {
|
|
41
|
+
const { messagebox } = await createMessageboxTest({
|
|
42
|
+
title: 'Test Title',
|
|
43
|
+
content: 'Test content',
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
47
|
+
expect(messageboxDiv).toBeInTheDocument()
|
|
48
|
+
|
|
49
|
+
const title = messagebox.querySelector('.pkt-messagebox__title')
|
|
50
|
+
expect(title).toBeInTheDocument()
|
|
51
|
+
expect(title?.textContent).toBe('Test Title')
|
|
52
|
+
|
|
53
|
+
const text = messagebox.querySelector('.pkt-messagebox__text')
|
|
54
|
+
expect(text).toBeInTheDocument()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('renders content correctly', async () => {
|
|
58
|
+
const { messagebox } = await createMessageboxTest({
|
|
59
|
+
content: 'This is the message content',
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const text = messagebox.querySelector('.pkt-messagebox__text')
|
|
63
|
+
expect(text?.textContent).toContain('This is the message content')
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
describe('Properties and attributes', () => {
|
|
68
|
+
test('applies default properties correctly', async () => {
|
|
69
|
+
const { messagebox } = await createMessageboxTest()
|
|
70
|
+
|
|
71
|
+
expect(messagebox.closable).toBe(false)
|
|
72
|
+
expect(messagebox.compact).toBe(false)
|
|
73
|
+
expect(messagebox.title).toBe('')
|
|
74
|
+
expect(messagebox.skin).toBe('beige')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('sets properties correctly', async () => {
|
|
78
|
+
const { messagebox } = await createMessageboxTest({
|
|
79
|
+
closable: true,
|
|
80
|
+
compact: true,
|
|
81
|
+
title: 'Custom Title',
|
|
82
|
+
skin: 'blue',
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
expect(messagebox.closable).toBe(true)
|
|
86
|
+
expect(messagebox.compact).toBe(true)
|
|
87
|
+
expect(messagebox.title).toBe('Custom Title')
|
|
88
|
+
expect(messagebox.skin).toBe('blue')
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
describe('Skin variants', () => {
|
|
93
|
+
test('applies beige skin correctly', async () => {
|
|
94
|
+
const { messagebox } = await createMessageboxTest({ skin: 'beige' })
|
|
95
|
+
|
|
96
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
97
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--beige')).toBe(true)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('applies blue skin correctly', async () => {
|
|
101
|
+
const { messagebox } = await createMessageboxTest({ skin: 'blue' })
|
|
102
|
+
|
|
103
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
104
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--blue')).toBe(true)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('applies red skin correctly', async () => {
|
|
108
|
+
const { messagebox } = await createMessageboxTest({ skin: 'red' })
|
|
109
|
+
|
|
110
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
111
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--red')).toBe(true)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('applies green skin correctly', async () => {
|
|
115
|
+
const { messagebox } = await createMessageboxTest({ skin: 'green' })
|
|
116
|
+
|
|
117
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
118
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--green')).toBe(true)
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
describe('Compact mode', () => {
|
|
123
|
+
test('applies compact class when compact is true', async () => {
|
|
124
|
+
const { messagebox } = await createMessageboxTest({ compact: true })
|
|
125
|
+
|
|
126
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
127
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--compact')).toBe(true)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('does not apply compact class when compact is false', async () => {
|
|
131
|
+
const { messagebox } = await createMessageboxTest({ compact: false })
|
|
132
|
+
|
|
133
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
134
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--compact')).toBe(false)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('Closable functionality', () => {
|
|
139
|
+
test('renders close button when closable is true', async () => {
|
|
140
|
+
const { messagebox } = await createMessageboxTest({ closable: true })
|
|
141
|
+
|
|
142
|
+
const closeButton = messagebox.querySelector('.pkt-messagebox__close button')
|
|
143
|
+
expect(closeButton).toBeInTheDocument()
|
|
144
|
+
|
|
145
|
+
const closeIcon = messagebox.querySelector('pkt-icon[name="close"]')
|
|
146
|
+
expect(closeIcon).toBeInTheDocument()
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('does not render close button when closable is false', async () => {
|
|
150
|
+
const { messagebox } = await createMessageboxTest({ closable: false })
|
|
151
|
+
|
|
152
|
+
const closeButton = messagebox.querySelector('.pkt-messagebox__close')
|
|
153
|
+
expect(closeButton).not.toBeInTheDocument()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('closes messagebox when close button is clicked', async () => {
|
|
157
|
+
const { messagebox } = await createMessageboxTest({ closable: true })
|
|
158
|
+
|
|
159
|
+
const closeButton = messagebox.querySelector('.pkt-messagebox__close button')
|
|
160
|
+
fireEvent.click(closeButton!)
|
|
161
|
+
|
|
162
|
+
await messagebox.updateComplete
|
|
163
|
+
expect(messagebox._isClosed).toBe(true)
|
|
164
|
+
expect(messagebox.classList.contains('pkt-hide')).toBe(true)
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test('dispatches close events when closed', async () => {
|
|
168
|
+
const { messagebox } = await createMessageboxTest({ closable: true })
|
|
169
|
+
|
|
170
|
+
const closeHandler = jest.fn()
|
|
171
|
+
const onCloseHandler = jest.fn()
|
|
172
|
+
messagebox.addEventListener('close', closeHandler)
|
|
173
|
+
messagebox.addEventListener('on-close', onCloseHandler)
|
|
174
|
+
|
|
175
|
+
const closeButton = messagebox.querySelector('.pkt-messagebox__close button')
|
|
176
|
+
fireEvent.click(closeButton!)
|
|
177
|
+
|
|
178
|
+
expect(closeHandler).toHaveBeenCalled()
|
|
179
|
+
expect(onCloseHandler).toHaveBeenCalled()
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
describe('Title functionality', () => {
|
|
184
|
+
test('renders title when provided', async () => {
|
|
185
|
+
const { messagebox } = await createMessageboxTest({ title: 'Important Message' })
|
|
186
|
+
|
|
187
|
+
const title = messagebox.querySelector('.pkt-messagebox__title')
|
|
188
|
+
expect(title).toBeInTheDocument()
|
|
189
|
+
expect(title?.textContent).toBe('Important Message')
|
|
190
|
+
expect(title?.textContent).toBe('Important Message')
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
test('does not render title when empty', async () => {
|
|
194
|
+
const { messagebox } = await createMessageboxTest({ title: '' })
|
|
195
|
+
|
|
196
|
+
const title = messagebox.querySelector('.pkt-messagebox__title')
|
|
197
|
+
expect(title).not.toBeInTheDocument()
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
describe('CSS classes', () => {
|
|
202
|
+
test('applies base messagebox class', async () => {
|
|
203
|
+
const { messagebox } = await createMessageboxTest()
|
|
204
|
+
|
|
205
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
206
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox')).toBe(true)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('applies closable class when closable', async () => {
|
|
210
|
+
const { messagebox } = await createMessageboxTest({ closable: true })
|
|
211
|
+
|
|
212
|
+
const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
|
|
213
|
+
expect(messageboxDiv?.classList.contains('pkt-messagebox--closable')).toBe(true)
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
describe('Accessibility', () => {
|
|
218
|
+
test('basic messagebox is accessible', async () => {
|
|
219
|
+
const { container } = await createMessageboxTest({
|
|
220
|
+
title: 'Accessible Message',
|
|
221
|
+
content: 'This is an accessible message',
|
|
222
|
+
})
|
|
223
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
224
|
+
|
|
225
|
+
const results = await axe(container)
|
|
226
|
+
expect(results).toHaveNoViolations()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('closable messagebox is accessible', async () => {
|
|
230
|
+
const { container } = await createMessageboxTest({
|
|
231
|
+
closable: true,
|
|
232
|
+
title: 'Closable Message',
|
|
233
|
+
content: 'This message can be closed',
|
|
234
|
+
})
|
|
235
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
236
|
+
|
|
237
|
+
const results = await axe(container)
|
|
238
|
+
expect(results).toHaveNoViolations()
|
|
239
|
+
})
|
|
240
|
+
})
|
|
241
|
+
})
|
|
@@ -65,6 +65,7 @@ export class PktMessagebox extends PktElement implements IPktMessagebox {
|
|
|
65
65
|
<button
|
|
66
66
|
@click=${this.close}
|
|
67
67
|
class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only"
|
|
68
|
+
aria-label="Lukk"
|
|
68
69
|
>
|
|
69
70
|
<pkt-icon name="close" class="pkt-link__icon"></pkt-icon>
|
|
70
71
|
</button>
|