@oslokommune/punkt-elements 13.4.0 → 13.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/{alert-B0OUR9oD.js → alert-B07oUpkq.js} +5 -4
- package/dist/{alert-BH0lJ2ny.cjs → alert-DQNBDKjT.cjs} +1 -1
- package/dist/{backlink-B13JTp9D.js → backlink-C2jbzu0U.js} +16 -15
- package/dist/backlink-JbBNi3qg.cjs +13 -0
- package/dist/{button-CDocR7iN.cjs → button-B8rdtaHB.cjs} +1 -1
- package/dist/{button-DrrEvUy9.js → button-DhispFOY.js} +1 -0
- package/dist/{consent-CftYu8Di.js → consent-BpcQFvbi.js} +1 -1
- package/dist/{consent-DrS71kvz.cjs → consent-hYeFWNFr.cjs} +1 -1
- package/dist/pkt-alert.cjs +1 -1
- package/dist/pkt-alert.js +1 -1
- package/dist/pkt-backlink.cjs +1 -1
- package/dist/pkt-backlink.js +1 -1
- package/dist/pkt-button.cjs +1 -1
- package/dist/pkt-button.js +1 -1
- package/dist/pkt-consent.cjs +1 -1
- package/dist/pkt-consent.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +4 -4
- package/package.json +2 -2
- package/src/components/accordion/accordion.test.ts +0 -4
- package/src/components/alert/alert.test.ts +348 -0
- package/src/components/alert/alert.ts +1 -0
- package/src/components/backlink/backlink.test.ts +286 -0
- package/src/components/backlink/backlink.ts +5 -3
- package/src/components/button/button.test.ts +514 -0
- package/src/components/button/button.ts +2 -0
- package/dist/backlink-C5jQRMwJ.cjs +0 -13
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
3
|
+
import { fireEvent } from '@testing-library/dom'
|
|
4
|
+
|
|
5
|
+
expect.extend(toHaveNoViolations)
|
|
6
|
+
|
|
7
|
+
import './button'
|
|
8
|
+
import { PktButton } from './button' // For type checking
|
|
9
|
+
|
|
10
|
+
const waitForCustomElements = async () => {
|
|
11
|
+
await Promise.all([
|
|
12
|
+
customElements.whenDefined('pkt-button'),
|
|
13
|
+
customElements.whenDefined('pkt-icon'),
|
|
14
|
+
])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Helper function to create button markup
|
|
18
|
+
const createButton = async (buttonProps = '', content = 'Test Button') => {
|
|
19
|
+
const container = document.createElement('div')
|
|
20
|
+
container.innerHTML = `
|
|
21
|
+
<pkt-button ${buttonProps}>
|
|
22
|
+
${content}
|
|
23
|
+
</pkt-button>
|
|
24
|
+
`
|
|
25
|
+
document.body.appendChild(container)
|
|
26
|
+
await waitForCustomElements()
|
|
27
|
+
return container
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Cleanup after each test
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
document.body.innerHTML = ''
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('PktButton', () => {
|
|
36
|
+
describe('Rendering and basic functionality', () => {
|
|
37
|
+
test('renders without errors', async () => {
|
|
38
|
+
const container = await createButton()
|
|
39
|
+
|
|
40
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
41
|
+
expect(pktButton).toBeInTheDocument()
|
|
42
|
+
|
|
43
|
+
await pktButton.updateComplete
|
|
44
|
+
expect(pktButton).toBeTruthy()
|
|
45
|
+
|
|
46
|
+
const button = pktButton.querySelector('button')
|
|
47
|
+
expect(button).toBeInTheDocument()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('renders with correct structure', async () => {
|
|
51
|
+
const container = await createButton('variant="icon-left" icon-name="user"', 'Click Me')
|
|
52
|
+
|
|
53
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
54
|
+
await pktButton.updateComplete
|
|
55
|
+
|
|
56
|
+
const button = pktButton.querySelector('button')
|
|
57
|
+
const icon = button?.querySelector('pkt-icon')
|
|
58
|
+
const textSpan = button?.querySelector('.pkt-btn__text')
|
|
59
|
+
|
|
60
|
+
expect(button).toHaveClass('pkt-btn')
|
|
61
|
+
expect(icon).toHaveClass('pkt-btn__icon')
|
|
62
|
+
expect(textSpan).toHaveClass('pkt-btn__text')
|
|
63
|
+
expect(textSpan?.textContent?.trim()).toContain('Click Me')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('renders text correctly', async () => {
|
|
67
|
+
const container = await createButton('', 'Button Text Content')
|
|
68
|
+
|
|
69
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
70
|
+
await pktButton.updateComplete
|
|
71
|
+
|
|
72
|
+
const textSpan = pktButton.querySelector('.pkt-btn__text')
|
|
73
|
+
expect(textSpan).toBeInTheDocument()
|
|
74
|
+
expect(textSpan?.textContent?.trim()).toContain('Button Text Content')
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
describe('Properties and attributes', () => {
|
|
79
|
+
test('applies default properties correctly', async () => {
|
|
80
|
+
const container = await createButton()
|
|
81
|
+
|
|
82
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
83
|
+
await pktButton.updateComplete
|
|
84
|
+
|
|
85
|
+
expect(pktButton.size).toBe('medium')
|
|
86
|
+
expect(pktButton.skin).toBe('primary')
|
|
87
|
+
expect(pktButton.variant).toBe('label-only')
|
|
88
|
+
expect(pktButton.type).toBe('button')
|
|
89
|
+
expect(pktButton.mode).toBe('light')
|
|
90
|
+
expect(pktButton.disabled).toBe(false)
|
|
91
|
+
expect(pktButton.isLoading).toBe(false)
|
|
92
|
+
|
|
93
|
+
const button = pktButton.querySelector('button')
|
|
94
|
+
expect(button).toHaveClass('pkt-btn')
|
|
95
|
+
expect(button).toHaveClass('pkt-btn--medium')
|
|
96
|
+
expect(button).toHaveClass('pkt-btn--primary')
|
|
97
|
+
expect(button).toHaveClass('pkt-btn--label-only')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('applies different size properties correctly', async () => {
|
|
101
|
+
const sizes = ['small', 'medium', 'large'] as const
|
|
102
|
+
|
|
103
|
+
for (const size of sizes) {
|
|
104
|
+
const container = await createButton(`size="${size}"`)
|
|
105
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
106
|
+
await pktButton.updateComplete
|
|
107
|
+
|
|
108
|
+
expect(pktButton.size).toBe(size)
|
|
109
|
+
|
|
110
|
+
const button = pktButton.querySelector('button')
|
|
111
|
+
expect(button).toHaveClass(`pkt-btn--${size}`)
|
|
112
|
+
|
|
113
|
+
// Cleanup for next iteration
|
|
114
|
+
container.remove()
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test('applies different skin properties correctly', async () => {
|
|
119
|
+
const skins = ['primary', 'secondary', 'tertiary'] as const
|
|
120
|
+
|
|
121
|
+
for (const skin of skins) {
|
|
122
|
+
const container = await createButton(`skin="${skin}"`)
|
|
123
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
124
|
+
await pktButton.updateComplete
|
|
125
|
+
|
|
126
|
+
expect(pktButton.skin).toBe(skin)
|
|
127
|
+
|
|
128
|
+
const button = pktButton.querySelector('button')
|
|
129
|
+
expect(button).toHaveClass(`pkt-btn--${skin}`)
|
|
130
|
+
|
|
131
|
+
// Cleanup for next iteration
|
|
132
|
+
container.remove()
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('applies different variant properties correctly', async () => {
|
|
137
|
+
const variants = [
|
|
138
|
+
'label-only',
|
|
139
|
+
'icon-left',
|
|
140
|
+
'icon-right',
|
|
141
|
+
'icon-only',
|
|
142
|
+
'icons-right-and-left',
|
|
143
|
+
] as const
|
|
144
|
+
|
|
145
|
+
for (const variant of variants) {
|
|
146
|
+
const container = await createButton(
|
|
147
|
+
`variant="${variant}" icon-name="user" second-icon-name="star"`,
|
|
148
|
+
)
|
|
149
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
150
|
+
await pktButton.updateComplete
|
|
151
|
+
|
|
152
|
+
expect(pktButton.variant).toBe(variant)
|
|
153
|
+
|
|
154
|
+
const button = pktButton.querySelector('button')
|
|
155
|
+
expect(button).toHaveClass(`pkt-btn--${variant}`)
|
|
156
|
+
|
|
157
|
+
// Check icon rendering based on variant
|
|
158
|
+
const icons = button?.querySelectorAll('pkt-icon:not(.pkt-btn__spinner)')
|
|
159
|
+
if (variant === 'label-only') {
|
|
160
|
+
expect(icons).toHaveLength(0)
|
|
161
|
+
} else if (variant === 'icons-right-and-left') {
|
|
162
|
+
expect(icons).toHaveLength(2)
|
|
163
|
+
} else {
|
|
164
|
+
expect(icons).toHaveLength(1)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Cleanup for next iteration
|
|
168
|
+
container.remove()
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
test('applies different color properties correctly', async () => {
|
|
173
|
+
const colors = ['blue', 'green', 'red', 'yellow'] as const
|
|
174
|
+
|
|
175
|
+
for (const color of colors) {
|
|
176
|
+
const container = await createButton(`color="${color}"`)
|
|
177
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
178
|
+
await pktButton.updateComplete
|
|
179
|
+
|
|
180
|
+
expect(pktButton.color).toBe(color)
|
|
181
|
+
|
|
182
|
+
const button = pktButton.querySelector('button')
|
|
183
|
+
expect(button).toHaveClass(`pkt-btn--${color}`)
|
|
184
|
+
|
|
185
|
+
// Cleanup for next iteration
|
|
186
|
+
container.remove()
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('handles type property correctly', async () => {
|
|
191
|
+
const types = ['button', 'submit', 'reset'] as const
|
|
192
|
+
|
|
193
|
+
for (const type of types) {
|
|
194
|
+
const container = await createButton(`type="${type}"`)
|
|
195
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
196
|
+
await pktButton.updateComplete
|
|
197
|
+
|
|
198
|
+
expect(pktButton.type).toBe(type)
|
|
199
|
+
|
|
200
|
+
const button = pktButton.querySelector('button')
|
|
201
|
+
expect(button?.getAttribute('type')).toBe(type)
|
|
202
|
+
|
|
203
|
+
// Cleanup for next iteration
|
|
204
|
+
container.remove()
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
test('handles icon properties correctly', async () => {
|
|
209
|
+
const container = await createButton('variant="icon-left" icon-name="user"')
|
|
210
|
+
|
|
211
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
212
|
+
await pktButton.updateComplete
|
|
213
|
+
|
|
214
|
+
expect(pktButton.iconName).toBe('user')
|
|
215
|
+
|
|
216
|
+
const icon = pktButton.querySelector('pkt-icon:not(.pkt-btn__spinner)')
|
|
217
|
+
expect(icon?.getAttribute('name')).toBe('user')
|
|
218
|
+
expect(icon).toHaveClass('pkt-btn__icon')
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('handles second icon for icons-right-and-left variant', async () => {
|
|
222
|
+
const container = await createButton('variant="icons-right-and-left"')
|
|
223
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
224
|
+
|
|
225
|
+
// Set both icon names as properties
|
|
226
|
+
pktButton.iconName = 'home'
|
|
227
|
+
pktButton.secondIconName = 'star'
|
|
228
|
+
await pktButton.updateComplete
|
|
229
|
+
|
|
230
|
+
expect(pktButton.iconName).toBe('home')
|
|
231
|
+
expect(pktButton.secondIconName).toBe('star')
|
|
232
|
+
|
|
233
|
+
const icons = pktButton.querySelectorAll('pkt-icon:not(.pkt-btn__spinner)')
|
|
234
|
+
expect(icons).toHaveLength(2)
|
|
235
|
+
expect(icons[0]?.getAttribute('name')).toBe('home')
|
|
236
|
+
expect(icons[1]?.getAttribute('name')).toBe('star')
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
describe('Disabled state', () => {
|
|
241
|
+
test('handles disabled property correctly', async () => {
|
|
242
|
+
const container = await createButton('disabled')
|
|
243
|
+
|
|
244
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
245
|
+
await pktButton.updateComplete
|
|
246
|
+
|
|
247
|
+
expect(pktButton.disabled).toBe(true)
|
|
248
|
+
|
|
249
|
+
const button = pktButton.querySelector('button')
|
|
250
|
+
expect(button).toHaveClass('pkt-btn--disabled')
|
|
251
|
+
expect(button?.hasAttribute('disabled')).toBe(true)
|
|
252
|
+
expect(button?.getAttribute('aria-disabled')).toBe('true')
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
test('prevents click events when disabled', async () => {
|
|
256
|
+
const container = await createButton('disabled')
|
|
257
|
+
const clickSpy = jest.fn()
|
|
258
|
+
|
|
259
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
260
|
+
await pktButton.updateComplete
|
|
261
|
+
|
|
262
|
+
pktButton.addEventListener('click', clickSpy)
|
|
263
|
+
|
|
264
|
+
const button = pktButton.querySelector('button')
|
|
265
|
+
fireEvent.click(button!)
|
|
266
|
+
|
|
267
|
+
expect(clickSpy).not.toHaveBeenCalled()
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
test('prevents keyboard events when disabled', async () => {
|
|
271
|
+
const container = await createButton('disabled')
|
|
272
|
+
const clickSpy = jest.fn()
|
|
273
|
+
|
|
274
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
275
|
+
await pktButton.updateComplete
|
|
276
|
+
|
|
277
|
+
pktButton.addEventListener('click', clickSpy)
|
|
278
|
+
|
|
279
|
+
const button = pktButton.querySelector('button')
|
|
280
|
+
fireEvent.keyDown(button!, { key: 'Enter' })
|
|
281
|
+
fireEvent.keyDown(button!, { key: ' ' })
|
|
282
|
+
|
|
283
|
+
expect(clickSpy).not.toHaveBeenCalled()
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
test('converts string "false" to boolean false for disabled', async () => {
|
|
287
|
+
const container = await createButton('disabled="false"')
|
|
288
|
+
|
|
289
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
290
|
+
await pktButton.updateComplete
|
|
291
|
+
|
|
292
|
+
expect(pktButton.disabled).toBe(false)
|
|
293
|
+
|
|
294
|
+
const button = pktButton.querySelector('button')
|
|
295
|
+
expect(button).not.toHaveClass('pkt-btn--disabled')
|
|
296
|
+
expect(button?.hasAttribute('disabled')).toBe(false)
|
|
297
|
+
})
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
describe('Loading state', () => {
|
|
301
|
+
test('handles isLoading property correctly', async () => {
|
|
302
|
+
const container = await createButton()
|
|
303
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
304
|
+
|
|
305
|
+
// Set isLoading as a property
|
|
306
|
+
pktButton.isLoading = true
|
|
307
|
+
await pktButton.updateComplete
|
|
308
|
+
|
|
309
|
+
expect(pktButton.isLoading).toBe(true)
|
|
310
|
+
|
|
311
|
+
const button = pktButton.querySelector('button')
|
|
312
|
+
expect(button).toHaveClass('pkt-btn--isLoading')
|
|
313
|
+
expect(button?.getAttribute('aria-busy')).toBe('true')
|
|
314
|
+
expect(button?.getAttribute('aria-disabled')).toBe('true')
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
test('renders loading spinner when isLoading is true', async () => {
|
|
318
|
+
const container = await createButton()
|
|
319
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
320
|
+
|
|
321
|
+
// Set isLoading as a property
|
|
322
|
+
pktButton.isLoading = true
|
|
323
|
+
await pktButton.updateComplete
|
|
324
|
+
|
|
325
|
+
const spinner = pktButton.querySelector('.pkt-btn__spinner')
|
|
326
|
+
expect(spinner).toBeInTheDocument()
|
|
327
|
+
expect(spinner?.getAttribute('name')).toBe('spinner-blue')
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
test('prevents click events when loading', async () => {
|
|
331
|
+
const container = await createButton()
|
|
332
|
+
const clickSpy = jest.fn()
|
|
333
|
+
|
|
334
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
335
|
+
|
|
336
|
+
// Set isLoading as a property
|
|
337
|
+
pktButton.isLoading = true
|
|
338
|
+
await pktButton.updateComplete
|
|
339
|
+
|
|
340
|
+
pktButton.addEventListener('click', clickSpy)
|
|
341
|
+
|
|
342
|
+
const button = pktButton.querySelector('button')
|
|
343
|
+
fireEvent.click(button!)
|
|
344
|
+
|
|
345
|
+
expect(clickSpy).not.toHaveBeenCalled()
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
test('uses custom loading animation path', async () => {
|
|
349
|
+
const customPath = 'https://custom.example.com/animations/'
|
|
350
|
+
const container = await createButton('isLoading')
|
|
351
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
352
|
+
|
|
353
|
+
pktButton.loadingAnimationPath = customPath
|
|
354
|
+
await pktButton.updateComplete
|
|
355
|
+
|
|
356
|
+
expect(pktButton.loadingAnimationPath).toBe(customPath)
|
|
357
|
+
|
|
358
|
+
const spinner = pktButton.querySelector('.pkt-btn__spinner')
|
|
359
|
+
expect(spinner?.getAttribute('path')).toBe(customPath)
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
test('converts string "false" to boolean false for isLoading', async () => {
|
|
363
|
+
const container = await createButton('isLoading="false"')
|
|
364
|
+
|
|
365
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
366
|
+
await pktButton.updateComplete
|
|
367
|
+
|
|
368
|
+
expect(pktButton.isLoading).toBe(false)
|
|
369
|
+
|
|
370
|
+
const button = pktButton.querySelector('button')
|
|
371
|
+
expect(button).not.toHaveClass('pkt-btn--isLoading')
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
describe('Form integration', () => {
|
|
376
|
+
test('handles form attribute correctly', async () => {
|
|
377
|
+
const container = await createButton('form="test-form" type="submit"')
|
|
378
|
+
|
|
379
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
380
|
+
await pktButton.updateComplete
|
|
381
|
+
|
|
382
|
+
expect(pktButton.form).toBe('test-form')
|
|
383
|
+
|
|
384
|
+
const button = pktButton.querySelector('button')
|
|
385
|
+
expect(button?.getAttribute('form')).toBe('test-form')
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
test('works as submit button', async () => {
|
|
389
|
+
const container = await createButton('type="submit"')
|
|
390
|
+
|
|
391
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
392
|
+
await pktButton.updateComplete
|
|
393
|
+
|
|
394
|
+
const button = pktButton.querySelector('button')
|
|
395
|
+
expect(button?.getAttribute('type')).toBe('submit')
|
|
396
|
+
})
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
describe('Click functionality', () => {
|
|
400
|
+
test('allows click events when not disabled or loading', async () => {
|
|
401
|
+
const container = await createButton()
|
|
402
|
+
const clickSpy = jest.fn()
|
|
403
|
+
|
|
404
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
405
|
+
await pktButton.updateComplete
|
|
406
|
+
|
|
407
|
+
pktButton.addEventListener('click', clickSpy)
|
|
408
|
+
|
|
409
|
+
const button = pktButton.querySelector('button')
|
|
410
|
+
fireEvent.click(button!)
|
|
411
|
+
|
|
412
|
+
expect(clickSpy).toHaveBeenCalledTimes(1)
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
test('allows keyboard activation when not disabled or loading', async () => {
|
|
416
|
+
const container = await createButton()
|
|
417
|
+
const clickSpy = jest.fn()
|
|
418
|
+
|
|
419
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
420
|
+
await pktButton.updateComplete
|
|
421
|
+
|
|
422
|
+
pktButton.addEventListener('click', clickSpy)
|
|
423
|
+
|
|
424
|
+
const button = pktButton.querySelector('button')
|
|
425
|
+
fireEvent.keyDown(button!, { key: 'Enter' })
|
|
426
|
+
|
|
427
|
+
// Note: Native button handles Enter key, so we just test that events aren't prevented
|
|
428
|
+
// The actual click event would be triggered by the browser
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
describe('Accessibility', () => {
|
|
433
|
+
test('has correct ARIA attributes', async () => {
|
|
434
|
+
const container = await createButton('disabled')
|
|
435
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
436
|
+
|
|
437
|
+
// Set isLoading as a property
|
|
438
|
+
pktButton.isLoading = true
|
|
439
|
+
await pktButton.updateComplete
|
|
440
|
+
|
|
441
|
+
const button = pktButton.querySelector('button')
|
|
442
|
+
|
|
443
|
+
expect(button?.getAttribute('aria-disabled')).toBe('true')
|
|
444
|
+
expect(button?.getAttribute('aria-busy')).toBe('true')
|
|
445
|
+
expect(button?.hasAttribute('disabled')).toBe(true)
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
test('provides semantic button structure', async () => {
|
|
449
|
+
const container = await createButton()
|
|
450
|
+
|
|
451
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
452
|
+
await pktButton.updateComplete
|
|
453
|
+
|
|
454
|
+
const button = pktButton.querySelector('button')
|
|
455
|
+
|
|
456
|
+
expect(button).toBeInTheDocument()
|
|
457
|
+
expect(button?.tagName.toLowerCase()).toBe('button')
|
|
458
|
+
expect(button?.getAttribute('type')).toBe('button')
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
test('renders with no WCAG errors with axe - default button', async () => {
|
|
462
|
+
const container = await createButton('', 'Click me')
|
|
463
|
+
|
|
464
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
465
|
+
await pktButton.updateComplete
|
|
466
|
+
|
|
467
|
+
const results = await axe(container)
|
|
468
|
+
expect(results).toHaveNoViolations()
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
test('renders with no WCAG errors with axe - icon button', async () => {
|
|
472
|
+
const container = await createButton(
|
|
473
|
+
'variant="icon-left" icon-name="user" skin="secondary"',
|
|
474
|
+
'User Profile',
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
478
|
+
await pktButton.updateComplete
|
|
479
|
+
|
|
480
|
+
const results = await axe(container)
|
|
481
|
+
expect(results).toHaveNoViolations()
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
test('renders with no WCAG errors with axe - disabled button', async () => {
|
|
485
|
+
const container = await createButton('disabled', 'Disabled Button')
|
|
486
|
+
|
|
487
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
488
|
+
await pktButton.updateComplete
|
|
489
|
+
|
|
490
|
+
const results = await axe(container)
|
|
491
|
+
expect(results).toHaveNoViolations()
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
test('renders with no WCAG errors with axe - loading button', async () => {
|
|
495
|
+
const container = await createButton('isLoading', 'Loading...')
|
|
496
|
+
|
|
497
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
498
|
+
await pktButton.updateComplete
|
|
499
|
+
|
|
500
|
+
const results = await axe(container)
|
|
501
|
+
expect(results).toHaveNoViolations()
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
test('renders with no WCAG errors with axe - submit button', async () => {
|
|
505
|
+
const container = await createButton('type="submit" color="green"', 'Submit Form')
|
|
506
|
+
|
|
507
|
+
const pktButton = container.querySelector('pkt-button') as PktButton
|
|
508
|
+
await pktButton.updateComplete
|
|
509
|
+
|
|
510
|
+
const results = await axe(container)
|
|
511
|
+
expect(results).toHaveNoViolations()
|
|
512
|
+
})
|
|
513
|
+
})
|
|
514
|
+
})
|
|
@@ -7,6 +7,8 @@ import { classMap } from 'lit/directives/class-map.js'
|
|
|
7
7
|
import { ifDefined } from 'lit/directives/if-defined.js'
|
|
8
8
|
import { createRef, Ref, ref } from 'lit/directives/ref.js'
|
|
9
9
|
|
|
10
|
+
import '@/components/icon'
|
|
11
|
+
|
|
10
12
|
// Allow global override of animation assets path
|
|
11
13
|
window.pktAnimationPath =
|
|
12
14
|
window.pktAnimationPath || 'https://punkt-cdn.oslo.kommune.no/latest/animations/'
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";const i=require("./element-6DBpyGQm.cjs"),c=require("./if-defined-Cni-RHLS.cjs");var p=Object.defineProperty,o=Object.getOwnPropertyDescriptor,n=(k,t,a,r)=>{for(var e=r>1?void 0:r?o(t,a):t,l=k.length-1,s;l>=0;l--)(s=k[l])&&(e=(r?s(t,a,e):s(e))||e);return r&&e&&p(t,a,e),e};exports.PktBackLink=class extends i.PktElement{constructor(){super(...arguments),this.href="",this.text="Forsiden",this.ariaLabel=""}attributeChangedCallback(t,a,r){t==="arialabel"&&this.removeAttribute("arialabel"),t==="href"&&this.removeAttribute("href"),t==="text"&&this.removeAttribute("text"),super.attributeChangedCallback(t,a,r)}render(){return i.x`<nav
|
|
2
|
-
class="pkt-back-link"
|
|
3
|
-
aria-label=${this.ariaLabel||"Gå tilbake til forrige side"}
|
|
4
|
-
>
|
|
5
|
-
<a href=${c.o(this.href||"/")} class="pkt-link pkt-link--icon-left"
|
|
6
|
-
><pkt-icon
|
|
7
|
-
class="pkt-back-link__icon pkt-icon pkt-link__icon"
|
|
8
|
-
name="chevron-thin-left"
|
|
9
|
-
aria-hidden="true"
|
|
10
|
-
></pkt-icon
|
|
11
|
-
><span class="pkt-back-link__text">${this.text}</span></a
|
|
12
|
-
>
|
|
13
|
-
</nav>`}};n([i.n({type:String,reflect:!0})],exports.PktBackLink.prototype,"href",2);n([i.n({type:String,reflect:!0})],exports.PktBackLink.prototype,"text",2);n([i.n({type:String,reflect:!0})],exports.PktBackLink.prototype,"ariaLabel",2);exports.PktBackLink=n([i.t("pkt-backlink")],exports.PktBackLink);
|