diff --git a/app/hooks/use-form.ts b/app/hooks/use-form.ts index a81b786a0a..75f6085050 100644 --- a/app/hooks/use-form.ts +++ b/app/hooks/use-form.ts @@ -8,14 +8,12 @@ import { type FieldValues, type UseFormProps, useForm as _useForm } from 'react-hook-form' /** - * Same as built-in `useForm` except `mode: 'onTouched'` is hard-coded and the - * caller can't set it. `onTouched` means the first validation on a field is - * triggered by blur, after which it updates with every change. - * + * Same as built-in `useForm` except we can hard-code some props and prevent the + * caller from setting them. * See https://react-hook-form.com/docs/useform#mode */ export function useForm( props?: Omit, 'mode'> ) { - return _useForm({ mode: 'onTouched', ...props }) + return _useForm({ mode: 'onSubmit', ...props }) } diff --git a/app/test/e2e/instance-create.e2e.ts b/app/test/e2e/instance-create.e2e.ts index f580baf4e9..34cf965dd3 100644 --- a/app/test/e2e/instance-create.e2e.ts +++ b/app/test/e2e/instance-create.e2e.ts @@ -107,13 +107,16 @@ test('can create an instance with custom hardware', async ({ page }) => { // test disk size validation against image size await diskSizeInput.fill('5') - await diskSizeInput.blur() // need blur to trigger validation + + const submitButton = page.getByRole('button', { name: 'Create instance' }) + await submitButton.click() // submit to trigger validation + await expectVisible(page, [ 'main >> text=Must be as large as selected image (min. 6 GiB)', ]) await diskSizeInput.fill('10') - await page.getByRole('button', { name: 'Create instance' }).click() + await submitButton.click() await expect(page).toHaveURL(`/projects/mock-project/instances/${instanceName}/storage`) diff --git a/app/test/e2e/project-create.e2e.ts b/app/test/e2e/project-create.e2e.ts index 0520156bac..dc4e9c4360 100644 --- a/app/test/e2e/project-create.e2e.ts +++ b/app/test/e2e/project-create.e2e.ts @@ -32,9 +32,10 @@ test.describe('Project create', () => { test('shows field-level validation error and does not POST', async ({ page }) => { await page.fill('role=textbox[name="Name"]', 'Invalid name') - await page.click('role=textbox[name="Description"]') // just to blur name input - // role=dialog to distinguish from live announce - await expectVisible(page, ['role=dialog >> text="Must start with a lower-case letter"']) + // submit to trigger validation + await page.getByRole('button', { name: 'Create project' }).click() + + await expect(page.getByText('Must start with a lower-case letter').nth(0)).toBeVisible() }) test('shows form-level error for known server error', async ({ page }) => {