Browse Source

test: improve test quality based on code review feedback

- basic-form: actually click submit button and verify fakeSubmitForm
  was called, instead of just asserting button exists
- basic-form: import waitFor from @testing-library/react
- analysis: assert '0 items' text after empty data loads instead of
  checking element that exists on initial render
- Replace dynamic import with static import in 3 test files where mock
  factories don't reference file-level variables (analysis, basic-form,
  table-list); keep dynamic import in app.test.tsx where mock factory
  references mockHistory/mockQueryCurrentUser which aren't available
  during hoisted static import resolution

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/11847/head
afc163 4 months ago
parent
commit
0d7217fbe7
  1. 2
      package-lock.json
  2. 12
      src/app.test.tsx
  3. 5
      src/pages/dashboard/analysis/index.test.tsx
  4. 11
      src/pages/form/basic-form/index.test.tsx
  5. 3
      src/pages/table-list/index.test.tsx

2
package-lock.json

@ -66,7 +66,7 @@
"vitest": "4.1.8"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@adobe/css-tools": {

12
src/app.test.tsx

@ -59,6 +59,7 @@ describe('app getInitialState', () => {
});
it('should fetch currentUser when not on login page', async () => {
const { getInitialState } = await import('./app');
mockQueryCurrentUser.mockResolvedValue({
data: {
name: 'Test User',
@ -66,7 +67,6 @@ describe('app getInitialState', () => {
},
});
const { getInitialState } = await import('./app');
const state = await getInitialState();
expect(mockQueryCurrentUser).toHaveBeenCalled();
@ -79,9 +79,9 @@ describe('app getInitialState', () => {
});
it('should redirect to login when currentUser fetch fails (401)', async () => {
const { getInitialState } = await import('./app');
mockQueryCurrentUser.mockRejectedValue(new Error('401 Unauthorized'));
const { getInitialState } = await import('./app');
const state = await getInitialState();
expect(mockReplace).toHaveBeenCalledWith(
@ -91,13 +91,13 @@ describe('app getInitialState', () => {
});
it('should not fetch currentUser on login page', async () => {
const { getInitialState } = await import('./app');
mockHistory.location = {
pathname: '/user/login',
search: '',
hash: '',
};
const { getInitialState } = await import('./app');
const state = await getInitialState();
expect(mockQueryCurrentUser).not.toHaveBeenCalled();
@ -106,6 +106,7 @@ describe('app getInitialState', () => {
});
it('should encode redirect path correctly on 401', async () => {
const { getInitialState } = await import('./app');
mockHistory.location = {
pathname: '/admin/users',
search: '?page=2',
@ -113,7 +114,6 @@ describe('app getInitialState', () => {
};
mockQueryCurrentUser.mockRejectedValue(new Error('401'));
const { getInitialState } = await import('./app');
await getInitialState();
expect(mockReplace).toHaveBeenCalledWith(
@ -122,22 +122,22 @@ describe('app getInitialState', () => {
});
it('should include default settings in initial state', async () => {
const { getInitialState } = await import('./app');
mockQueryCurrentUser.mockResolvedValue({
data: { name: 'User' },
});
const { getInitialState } = await import('./app');
const state = await getInitialState();
expect(state.settings).toEqual({ navTheme: 'light' });
});
it('fetchUserInfo should return user data on success', async () => {
const { getInitialState } = await import('./app');
mockQueryCurrentUser.mockResolvedValue({
data: { name: 'Fetched User', access: 'user' },
});
const { getInitialState } = await import('./app');
const state = await getInitialState();
const user = await state.fetchUserInfo?.();

5
src/pages/dashboard/analysis/index.test.tsx

@ -80,8 +80,7 @@ vi.mock('./components/PageLoading', () => ({
default: () => <div data-testid="page-loading">Loading...</div>,
}));
// Import component after mocks
const Analysis = (await import('./index')).default;
import Analysis from './index';
const mockAnalysisData: AnalysisData = {
visitData: [
@ -235,7 +234,7 @@ describe('Analysis Dashboard', () => {
);
await waitFor(() => {
expect(screen.getByTestId('introduce-row')).toBeInTheDocument();
expect(screen.getByTestId('introduce-row')).toHaveTextContent('0 items');
});
});
});

11
src/pages/form/basic-form/index.test.tsx

@ -1,5 +1,5 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import * as service from './service';
@ -84,8 +84,7 @@ vi.mock('./style.style', () => ({
}),
}));
// Import component after mocks
const BasicForm = (await import('./index')).default;
import BasicForm from './index';
describe('BasicForm', () => {
let queryClient: QueryClient;
@ -143,7 +142,11 @@ describe('BasicForm', () => {
);
const submitButton = screen.getByRole('button', { name: /提交/i });
expect(submitButton).toBeInTheDocument();
submitButton.click();
await waitFor(() => {
expect(mockSubmit).toHaveBeenCalled();
});
});
it('should render within PageContainer', () => {

3
src/pages/table-list/index.test.tsx

@ -92,8 +92,7 @@ vi.mock('./components/UpdateForm', () => ({
default: ({ trigger }: any) => <div data-testid="update-form">{trigger}</div>,
}));
// Import component after mocks
const TableList = (await import('./index')).default;
import TableList from './index';
describe('TableList', () => {
let queryClient: QueryClient;

Loading…
Cancel
Save