|
|
@@ -378,4 +378,203 @@ describe('商品管理集成测试', () => {
|
|
|
expect(screen.getByText('状态')).toBeInTheDocument();
|
|
|
expect(screen.getByText('创建时间')).toBeInTheDocument();
|
|
|
});
|
|
|
+
|
|
|
+ describe('父子商品配置功能测试 (故事006.001)', () => {
|
|
|
+ it('应该显示spuId/spuName字段表单控件', async () => {
|
|
|
+ const mockGoods = {
|
|
|
+ data: [],
|
|
|
+ pagination: { total: 0, page: 1, pageSize: 10 },
|
|
|
+ };
|
|
|
+
|
|
|
+ (goodsClientManager.get().$get as any).mockResolvedValue(createMockResponse(200, mockGoods));
|
|
|
+
|
|
|
+ renderWithProviders(<GoodsManagement />);
|
|
|
+
|
|
|
+ // 打开创建商品表单
|
|
|
+ const createButton = screen.getByText('创建商品');
|
|
|
+ fireEvent.click(createButton);
|
|
|
+
|
|
|
+ // 验证spuId字段存在
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('主商品ID')).toBeInTheDocument();
|
|
|
+ expect(screen.getByTestId('goods-spu-id-input')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 验证spuName字段存在
|
|
|
+ expect(screen.getByText('主商品名称')).toBeInTheDocument();
|
|
|
+ expect(screen.getByTestId('goods-spu-name-input')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该支持创建父商品 (spuId=0)', async () => {
|
|
|
+ const mockGoods = {
|
|
|
+ data: [],
|
|
|
+ pagination: { total: 0, page: 1, pageSize: 10 },
|
|
|
+ };
|
|
|
+
|
|
|
+ (goodsClientManager.get().$get as any).mockResolvedValue(createMockResponse(200, mockGoods));
|
|
|
+
|
|
|
+ renderWithProviders(<GoodsManagement />);
|
|
|
+
|
|
|
+ // 打开创建商品表单
|
|
|
+ const createButton = screen.getByText('创建商品');
|
|
|
+ fireEvent.click(createButton);
|
|
|
+
|
|
|
+ // 填写基本商品信息
|
|
|
+ const nameInput = screen.getByTestId('goods-name-input');
|
|
|
+ const priceInput = screen.getByTestId('goods-price-input');
|
|
|
+ const spuIdInput = screen.getByTestId('goods-spu-id-input');
|
|
|
+
|
|
|
+ fireEvent.change(nameInput, { target: { value: '父商品测试' } });
|
|
|
+ fireEvent.change(priceInput, { target: { value: '299.99' } });
|
|
|
+
|
|
|
+ // 设置spuId=0(父商品)
|
|
|
+ fireEvent.change(spuIdInput, { target: { value: '0' } });
|
|
|
+
|
|
|
+ // Mock API调用
|
|
|
+ const { goodsClient } = await import('../../src/api/goodsClient');
|
|
|
+ (goodsClient.$post as any).mockResolvedValue(createMockResponse(201, {
|
|
|
+ id: 100,
|
|
|
+ name: '父商品测试',
|
|
|
+ price: 299.99,
|
|
|
+ spuId: 0,
|
|
|
+ spuName: null
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 提交表单
|
|
|
+ const submitButton = screen.getByText('创建');
|
|
|
+ fireEvent.click(submitButton);
|
|
|
+
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(goodsClient.$post).toHaveBeenCalled();
|
|
|
+ // 验证提交的数据包含spuId=0
|
|
|
+ const callArgs = (goodsClient.$post as any).mock.calls[0];
|
|
|
+ expect(callArgs[0].json.spuId).toBe(0);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该支持创建子商品并关联父商品', async () => {
|
|
|
+ const mockGoods = {
|
|
|
+ data: [],
|
|
|
+ pagination: { total: 0, page: 1, pageSize: 10 },
|
|
|
+ };
|
|
|
+
|
|
|
+ (goodsClientManager.get().$get as any).mockResolvedValue(createMockResponse(200, mockGoods));
|
|
|
+
|
|
|
+ renderWithProviders(<GoodsManagement />);
|
|
|
+
|
|
|
+ // 打开创建商品表单
|
|
|
+ const createButton = screen.getByText('创建商品');
|
|
|
+ fireEvent.click(createButton);
|
|
|
+
|
|
|
+ // 填写基本商品信息
|
|
|
+ const nameInput = screen.getByTestId('goods-name-input');
|
|
|
+ const priceInput = screen.getByTestId('goods-price-input');
|
|
|
+ const spuIdInput = screen.getByTestId('goods-spu-id-input');
|
|
|
+ const spuNameInput = screen.getByTestId('goods-spu-name-input');
|
|
|
+
|
|
|
+ fireEvent.change(nameInput, { target: { value: '子商品测试' } });
|
|
|
+ fireEvent.change(priceInput, { target: { value: '199.99' } });
|
|
|
+
|
|
|
+ // 设置spuId=100(父商品ID),spuName='父商品名称'
|
|
|
+ fireEvent.change(spuIdInput, { target: { value: '100' } });
|
|
|
+ fireEvent.change(spuNameInput, { target: { value: '父商品名称' } });
|
|
|
+
|
|
|
+ // Mock API调用
|
|
|
+ const { goodsClient } = await import('../../src/api/goodsClient');
|
|
|
+ (goodsClient.$post as any).mockResolvedValue(createMockResponse(201, {
|
|
|
+ id: 101,
|
|
|
+ name: '子商品测试',
|
|
|
+ price: 199.99,
|
|
|
+ spuId: 100,
|
|
|
+ spuName: '父商品名称'
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 提交表单
|
|
|
+ const submitButton = screen.getByText('创建');
|
|
|
+ fireEvent.click(submitButton);
|
|
|
+
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(goodsClient.$post).toHaveBeenCalled();
|
|
|
+ // 验证提交的数据包含正确的父子关系
|
|
|
+ const callArgs = (goodsClient.$post as any).mock.calls[0];
|
|
|
+ expect(callArgs[0].json.spuId).toBe(100);
|
|
|
+ expect(callArgs[0].json.spuName).toBe('父商品名称');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示子商品关联选择器组件', async () => {
|
|
|
+ const mockGoods = {
|
|
|
+ data: [],
|
|
|
+ pagination: { total: 0, page: 1, pageSize: 10 },
|
|
|
+ };
|
|
|
+
|
|
|
+ (goodsClientManager.get().$get as any).mockResolvedValue(createMockResponse(200, mockGoods));
|
|
|
+
|
|
|
+ renderWithProviders(<GoodsManagement />);
|
|
|
+
|
|
|
+ // 打开创建商品表单
|
|
|
+ const createButton = screen.getByText('创建商品');
|
|
|
+ fireEvent.click(createButton);
|
|
|
+
|
|
|
+ // 验证子商品选择器存在(通过placeholder)
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByPlaceholderText('选择子商品...')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 验证批量创建按钮存在(在商品列表操作中)
|
|
|
+ // 注意:批量创建按钮只在编辑模式下显示,这里我们主要验证功能存在
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示包含父子关系的商品列表', async () => {
|
|
|
+ // Mock包含父子关系的商品数据
|
|
|
+ const mockGoods = {
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ id: 100,
|
|
|
+ name: '父商品',
|
|
|
+ price: 299.99,
|
|
|
+ spuId: 0,
|
|
|
+ spuName: null,
|
|
|
+ childGoodsIds: [101, 102],
|
|
|
+ stock: 100,
|
|
|
+ salesNum: 50,
|
|
|
+ state: 1,
|
|
|
+ createdAt: '2024-01-01T00:00:00Z',
|
|
|
+ supplier: { id: 1, name: '供应商1' },
|
|
|
+ merchant: { id: 1, name: '商户1' },
|
|
|
+ // ...其他必要字段
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 101,
|
|
|
+ name: '子商品1',
|
|
|
+ price: 199.99,
|
|
|
+ spuId: 100,
|
|
|
+ spuName: '父商品',
|
|
|
+ stock: 50,
|
|
|
+ salesNum: 20,
|
|
|
+ state: 1,
|
|
|
+ createdAt: '2024-01-01T00:00:00Z',
|
|
|
+ supplier: { id: 1, name: '供应商1' },
|
|
|
+ merchant: { id: 1, name: '商户1' },
|
|
|
+ // ...其他必要字段
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ pagination: { total: 2, page: 1, pageSize: 10 },
|
|
|
+ };
|
|
|
+
|
|
|
+ (goodsClientManager.get().$get as any).mockResolvedValue(createMockResponse(200, mockGoods));
|
|
|
+
|
|
|
+ renderWithProviders(<GoodsManagement />);
|
|
|
+
|
|
|
+ // 等待数据加载
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('父商品')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('子商品1')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 验证表格显示父子商品信息
|
|
|
+ const tableRows = screen.getAllByRole('row');
|
|
|
+ expect(tableRows.length).toBeGreaterThan(2); // 表头 + 数据行
|
|
|
+ });
|
|
|
+ });
|
|
|
});
|