Skip to content

Commit e869857

Browse files
fix: Improve Storybook test logic for FormError stories
- Fixed race conditions in custom story by using findByText instead of getByText - Added proper timing delays for element rendering in placement story - Improved error message waiting logic in mixed story with clear/type sequence - Added better comments and sequential waiting for form/field errors - Fixed CSS class assertions by storing container references - Enhanced basic story with clearer step descriptions These changes should resolve the StorybookTestRunnerError issues by ensuring proper async handling and element availability.
1 parent 9d87584 commit e869857

4 files changed

Lines changed: 21 additions & 9 deletions

File tree

apps/docs/src/remix-hook-form/form-error-basic.stories.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,11 @@ The FormError component automatically displays when \`errors._form\` exists in t
189189
const submitButton = canvas.getByRole('button', { name: /sign in/i });
190190
await userEvent.click(submitButton);
191191

192+
// Wait for form-level error to appear
192193
await expect(canvas.findByText(/invalid email or password/i)).resolves.toBeInTheDocument();
194+
195+
// Verify field-level errors are cleared
193196
expect(canvas.queryByText(/please enter a valid email address/i)).not.toBeInTheDocument();
194197
});
195198
},
196199
};
197-

apps/docs/src/remix-hook-form/form-error-custom.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,18 @@ The custom component receives all the same props as the default FormMessage comp
191191
});
192192

193193
await step('Verify custom error styling and structure', async () => {
194-
const errorMessage = canvas.getByText(/authentication service is temporarily unavailable/i);
194+
// Wait for error message to be available
195+
const errorMessage = await canvas.findByText(/authentication service is temporarily unavailable/i);
195196
expect(errorMessage).toBeInTheDocument();
196197

197198
const errorContainer = errorMessage.closest('div');
198199
expect(errorContainer).toHaveClass('flex', 'items-center', 'p-4', 'bg-red-50', 'border-l-4', 'border-red-400', 'rounded-md');
199200

200201
const icon = errorContainer?.querySelector('svg');
201202
expect(icon).toBeInTheDocument();
202-
expect(icon).toHaveClass('h-5', 'w-5', 'text-red-400');
203+
expect(icon).toHaveClass('h-5', 'w-5', 'text-red-400', 'mr-3');
203204

204205
expect(errorMessage).toHaveClass('text-red-800', 'font-medium');
205206
});
206207
},
207208
};
208-

apps/docs/src/remix-hook-form/form-error-mixed.stories.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,24 @@ This pattern is useful when you want to show form-level context alongside specif
184184
const emailInput = canvas.getByLabelText(/email address/i);
185185
const passwordInput = canvas.getByLabelText(/password/i);
186186

187+
await userEvent.clear(emailInput);
188+
await userEvent.clear(passwordInput);
187189
await userEvent.type(emailInput, 'taken@example.com');
188190
await userEvent.type(passwordInput, 'validpass123');
189191

190192
const submitButton = canvas.getByRole('button', { name: /create account/i });
191193
await userEvent.click(submitButton);
192194

195+
// Wait for field-level error first
193196
await expect(canvas.findByText(/this email address is already registered/i)).resolves.toBeInTheDocument();
197+
198+
// Then wait for form-level error
194199
await expect(canvas.findByText(/registration failed/i)).resolves.toBeInTheDocument();
195200

196-
// Verify form-level error appears in multiple locations
201+
// Wait a moment for all errors to be rendered, then verify form-level error appears in multiple locations
202+
await new Promise(resolve => setTimeout(resolve, 100));
197203
const formErrors = canvas.getAllByText(/registration failed/i);
198204
expect(formErrors).toHaveLength(2);
199205
});
200206
},
201207
};
202-

apps/docs/src/remix-hook-form/form-error-placement.stories.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,17 @@ All three instances show the same error message but with different visual treatm
181181
});
182182

183183
await step('Verify different styling for each placement', async () => {
184+
// Wait a moment for all error messages to be rendered
185+
await new Promise(resolve => setTimeout(resolve, 100));
186+
184187
const errorMessages = canvas.getAllByText(/payment processing failed/i);
188+
expect(errorMessages).toHaveLength(3);
185189

186190
// Top placement - alert style
187191
const topError = errorMessages[0];
188192
expect(topError).toHaveClass('text-red-800');
189-
expect(topError.closest('div')).toHaveClass('p-4', 'bg-red-50', 'border', 'border-red-200', 'rounded-lg');
193+
const topContainer = topError.closest('div');
194+
expect(topContainer).toHaveClass('p-4', 'bg-red-50', 'border', 'border-red-200', 'rounded-lg');
190195

191196
// Inline placement - minimal style
192197
const inlineError = errorMessages[1];
@@ -195,8 +200,8 @@ All three instances show the same error message but with different visual treatm
195200
// Bottom placement - banner style
196201
const bottomError = errorMessages[2];
197202
expect(bottomError).toHaveClass('text-red-700');
198-
expect(bottomError.closest('div')).toHaveClass('mt-4', 'p-3', 'bg-red-100', 'border-l-4', 'border-red-500', 'rounded-r-md');
203+
const bottomContainer = bottomError.closest('div');
204+
expect(bottomContainer).toHaveClass('mt-4', 'p-3', 'bg-red-100', 'border-l-4', 'border-red-500', 'rounded-r-md');
199205
});
200206
},
201207
};
202-

0 commit comments

Comments
 (0)