Skip to content

Commit af7f470

Browse files
committed
Refactor Contact Form tests to new webComponent pattern
1 parent bb39daa commit af7f470

14 files changed

Lines changed: 528 additions & 633 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
import ContactForm from '../../../index.astro'
3+
---
4+
5+
<ContactForm />
Lines changed: 48 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,70 @@
1-
// @vitest-environment happy-dom
2-
import { describe, it, expect, beforeEach } from 'vitest'
1+
// @vitest-environment node
2+
import { describe, it, expect } from 'vitest'
33
import {
44
clearFieldFeedback,
55
hideErrorBanner,
66
initLabelHandlers,
77
showErrorBanner,
88
showFieldFeedback,
99
} from '@components/Forms/Contact/client/feedback'
10-
import type { ContactFormFields, FieldElements } from '@components/Forms/Contact/client/@types'
11-
12-
const createField = <T extends HTMLInputElement | HTMLTextAreaElement>(
13-
input: T,
14-
id: string,
15-
): FieldElements<T> => {
16-
const label = document.createElement('label')
17-
label.htmlFor = id
18-
const feedback = document.createElement('p')
19-
feedback.dataset['fieldError'] = id
20-
feedback.classList.add('hidden')
21-
return { input, label, feedback }
22-
}
23-
24-
const createFields = (): ContactFormFields => {
25-
const nameInput = Object.assign(document.createElement('input'), {
26-
id: 'name',
27-
value: '',
28-
})
29-
const emailInput = Object.assign(document.createElement('input'), {
30-
id: 'email',
31-
type: 'email',
32-
value: '',
33-
})
34-
const messageInput = Object.assign(document.createElement('textarea'), {
35-
id: 'message',
36-
value: '',
37-
})
38-
39-
return {
40-
name: createField(nameInput, 'name'),
41-
email: createField(emailInput, 'email'),
42-
message: createField(messageInput, 'message'),
43-
}
44-
}
10+
import { renderContactForm } from './testUtils'
4511

4612
describe('ContactForm feedback helpers', () => {
47-
beforeEach(() => {
48-
document.body.innerHTML = ''
13+
it('toggles error banner visibility', async () => {
14+
await renderContactForm(({ elements }) => {
15+
showErrorBanner(elements.formErrorBanner)
16+
expect(elements.formErrorBanner.classList.contains('hidden')).toBe(false)
17+
18+
hideErrorBanner(elements.formErrorBanner)
19+
expect(elements.formErrorBanner.classList.contains('hidden')).toBe(true)
20+
})
4921
})
5022

51-
it('toggles error banner visibility', () => {
52-
const banner = document.createElement('div')
53-
banner.classList.add('hidden')
54-
55-
showErrorBanner(banner)
56-
expect(banner.classList.contains('hidden')).toBe(false)
57-
58-
hideErrorBanner(banner)
59-
expect(banner.classList.contains('hidden')).toBe(true)
60-
})
61-
62-
it('shows and clears error feedback for a field', () => {
63-
const field = createField(Object.assign(document.createElement('input'), { id: 'email' }), 'email')
64-
field.feedback.style.color = ''
65-
66-
showFieldFeedback(field, 'Invalid email', 'error')
67-
expect(field.feedback.textContent).toBe('Invalid email')
68-
expect(field.feedback.classList.contains('hidden')).toBe(false)
69-
expect(field.feedback.dataset['state']).toBe('error')
70-
expect(field.feedback.style.color).toBe('var(--color-danger)')
71-
expect(field.input.classList.contains('error')).toBe(true)
72-
73-
clearFieldFeedback(field)
74-
expect(field.feedback.textContent).toBe('')
75-
expect(field.feedback.classList.contains('hidden')).toBe(true)
76-
expect(field.feedback.dataset['state']).toBeUndefined()
77-
expect(field.feedback.getAttribute('style')).toBeNull()
78-
expect(field.input.classList.contains('error')).toBe(false)
23+
it('shows and clears error feedback for a field', async () => {
24+
await renderContactForm(({ elements }) => {
25+
const field = elements.fields.email
26+
27+
showFieldFeedback(field, 'Invalid email', 'error')
28+
expect(field.feedback.textContent).toBe('Invalid email')
29+
expect(field.feedback.classList.contains('hidden')).toBe(false)
30+
expect(field.feedback.dataset['state']).toBe('error')
31+
expect(field.feedback.style.color).toBe('var(--color-danger)')
32+
expect(field.input.classList.contains('error')).toBe(true)
33+
34+
clearFieldFeedback(field)
35+
expect(field.feedback.textContent).toBe('')
36+
expect(field.feedback.classList.contains('hidden')).toBe(true)
37+
expect(field.feedback.dataset['state']).toBeUndefined()
38+
expect(field.feedback.getAttribute('style')).toBeNull()
39+
expect(field.input.classList.contains('error')).toBe(false)
40+
})
7941
})
8042

81-
it('supports warning-level feedback without marking the field as error', () => {
82-
const field = createField(Object.assign(document.createElement('textarea'), { id: 'message' }), 'message')
43+
it('supports warning-level feedback without marking the field as error', async () => {
44+
await renderContactForm(({ elements }) => {
45+
const field = elements.fields.message
8346

84-
showFieldFeedback(field, 'Almost too long', 'warning')
47+
showFieldFeedback(field, 'Almost too long', 'warning')
8548

86-
expect(field.feedback.dataset['state']).toBe('warning')
87-
expect(field.feedback.style.color).toBe('var(--color-warning)')
88-
expect(field.input.classList.contains('error')).toBe(false)
49+
expect(field.feedback.dataset['state']).toBe('warning')
50+
expect(field.feedback.style.color).toBe('var(--color-warning)')
51+
expect(field.input.classList.contains('error')).toBe(false)
52+
})
8953
})
9054

91-
it('initializes label handlers and syncs opacity based on field values', () => {
92-
const fields = createFields()
93-
const controller = initLabelHandlers(fields)
55+
it('initializes label handlers and syncs opacity based on field values', async () => {
56+
await renderContactForm(({ elements, window }) => {
57+
const controller = initLabelHandlers(elements.fields)
9458

95-
expect(fields.name.label.style.opacity).toBe('0.5')
59+
expect(elements.fields.name.label.style.opacity).toBe('0.5')
9660

97-
fields.name.input.value = 'Webstack'
98-
fields.name.input.dispatchEvent(new Event('input'))
99-
expect(fields.name.label.style.opacity).toBe('0')
61+
elements.fields.name.input.value = 'Webstack'
62+
elements.fields.name.input.dispatchEvent(new window.Event('input'))
63+
expect(elements.fields.name.label.style.opacity).toBe('0')
10064

101-
fields.name.input.value = ''
102-
controller.sync()
103-
expect(fields.name.label.style.opacity).toBe('0.5')
65+
elements.fields.name.input.value = ''
66+
controller.sync()
67+
expect(elements.fields.name.label.style.opacity).toBe('0.5')
68+
})
10469
})
10570
})

0 commit comments

Comments
 (0)