UserFormPage.test.tsx 3.29 KB
import { describe, it, expect } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import { ConfigProvider } from 'antd';
import { configureStore } from '@reduxjs/toolkit';
import authReducer, { setSession } from '../../store/slices/authSlice';
import UserFormPage from './UserFormPage';

function makeStore() {
  const store = configureStore({ reducer: { auth: authReducer } });
  store.dispatch(
    setSession({
      accessToken: 'jwt',
      userInfo: {
        userId: 2,
        username: 'admin',
        userType: 'SUPER_ADMIN',
        language: 'zh-CN',
        companyCode: 'HQ',
      },
    }),
  );
  return store;
}

function renderForm(mode: 'create' | 'edit', initialEntry: string) {
  return render(
    <Provider store={makeStore()}>
      <ConfigProvider>
        <MemoryRouter initialEntries={[initialEntry]}>
          <Routes>
            <Route path="/users" element={<div data-testid="users-list">LIST</div>} />
            <Route path="/users/new" element={<UserFormPage mode={mode} />} />
            <Route path="/users/:userId" element={<UserFormPage mode={mode} />} />
          </Routes>
        </MemoryRouter>
      </ConfigProvider>
    </Provider>,
  );
}

describe('UserFormPage (create)', () => {
  it('renders empty form with username editable', () => {
    renderForm('create', '/users/new');
    const usernameInput = screen.getByLabelText('用户名') as HTMLInputElement;
    expect(usernameInput).not.toBeDisabled();
  });

  it('cancel button navigates back to /users', async () => {
    renderForm('create', '/users/new');
    const user = userEvent.setup();
    await user.click(screen.getByTestId('form-cancel'));
    expect(await screen.findByTestId('users-list')).toBeInTheDocument();
  });

  it('submit valid form navigates to /users', async () => {
    renderForm('create', '/users/new');
    const user = userEvent.setup();
    await user.type(screen.getByLabelText('用户名'), 'newbie');
    await user.type(screen.getByLabelText('用户号'), 'U999');
    await user.click(screen.getByTestId('form-save'));
    expect(await screen.findByTestId('users-list', {}, { timeout: 3000 })).toBeInTheDocument();
  });

  it('duplicate username (40901) shows field-level error', async () => {
    renderForm('create', '/users/new');
    const user = userEvent.setup();
    await user.type(screen.getByLabelText('用户名'), 'dup');
    await user.type(screen.getByLabelText('用户号'), 'U999');
    await user.click(screen.getByTestId('form-save'));
    await waitFor(() => expect(screen.getByText('用户名已存在')).toBeInTheDocument());
  });
});

describe('UserFormPage (edit)', () => {
  it('fetches detail and prefills form with username readonly', async () => {
    renderForm('edit', '/users/1');
    await waitFor(() => {
      const usernameInput = screen.getByLabelText('用户名') as HTMLInputElement;
      expect(usernameInput.value).toBe('alice');
      expect(usernameInput).toBeDisabled();
    });
  });

  it('unknown userId (40401) shows 404 result', async () => {
    renderForm('edit', '/users/99999');
    await waitFor(() => expect(screen.getByTestId('user-not-found')).toBeInTheDocument());
  });
});