import { test, expect, request } from '@playwright/test'; const PROJECT_ID = '550e8400-e29b-41d4-a716-446655440001'; const BUILDING_1_ID = '2293e53a-0a48-48df-955a-b59c721135c8'; const BUILDING_2_ID = 'f52b7ab1-2fbc-4b38-a29f-dc48fc3246fa'; const BUILDING_3_ID = '1c046633-4290-4a9a-b670-c0febe7e9105'; async function getToken() { const context = await request.newContext(); const resp = await context.post('http://127.0.0.1:8080/api/auth/login', { headers: { 'Content-Type': 'application/json' }, data: { username: 'admin', password: 'Admin@123' } }); const loginData = await resp.json(); await context.dispose(); return loginData.data?.token as string; } async function cleanupTestRooms(token: string) { const context = await request.newContext(); const resp = await context.get(`http://127.0.0.1:8080/api/mdm/space-nodes/project/${PROJECT_ID}/type/ROOM`, { headers: { 'Authorization': `Bearer ${token}` } }); const data = await resp.json(); const rooms = data.data || []; for (const room of rooms) { if (room.name.includes('E2E测试') || room.name.includes('批量多选')) { await context.delete(`http://127.0.0.1:8080/api/mdm/space-nodes/${room.id}`, { headers: { 'Authorization': `Bearer ${token}` } }); } } await context.dispose(); } test.describe('批量添加房间/车位 - 多选功能测试', () => { test.beforeEach(async ({ page }) => { const token = await getToken(); await page.goto('http://127.0.0.1:5175/login'); await page.evaluate((t) => { localStorage.setItem('token', t); localStorage.setItem('userInfo', JSON.stringify({ username: 'admin' })); }, token!); }); test('UC-001: 多楼栋选择能正确创建多组房间', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const buildingSelect = page.locator('.ant-modal-content .ant-select').first(); if (await buildingSelect.isVisible({ timeout: 3000 })) { await buildingSelect.click(); await page.waitForTimeout(500); const option1 = page.locator('.ant-select-dropdown .ant-select-item:has-text("1号楼")'); const option2 = page.locator('.ant-select-dropdown .ant-select-item:has-text("2号楼")'); if (await option1.isVisible()) { await option1.click(); await page.waitForTimeout(300); } if (await option2.isVisible()) { await option2.click(); await page.waitForTimeout(300); } await page.keyboard.press('Escape'); await page.waitForTimeout(300); const startFloorInput = page.locator('.ant-modal-content .ant-input-number').nth(0); const endFloorInput = page.locator('.ant-modal-content .ant-input-number').nth(1); const roomsPerFloorInput = page.locator('.ant-modal-content .ant-input-number').nth(2); if (await startFloorInput.isVisible()) { await startFloorInput.fill('1'); await endFloorInput.fill('2'); await roomsPerFloorInput.fill('2'); } console.log('UC-001: 多楼栋选择测试完成'); } } }); test('UC-002: 多停车区域选择能正确创建多组车位', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const parkingTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("车位")'); if (await parkingTab.isVisible({ timeout: 3000 })) { await parkingTab.click(); await page.waitForTimeout(500); console.log('UC-002: 进入车位批量添加页面'); } } }); test('UC-003: 单楼栋选择时显示楼层信息提示', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const buildingSelect = page.locator('.ant-modal-content .ant-select').first(); if (await buildingSelect.isVisible({ timeout: 3000 })) { await buildingSelect.click(); await page.waitForTimeout(500); const option1 = page.locator('.ant-select-dropdown .ant-select-item:has-text("1号楼")'); if (await option1.isVisible()) { await option1.click(); await page.waitForTimeout(500); } await page.keyboard.press('Escape'); const floorInfoTip = page.locator('.ant-modal-content .ant-alert:has-text("楼层")').or(page.locator('.ant-modal-content .ant-info:has-text("楼层")')); const hasFloorTip = await floorInfoTip.isVisible({ timeout: 3000 }).catch(() => false); console.log(`UC-003: 楼层信息提示显示状态: ${hasFloorTip}`); expect(hasFloorTip).toBe(true); } } }); test('UC-004: 多楼栋选择时不显示楼层信息提示', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const buildingSelect = page.locator('.ant-modal-content .ant-select').first(); if (await buildingSelect.isVisible({ timeout: 3000 })) { await buildingSelect.click(); await page.waitForTimeout(500); const option1 = page.locator('.ant-select-dropdown .ant-select-item:has-text("1号楼")'); const option2 = page.locator('.ant-select-dropdown .ant-select-item:has-text("2号楼")'); if (await option1.isVisible()) { await option1.click(); await page.waitForTimeout(300); } if (await option2.isVisible()) { await option2.click(); await page.waitForTimeout(300); } await page.keyboard.press('Escape'); await page.waitForTimeout(500); const floorInfoTip = page.locator('.ant-modal-content .ant-alert:has-text("楼层")').or(page.locator('.ant-modal-content .ant-info:has-text("楼层")')); const hasFloorTip = await floorInfoTip.isVisible({ timeout: 3000 }).catch(() => false); console.log(`UC-004: 多楼栋选择时楼层信息提示显示状态: ${hasFloorTip}`); expect(hasFloorTip).toBe(false); } } }); test('商铺-001: 批量添加商铺功能正常', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const shopTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("商铺")'); if (await shopTab.isVisible({ timeout: 3000 })) { await shopTab.click(); await page.waitForTimeout(500); console.log('商铺-001: 进入商铺批量添加页面成功'); } } }); test('楼栋-001: 批量添加楼栋功能正常', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const buildingTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("楼栋")'); if (await buildingTab.isVisible({ timeout: 3000 })) { await buildingTab.click(); await page.waitForTimeout(500); console.log('楼栋-001: 进入楼栋批量添加页面成功'); } } }); test('公共区域-001: 批量添加公共区域功能正常', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const publicTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("公共区域")'); if (await publicTab.isVisible({ timeout: 3000 })) { await publicTab.click(); await page.waitForTimeout(500); console.log('公共区域-001: 进入公共区域批量添加页面成功'); } } }); test('VC-001: 填写完整信息后不提示"请填写"', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const buildingSelect = page.locator('.ant-modal-content .ant-select').first(); if (await buildingSelect.isVisible({ timeout: 3000 })) { await buildingSelect.click(); await page.waitForTimeout(500); const option1 = page.locator('.ant-select-dropdown .ant-select-item:has-text("1号楼")'); if (await option1.isVisible()) { await option1.click(); await page.waitForTimeout(500); } await page.keyboard.press('Escape'); await page.waitForTimeout(300); } const inputs = page.locator('.ant-modal-content .ant-input-number'); const count = await inputs.count(); if (count >= 3) { await inputs.nth(0).fill('1'); await inputs.nth(1).fill('3'); await inputs.nth(2).fill('4'); const submitBtn = page.locator('.ant-modal-content button:has-text("确定")'); if (await submitBtn.isVisible()) { await submitBtn.click(); await page.waitForTimeout(1000); const warningMsg = page.locator('.ant-message:has-text("请填写")'); const hasWarning = await warningMsg.isVisible({ timeout: 1000 }).catch(() => false); console.log(`VC-001: 填写完整信息后警告提示: ${hasWarning}`); expect(hasWarning).toBe(false); } } } }); test('VC-002: 起始楼层大于结束楼层时提示错误', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const buildingSelect = page.locator('.ant-modal-content .ant-select').first(); if (await buildingSelect.isVisible({ timeout: 3000 })) { await buildingSelect.click(); await page.waitForTimeout(500); const option1 = page.locator('.ant-select-dropdown .ant-select-item:has-text("1号楼")'); if (await option1.isVisible()) { await option1.click(); await page.waitForTimeout(500); } await page.keyboard.press('Escape'); await page.waitForTimeout(300); } const inputs = page.locator('.ant-modal-content .ant-input-number'); const count = await inputs.count(); if (count >= 2) { await inputs.nth(0).fill('5'); await inputs.nth(1).fill('2'); const submitBtn = page.locator('.ant-modal-content button:has-text("确定")'); if (await submitBtn.isVisible()) { await submitBtn.click(); await page.waitForTimeout(1000); const errorMsg = page.locator('.ant-message:has-text("起始楼层不能大于结束楼层")'); const hasError = await errorMsg.isVisible({ timeout: 2000 }).catch(() => false); console.log(`VC-002: 错误提示显示: ${hasError}`); expect(hasError).toBe(true); } } } }); test('BC-001: 未选择楼栋时提示"请选择所属楼栋"', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const roomTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("房间")'); if (await roomTab.isVisible({ timeout: 3000 })) { await roomTab.click(); await page.waitForTimeout(500); } const inputs = page.locator('.ant-modal-content .ant-input-number'); const count = await inputs.count(); if (count >= 3) { await inputs.nth(0).fill('1'); await inputs.nth(1).fill('3'); await inputs.nth(2).fill('4'); const submitBtn = page.locator('.ant-modal-content button:has-text("确定")'); if (await submitBtn.isVisible()) { await submitBtn.click(); await page.waitForTimeout(1000); const errorMsg = page.locator('.ant-message:has-text("请选择所属楼栋")'); const hasError = await errorMsg.isVisible({ timeout: 2000 }).catch(() => false); console.log(`BC-001: 未选择楼栋错误提示: ${hasError}`); expect(hasError).toBe(true); } } } }); test('BC-002: 未选择停车区域时提示"请选择所属停车区域"', async ({ page }) => { await page.goto(`http://127.0.0.1:5175/project/list`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const projectCard = page.locator('.ant-card').first(); if (await projectCard.isVisible()) { await projectCard.click(); await page.waitForTimeout(2000); } const spaceMenuItem = page.locator('text=空间管理').or(page.locator('text=空间管理')); if (await spaceMenuItem.isVisible()) { await spaceMenuItem.click(); await page.waitForTimeout(1000); } const addButton = page.locator('button:has-text("批量添加")').or(page.locator('button:has-text("批量新增")')).first(); if (await addButton.isVisible({ timeout: 5000 })) { await addButton.click(); await page.waitForTimeout(1000); const parkingTab = page.locator('.ant-modal-content .ant-tabs-tab:has-text("车位")'); if (await parkingTab.isVisible({ timeout: 3000 })) { await parkingTab.click(); await page.waitForTimeout(500); } const floorCountInput = page.locator('.ant-modal-content .ant-input-number').first(); if (await floorCountInput.isVisible()) { await floorCountInput.fill('10'); const submitBtn = page.locator('.ant-modal-content button:has-text("确定")'); if (await submitBtn.isVisible()) { await submitBtn.click(); await page.waitForTimeout(1000); const errorMsg = page.locator('.ant-message:has-text("请选择所属停车区域")'); const hasError = await errorMsg.isVisible({ timeout: 2000 }).catch(() => false); console.log(`BC-002: 未选择停车区域错误提示: ${hasError}`); expect(hasError).toBe(true); } } } }); test('API-批量创建: 验证批量创建房间API', async () => { const token = await getToken(); expect(token).toBeTruthy(); const context = await request.newContext(); const buildingResp = await context.get(`http://127.0.0.1:8080/api/mdm/space-nodes/project/${PROJECT_ID}/type/BUILDING`, { headers: { 'Authorization': `Bearer ${token}` } }); const buildingData = await buildingResp.json(); const buildings = buildingData.data || []; expect(buildings.length).toBeGreaterThanOrEqual(2); const building1 = buildings[0]; const building2 = buildings[1]; const room1 = await context.post('http://127.0.0.1:8080/api/mdm/space-nodes', { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, data: { projectId: PROJECT_ID, name: `E2E测试房间-楼栋1-1F-001`, nodeCategory: 'BUILDING', nodeType: 'ROOM', parentId: building1.id, status: 'ACTIVE', floorNumber: 1 } }); const room1Data = await room1.json(); expect(room1Data.code).toBe(200); console.log('API-批量创建: 房间1创建成功'); const room2 = await context.post('http://127.0.0.1:8080/api/mdm/space-nodes', { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, data: { projectId: PROJECT_ID, name: `E2E测试房间-楼栋2-1F-001`, nodeCategory: 'BUILDING', nodeType: 'ROOM', parentId: building2.id, status: 'ACTIVE', floorNumber: 1 } }); const room2Data = await room2.json(); expect(room2Data.code).toBe(200); console.log('API-批量创建: 房间2创建成功'); await context.dispose(); }); });