diff --git a/src/components/ContactBook/AddContact.test.tsx b/src/components/ContactBook/AddContact.test.tsx new file mode 100644 index 0000000..23ee260 --- /dev/null +++ b/src/components/ContactBook/AddContact.test.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import { describe, it, expect, vi } from 'vitest' +import { render, screen, fireEvent } from '@testing-library/react' +import { AddContact } from './AddContact' + +describe('AddContact accessible labeling', () => { + it('associates inputs with accessible labels', () => { + render() + + expect(screen.getByLabelText(/contact name/i)).toBeInTheDocument() + expect(screen.getByLabelText(/stellar address/i)).toBeInTheDocument() + }) + + it('validates required fields on submit', () => { + const onAdd = vi.fn() + render() + + fireEvent.click(screen.getByRole('button', { name: /add/i })) + expect(screen.getByText(/name is required/i)).toBeInTheDocument() + expect(screen.getByText(/invalid stellar address/i)).toBeInTheDocument() + expect(onAdd).not.toHaveBeenCalled() + }) +}) diff --git a/src/components/ContactBook/AddContact.tsx b/src/components/ContactBook/AddContact.tsx index 2d5094c..711a10d 100644 --- a/src/components/ContactBook/AddContact.tsx +++ b/src/components/ContactBook/AddContact.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react' import { isValidStellarAddress } from '../../utils/stellar' +import { VisuallyHidden } from '../common/VisuallyHidden' import type { Contact } from './ContactItem' interface Props { @@ -23,16 +24,36 @@ export function AddContact({ onAdd, onCancel }: Props) { return (

Add contact

- setName(e.target.value)} - placeholder="Name" className="input w-full" - /> - {errors.name &&

{errors.name}

} - setAddress(e.target.value.trim())} - placeholder="G... address" className="input w-full font-mono" - /> - {errors.address &&

{errors.address}

} +
+ + setName(e.target.value)} + placeholder="Name" + className="input w-full" + aria-invalid={!!errors.name} + aria-describedby={errors.name ? "contact-name-error" : undefined} + /> + {errors.name &&

{errors.name}

} +
+
+ + setAddress(e.target.value.trim())} + placeholder="G... address" + className="input w-full font-mono" + aria-invalid={!!errors.address} + aria-describedby={errors.address ? "contact-address-error" : undefined} + /> + {errors.address &&

{errors.address}

} +