BoxSelectionComponent.tsx
import React, { useState } from 'react'; import { Modal, Button, Table, message } from 'antd'; const BoxSelectionComponent: React.FC = () => { const [modalVisible, setModalVisible] = useState(false); const [selectedBoxes, setSelectedBoxes] = useState<string[]>([]); const boxes = ['A', 'B', 'C', 'D', 'E']; const showModal = () => { setModalVisible(true); }; const handleBoxSelect = (box: string) => { const isSelected = selectedBoxes.includes(box); if (isSelected) { const updatedSelection = selectedBoxes.filter((selectedBox) => selectedBox !== box); setSelectedBoxes(updatedSelection); } else { if (selectedBoxes.length < 3) { setSelectedBoxes([...selectedBoxes, box]); } else { message.warning('最多可以选中三个盒子'); } } }; const handleDelete = (box: string) => { const updatedSelection = selectedBoxes.filter((selectedBox) => selectedBox !== box); setSelectedBoxes(updatedSelection); if (updatedSelection.length === 0) { message.warning('至少选择一个盒子'); } }; const handleOk = () => { if (selectedBoxes.length === 0) { message.warning('至少选择一个盒子'); return; } // 处理选中的盒子,可以在这里进行进一步操作,比如提交数据 console.log('选中的盒子:', selectedBoxes); setModalVisible(false); }; const handleCancel = () => { setModalVisible(false); }; const columns = [ { title: '序号', dataIndex: 'index', key: 'index', render: (_: any, record: { index: number }) => record.index + 1, }, { title: '名称', dataIndex: 'name', key: 'name', }, { title: '操作', key: 'action', render: (_: any, record: { index: number; name: string }) => ( <> <Button type="link" onClick={() => handleView(record)}> 查看 </Button> <Button type="link" onClick={() => handleDelete(record.name)}> 删除 </Button> </> ), }, ]; const data = selectedBoxes.map((box, index) => ({ key: index, index, name: box, })); const handleView = (record: { index: number; name: string }) => { // 处理查看操作,可以根据需要展示盒子的详细信息等 console.log('查看盒子:', record); }; return ( <> <Button type="primary" onClick={showModal}> 打开Modal </Button> <Modal title="选择盒子" visible={modalVisible} onOk={handleOk} onCancel={handleCancel} > <div> {boxes.map((box) => ( <div key={box} style={{ border: '1px solid #ccc', padding: '10px', marginBottom: '10px', backgroundColor: selectedBoxes.includes(box) ? '#e6f7ff' : 'white', cursor: 'pointer', }} onClick={() => handleBoxSelect(box)} > {box} </div> ))} </div> </Modal> <Table columns={columns} dataSource={data} pagination={false} />
</> ); }; export default BoxSelectionComponent;
单元测试
import React from 'react'; import { render, fireEvent, waitFor, screen } from '@testing-library/react'; import BoxSelectionComponent from './BoxSelectionComponent'; describe('BoxSelectionComponent', () => { // 渲染资源选择器 it('renders component correctly', () => { render(<BoxSelectionComponent />); expect(screen.getByText('打开Modal')).toBeInTheDocument(); }); // 点击之后可选择课程 it('opens modal when button is clicked', async () => { render(<BoxSelectionComponent />); fireEvent.click(screen.getByText('打开Modal')); await waitFor(() => { expect(screen.getByText('选择盒子')).toBeInTheDocument(); }); }); // 选中课程的盒子应该是什么样以及是否被选中和被取消 it('selects and deselects boxes correctly', async () => { render(<BoxSelectionComponent />); fireEvent.click(screen.getByText('打开Modal')); const boxA = screen.getByText('A'); const boxB = screen.getByText('B'); const boxC = screen.getByText('C'); fireEvent.click(boxA); fireEvent.click(boxB); expect(boxA).toHaveStyle('background-color: #e6f7ff'); // 断言第1个已经被选中 expect(boxA).toHaveStyle('background-color: #e6f7ff'); // 断言第2个已经被选中 fireEvent.click(boxA); expect(boxA).toHaveStyle('background-color: white'); // 再次点击断言第1个已经被删除 expect(boxB).toHaveStyle('background-color: white'); // 再次点击断言第1个已经被删除 expect(boxC).toHaveStyle('background-color: white'); // 再次点击断言第1个已经被删除 }); // 验证是否可以正常删除 it('deletes selected boxes correctly', async () => { render(<BoxSelectionComponent />); fireEvent.click(screen.getByText('打开Modal')); const boxA = screen.getByText('A'); const boxB = screen.getByText('B'); fireEvent.click(boxA); fireEvent.click(boxB); const deleteButton = await screen.findAllByText('删除'); fireEvent.click(deleteButton[0]); // 第一个选中的假设是第一个删除的 await waitFor(() => { expect(screen.queryByText('A')).not.toBeInTheDocument(); }); // 触发校验 expect(screen.getByText('至少选择一个盒子')).toBeInTheDocument(); }); // 触发选中最多三个 it('warns when trying to select more than three boxes', () => { render(<BoxSelectionComponent />); fireEvent.click(screen.getByText('打开Modal')); const boxA = screen.getByText('A'); const boxB = screen.getByText('B'); const boxC = screen.getByText('C'); const boxD = screen.getByText('D'); fireEvent.click(boxA); fireEvent.click(boxB); fireEvent.click(boxC); fireEvent.click(boxD); expect(screen.getByText('最多可以选中三个盒子')).toBeInTheDocument(); }); })
import React, { useState } from 'react';
import { Modal, Button, Table, message } from 'antd';
const BoxSelectionComponent: React.FC = () => {
const [modalVisible, setModalVisible] = useState(false);
const [selectedBoxes, setSelectedBoxes] = useState<string[]>([]);
const boxes = ['A', 'B', 'C', 'D', 'E'];
const showModal = () => {
setModalVisible(true);
};
const handleBoxSelect = (box: string) => {
const isSelected = selectedBoxes.includes(box);
if (isSelected) {
const updatedSelection = selectedBoxes.filter((selectedBox) => selectedBox !== box);
setSelectedBoxes(updatedSelection);
} else {
if (selectedBoxes.length < 3) {
setSelectedBoxes([...selectedBoxes, box]);
} else {
message.warning('最多可以选中三个盒子');
}
}
};
const handleDelete = (box: string) => {
const updatedSelection = selectedBoxes.filter((selectedBox) => selectedBox !== box);
setSelectedBoxes(updatedSelection);
if (updatedSelection.length === 0) {
message.warning('至少选择一个盒子');
}
};
const handleOk = () => {
if (selectedBoxes.length === 0) {
message.warning('至少选择一个盒子');
return;
}
// 处理选中的盒子,可以在这里进行进一步操作,比如提交数据
console.log('选中的盒子:', selectedBoxes);
setModalVisible(false);
};
const handleCancel = () => {
setModalVisible(false);
};
const columns = [
{
title: '序号',
dataIndex: 'index',
key: 'index',
render: (_: any, record: { index: number }) => record.index + 1,
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
},
{
title: '操作',
key: 'action',
render: (_: any, record: { index: number; name: string }) => (
<>
<Button type="link" onClick={() => handleView(record)}>
查看
</Button>
<Button type="link" onClick={() => handleDelete(record.name)}>
删除
</Button>
</>
),
},
];
const data = selectedBoxes.map((box, index) => ({
key: index,
index,
name: box,
}));
const handleView = (record: { index: number; name: string }) => {
// 处理查看操作,可以根据需要展示盒子的详细信息等
console.log('查看盒子:', record);
};
return (
<>
<Button type="primary" onClick={showModal}>
打开Modal
</Button>
<Modal
title="选择盒子"
visible={modalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
<div>
{boxes.map((box) => (
<div
key={box}
style={{
border: '1px solid #ccc',
padding: '10px',
marginBottom: '10px',
backgroundColor: selectedBoxes.includes(box) ? '#e6f7ff' : 'white',
cursor: 'pointer',
}}
onClick={() => handleBoxSelect(box)}
>
{box}
</div>
))}
</div>
</Modal>
<Table columns={columns} dataSource={data}
pagination={false}
/>
</>
);
};
export default BoxSelectionComponent;