Skip to content

Commit 968bfbc

Browse files
committed
Update tests to new pattern in Socail Highlighter
1 parent bc7d496 commit 968bfbc

3 files changed

Lines changed: 244 additions & 168 deletions

File tree

src/components/ContactForm/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
// ContactForm.astro - Reusable contact form component
3-
import GDPRConsent from '@components/GDPR/Consent/index.astro'
3+
import GDPRConsent from '@components/Consent/Checkbox/index.astro'
44
import UploadPlaceholder from './upload.astro'
55
---
66

src/components/Social/Highlighter/__tests__/client.spec.ts

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -120,21 +120,27 @@ describe('Highlighter LoadableScript', () => {
120120

121121
describe('HighlighterElement', () => {
122122
let highlighter: HTMLElement
123-
const queryFromShadow = <T extends Element>(selector: string): T | null =>
124-
(highlighter.shadowRoot?.querySelector(selector) as T | null) ?? null
123+
const queryWithin = <T extends Element>(selector: string): T | null =>
124+
(highlighter.querySelector(selector) as T | null) ?? null
125125

126-
const getFromShadow = <T extends Element>(selector: string): T => {
127-
const element = queryFromShadow<T>(selector)
126+
const getWithin = <T extends Element>(selector: string): T => {
127+
const element = queryWithin<T>(selector)
128128
if (!element) {
129-
throw new Error(`Expected element ${selector} to exist inside Highlighter shadow DOM`)
129+
throw new Error(`Expected element ${selector} to exist inside Highlighter`)
130130
}
131131
return element
132132
}
133133

134134
const getShareButton = (platform: string): HTMLButtonElement =>
135-
getFromShadow<HTMLButtonElement>(`[data-platform="${platform}"]`)
135+
getWithin<HTMLButtonElement>(`.share-button[data-platform="${platform}"]`)
136136

137-
const getShareDialog = () => getFromShadow<HTMLElement>('.share-dialog')
137+
const getShareDialog = () => getWithin<HTMLElement>('.share-dialog')
138+
const getTriggerButton = () => getWithin<HTMLButtonElement>('.highlighter__trigger')
139+
const getWrapper = () => getWithin<HTMLDivElement>('.highlighter__wrapper')
140+
const getHighlightContent = (element: Element = highlighter) =>
141+
element.querySelector<HTMLElement>('.highlighter__content')
142+
const getHighlightText = (element: Element = highlighter) =>
143+
getHighlightContent(element)?.textContent?.trim() ?? ''
138144

139145
const getLatestShareEvent = (
140146
listener: ReturnType<typeof vi.fn>
@@ -172,22 +178,22 @@ describe('HighlighterElement', () => {
172178
})
173179

174180
describe('Rendering', () => {
175-
it('should create shadow DOM', () => {
176-
expect(highlighter.shadowRoot).toBeTruthy()
181+
it('should render in the light DOM', () => {
182+
expect(highlighter.shadowRoot).toBeNull()
177183
})
178184

179185
it('should render share dialog', () => {
180186
expect(getShareDialog()).toBeTruthy()
181187
})
182188

183189
it('should render all platform buttons', () => {
184-
const buttons = highlighter.shadowRoot?.querySelectorAll('.share-button')
190+
const buttons = highlighter.querySelectorAll('.share-button')
185191
expect(buttons).toHaveLength(6) // 5 platforms + copy button
186192
})
187193

188194
it('should render platform buttons in correct order', () => {
189-
const buttons = highlighter.shadowRoot?.querySelectorAll('.share-button')
190-
const platforms = Array.from(buttons || [])
195+
const buttons = highlighter.querySelectorAll('.share-button')
196+
const platforms = Array.from(buttons)
191197
.slice(0, 4) // First 4 are social platforms
192198
.map(btn => btn.getAttribute('data-platform'))
193199

@@ -247,17 +253,17 @@ describe('HighlighterElement', () => {
247253

248254
describe('Keyboard Navigation', () => {
249255
it('should show dialog on Enter key', async () => {
250-
// Trigger Enter key on the host element (using keyup for accessibility)
256+
const trigger = getTriggerButton()
251257
const event = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true })
252-
highlighter.dispatchEvent(event)
258+
trigger.dispatchEvent(event)
253259

254260
expect(getShareDialog().getAttribute('aria-hidden')).toBe('false')
255261
})
256262

257263
it('should show dialog on Space key', async () => {
258-
// Trigger Space key on the host element (using keyup for accessibility)
264+
const trigger = getTriggerButton()
259265
const event = new KeyboardEvent('keyup', { key: ' ', bubbles: true })
260-
highlighter.dispatchEvent(event)
266+
trigger.dispatchEvent(event)
261267

262268
expect(getShareDialog().getAttribute('aria-hidden')).toBe('false')
263269
})
@@ -267,35 +273,35 @@ describe('HighlighterElement', () => {
267273
highlighter.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }))
268274
expect(getShareDialog().getAttribute('aria-hidden')).toBe('false')
269275

270-
// Trigger Escape key (using keyup for accessibility)
276+
// Trigger Escape key on wrapper (using keyup for accessibility)
277+
const wrapper = getWrapper()
271278
const event = new KeyboardEvent('keyup', { key: 'Escape', bubbles: true })
272-
document.dispatchEvent(event)
279+
wrapper.dispatchEvent(event)
273280

274281
expect(getShareDialog().getAttribute('aria-hidden')).toBe('true')
275282
})
276283
})
277284

278285
describe('Text Extraction', () => {
279286
it('should extract text from slot', () => {
280-
const text = highlighter.textContent?.trim()
281-
expect(text).toBe('Test shareable content')
287+
expect(getHighlightText()).toBe('Test shareable content')
282288
})
283289

284-
it('should handle empty content', () => {
290+
it('should handle empty content', async () => {
285291
const emptyHighlighter = document.createElement('highlighter-element')
286292
document.body.appendChild(emptyHighlighter)
287293

288-
const text = emptyHighlighter.textContent?.trim()
289-
expect(text).toBe('')
294+
await flushMicrotasks()
295+
expect(getHighlightText(emptyHighlighter)).toBe('')
290296
})
291297

292-
it('should handle nested HTML', () => {
298+
it('should handle nested HTML', async () => {
293299
const htmlHighlighter = document.createElement('highlighter-element')
294300
htmlHighlighter.innerHTML = '<strong>Bold</strong> and <em>italic</em> text'
295301
document.body.appendChild(htmlHighlighter)
296302

297-
const text = htmlHighlighter.textContent?.trim()
298-
expect(text).toBe('Bold and italic text')
303+
await flushMicrotasks()
304+
expect(getHighlightText(htmlHighlighter)).toBe('Bold and italic text')
299305
})
300306
})
301307

@@ -358,9 +364,7 @@ describe('HighlighterElement', () => {
358364

359365
await flushMicrotasks()
360366

361-
const twitterButton = specialHighlighter.shadowRoot?.querySelector('[data-platform="twitter"]') as
362-
| HTMLButtonElement
363-
| null
367+
const twitterButton = specialHighlighter.querySelector<HTMLButtonElement>('[data-platform="twitter"]')
364368
if (!twitterButton) {
365369
throw new Error('twitter button missing on special highlighter')
366370
}
@@ -482,25 +486,26 @@ describe('HighlighterElement', () => {
482486
it('should have proper ARIA attributes on container', () => {
483487
// The host element is the container
484488
expect(highlighter.getAttribute('role')).toBeNull() // Not set by default on custom elements
485-
expect(highlighter.getAttribute('tabindex')).toBe('0')
489+
expect(highlighter.getAttribute('tabindex')).toBeNull()
486490
expect(highlighter.getAttribute('aria-label')).toBeTruthy()
491+
492+
const trigger = getTriggerButton()
493+
expect(trigger.getAttribute('type')).toBe('button')
494+
expect(trigger.getAttribute('aria-label')).toBe('Share this quote')
487495
})
488496

489497
it('should have proper ARIA labels on platform buttons', () => {
490-
const twitterButton = highlighter.shadowRoot?.querySelector('[data-platform="twitter"]')
491-
expect(twitterButton?.getAttribute('aria-label')).toBe('Share on X (Twitter)')
492-
493-
const linkedinButton = highlighter.shadowRoot?.querySelector('[data-platform="linkedin"]')
494-
expect(linkedinButton?.getAttribute('aria-label')).toBe('Share on LinkedIn')
498+
expect(getShareButton('twitter').getAttribute('aria-label')).toBe('Share on X (Twitter)')
499+
expect(getShareButton('linkedin').getAttribute('aria-label')).toBe('Share on LinkedIn')
495500
})
496501

497502
it('should toggle aria-hidden on dialog', () => {
498-
const dialog = highlighter.shadowRoot?.querySelector('.share-dialog')
499-
expect(dialog?.getAttribute('aria-hidden')).toBe('true')
503+
const dialog = getShareDialog()
504+
expect(dialog.getAttribute('aria-hidden')).toBe('true')
500505

501506
highlighter.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }))
502507

503-
expect(dialog?.getAttribute('aria-hidden')).toBe('false')
508+
expect(dialog.getAttribute('aria-hidden')).toBe('false')
504509
})
505510
})
506511

@@ -513,19 +518,13 @@ describe('HighlighterElement', () => {
513518
expect(() => button.click()).not.toThrow()
514519
})
515520

516-
it('should handle missing shadowRoot gracefully', () => {
517-
// This is more for coverage - should not happen in practice
518-
const element = document.createElement('div')
519-
expect(element.shadowRoot).toBeNull()
520-
})
521-
522-
it('should handle very long text content', () => {
521+
it('should handle very long text content', async () => {
523522
const longHighlighter = document.createElement('highlighter-element')
524523
longHighlighter.textContent = 'A'.repeat(1000)
525524
document.body.appendChild(longHighlighter)
526525

527-
const text = longHighlighter.textContent?.trim()
528-
expect(text).toHaveLength(1000)
526+
await flushMicrotasks()
527+
expect(getHighlightText(longHighlighter)).toHaveLength(1000)
529528
})
530529
})
531530
})

0 commit comments

Comments
 (0)