2.4 KiB
2.4 KiB
Component Testing
Philosophy: Test Behavior, Not Implementation
// BAD: Tests internals
expect(component.state.isOpen).toBe(true);
// GOOD: Tests user-visible behavior
await userEvent.click(getByRole('button', { name: 'Open' }));
expect(getByRole('dialog')).toBeVisible();
React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('form submission', async () => {
render(<LoginForm />);
await userEvent.type(screen.getByLabelText('Email'), 'test@example.com');
await userEvent.type(screen.getByLabelText('Password'), 'secret123');
await userEvent.click(screen.getByRole('button', { name: /login/i }));
expect(screen.getByText('Login successful')).toBeInTheDocument();
});
Vue Test Utils
import { mount } from '@vue/test-utils';
test('form submission', async () => {
const wrapper = mount(LoginForm);
await wrapper.find('input[type="email"]').setValue('test@example.com');
await wrapper.find('button').trigger('click');
expect(wrapper.text()).toContain('Login successful');
});
Angular Testing Library
import { render, screen } from '@testing-library/angular';
import userEvent from '@testing-library/user-event';
test('form submission', async () => {
await render(LoginFormComponent);
const user = userEvent.setup();
await user.type(screen.getByLabelText('Email'), 'test@example.com');
await user.click(screen.getByRole('button', { name: /login/i }));
expect(screen.getByText('Login successful')).toBeInTheDocument();
});
Query Priority (Accessibility-First)
getByRole- buttons, links, headingsgetByLabelText- form fieldsgetByPlaceholderText- inputsgetByText- non-interactive elementsgetByTestId- last resort
Async Patterns
await screen.findByText('Loaded');
await waitForElementToBeRemoved(() => screen.queryByText('Loading'));
await waitFor(() => expect(screen.getByText('Done')).toBeInTheDocument());
Mocking
vi.mock('./api', () => ({
fetchUser: vi.fn().mockResolvedValue({ name: 'John' })
}));
render(
<UserContext.Provider value={{ user: mockUser }}>
<Profile />
</UserContext.Provider>
);
Vitest Browser Mode
// vitest.config.ts - more accurate than jsdom
export default defineConfig({
test: { browser: { enabled: true, name: 'chromium', provider: 'playwright' } },
});