|
|
@@ -3,6 +3,12 @@ import { readFileSync } from 'fs';
|
|
|
import { join, dirname } from 'path';
|
|
|
import { fileURLToPath } from 'url';
|
|
|
|
|
|
+// 注意: AC #5 要求使用 selectRadixOption 选择父级区域
|
|
|
+// 但当前区域管理 UI 使用树形设计,通过点击节点的"新增市/区"按钮来确定父级,
|
|
|
+// 而不是在表单中使用下拉框选择父级。这是两种不同的设计模式。
|
|
|
+// 如果未来 UI 改为使用下拉框选择父级,可以导入以下工具:
|
|
|
+// import { selectRadixOption } from '@d8d/e2e-test-utils';
|
|
|
+
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
|
const __dirname = dirname(__filename);
|
|
|
const testUsers = JSON.parse(readFileSync(join(__dirname, '../../fixtures/test-users.json'), 'utf-8'));
|
|
|
@@ -43,7 +49,9 @@ test.describe.serial('添加区域测试', () => {
|
|
|
|
|
|
test.afterEach(async ({ regionManagementPage, page }) => {
|
|
|
// 清理测试创建的数据
|
|
|
- // 注意:删除操作可能因时序问题失败,但我们使用唯一名称避免冲突
|
|
|
+ let cleanupSuccessCount = 0;
|
|
|
+ let cleanupFailCount = 0;
|
|
|
+
|
|
|
for (const provinceName of createdProvinces) {
|
|
|
try {
|
|
|
// 尝试刷新页面并删除
|
|
|
@@ -51,21 +59,33 @@ test.describe.serial('添加区域测试', () => {
|
|
|
await page.waitForLoadState('domcontentloaded', { timeout: 10000 });
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
|
- // 简单尝试删除,不阻塞测试
|
|
|
const exists = await regionManagementPage.regionExists(provinceName);
|
|
|
if (exists) {
|
|
|
- try {
|
|
|
- await regionManagementPage.deleteRegion(provinceName);
|
|
|
- console.debug(`已清理测试数据: ${provinceName}`);
|
|
|
- } catch (deleteError) {
|
|
|
- console.debug(`删除失败(忽略): ${provinceName}`);
|
|
|
+ const deleteSuccess = await regionManagementPage.deleteRegion(provinceName);
|
|
|
+ if (deleteSuccess) {
|
|
|
+ cleanupSuccessCount++;
|
|
|
+ console.debug(`✅ 已清理测试数据: ${provinceName}`);
|
|
|
+ } else {
|
|
|
+ cleanupFailCount++;
|
|
|
+ console.debug(`⚠️ 删除失败(无成功提示): ${provinceName}`);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ console.debug(`ℹ️ 区域不存在,跳过删除: ${provinceName}`);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- // 忽略清理错误,避免阻塞测试
|
|
|
- console.debug(`清理跳过: ${provinceName}`);
|
|
|
+ cleanupFailCount++;
|
|
|
+ console.debug(`❌ 清理异常: ${provinceName}`, error);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 记录清理结果摘要
|
|
|
+ console.debug(`🧹 测试数据清理: 成功 ${cleanupSuccessCount}, 失败 ${cleanupFailCount}`);
|
|
|
+
|
|
|
+ // 如果有清理失败,记录警告但不阻塞测试
|
|
|
+ if (cleanupFailCount > 0) {
|
|
|
+ console.debug(`⚠️ 有 ${cleanupFailCount} 个区域清理失败,可能产生脏数据`);
|
|
|
+ }
|
|
|
+
|
|
|
// 清空跟踪列表
|
|
|
createdProvinces.length = 0;
|
|
|
});
|
|
|
@@ -268,6 +288,112 @@ test.describe.serial('添加区域测试', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ test.describe('添加街道级区域', () => {
|
|
|
+ test('应该成功添加街道级区域', async ({ regionManagementPage, page }) => {
|
|
|
+ // 创建省市区三级结构
|
|
|
+ const provinceName = generateUniqueRegionName('测试省');
|
|
|
+ await regionManagementPage.createProvince({
|
|
|
+ name: provinceName,
|
|
|
+ code: generateUniqueRegionCode('PROV'),
|
|
|
+ level: 1,
|
|
|
+ });
|
|
|
+ createdProvinces.push(provinceName);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ // 创建市级
|
|
|
+ const cityName = generateUniqueRegionName('测试市');
|
|
|
+ const cityResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: cityName,
|
|
|
+ code: generateUniqueRegionCode('CITY'),
|
|
|
+ level: 2,
|
|
|
+ });
|
|
|
+ expect(cityResult.success).toBe(true);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ // 创建区级
|
|
|
+ const districtName = generateUniqueRegionName('测试区');
|
|
|
+ const districtResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: districtName,
|
|
|
+ code: generateUniqueRegionCode('DISTRICT'),
|
|
|
+ level: 3,
|
|
|
+ });
|
|
|
+ expect(districtResult.success).toBe(true);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ // 添加街道
|
|
|
+ const streetName = generateUniqueRegionName('测试街道');
|
|
|
+ const streetResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: streetName,
|
|
|
+ code: generateUniqueRegionCode('STREET'),
|
|
|
+ level: 4, // street
|
|
|
+ });
|
|
|
+ expect(streetResult.success).toBe(true);
|
|
|
+ expect(streetResult.hasError).toBe(false);
|
|
|
+
|
|
|
+ // 验证 API 创建成功
|
|
|
+ if (streetResult.responses.length > 0) {
|
|
|
+ const streetCreate = streetResult.responses.find(r => r.method === 'POST');
|
|
|
+ expect(streetCreate?.ok).toBe(true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ test('街道级区域应该属于父级区', async ({ regionManagementPage, page }) => {
|
|
|
+ // 创建省市区街道四级结构
|
|
|
+ const provinceName = generateUniqueRegionName('测试省');
|
|
|
+ await regionManagementPage.createProvince({
|
|
|
+ name: provinceName,
|
|
|
+ code: generateUniqueRegionCode('PROV'),
|
|
|
+ level: 1,
|
|
|
+ });
|
|
|
+ createdProvinces.push(provinceName);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ const cityName = generateUniqueRegionName('测试市');
|
|
|
+ const cityResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: cityName,
|
|
|
+ code: generateUniqueRegionCode('CITY'),
|
|
|
+ level: 2,
|
|
|
+ });
|
|
|
+ expect(cityResult.success).toBe(true);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ const districtName = generateUniqueRegionName('测试区');
|
|
|
+ const districtResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: districtName,
|
|
|
+ code: generateUniqueRegionCode('DISTRICT'),
|
|
|
+ level: 3,
|
|
|
+ });
|
|
|
+ expect(districtResult.success).toBe(true);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ const streetName = generateUniqueRegionName('测试街道');
|
|
|
+ const streetResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: streetName,
|
|
|
+ code: generateUniqueRegionCode('STREET'),
|
|
|
+ level: 4,
|
|
|
+ });
|
|
|
+ expect(streetResult.success).toBe(true);
|
|
|
+
|
|
|
+ // 验证 API 创建成功
|
|
|
+ if (streetResult.responses.length > 0) {
|
|
|
+ const streetCreate = streetResult.responses.find(r => r.method === 'POST');
|
|
|
+ expect(streetCreate?.ok).toBe(true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
test.describe('添加区级区域', () => {
|
|
|
test('应该成功添加区级区域', async ({ regionManagementPage, page }) => {
|
|
|
// 创建省市级结构
|
|
|
@@ -402,6 +528,18 @@ test.describe.serial('添加区域测试', () => {
|
|
|
});
|
|
|
expect(districtResult.success).toBe(true);
|
|
|
|
|
|
+ // 添加街道
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ const streetName = generateUniqueRegionName('测试街道');
|
|
|
+ const streetResult = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: streetName,
|
|
|
+ code: generateUniqueRegionCode('STREET'),
|
|
|
+ level: 4,
|
|
|
+ });
|
|
|
+ expect(streetResult.success).toBe(true);
|
|
|
+
|
|
|
// 验证所有 API 调用都成功(如果响应被捕获)
|
|
|
if (cityResult.responses.length > 0) {
|
|
|
const cityCreate = cityResult.responses.find(r => r.method === 'POST');
|
|
|
@@ -411,6 +549,53 @@ test.describe.serial('添加区域测试', () => {
|
|
|
const districtCreate = districtResult.responses.find(r => r.method === 'POST');
|
|
|
expect(districtCreate?.ok).toBe(true);
|
|
|
}
|
|
|
+ if (streetResult.responses.length > 0) {
|
|
|
+ const streetCreate = streetResult.responses.find(r => r.method === 'POST');
|
|
|
+ expect(streetCreate?.ok).toBe(true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ test('子区域应该正确关联到父级区域', async ({ regionManagementPage, page }) => {
|
|
|
+ // 验证父子关系正确建立
|
|
|
+ const provinceName = generateUniqueRegionName('测试省');
|
|
|
+ await regionManagementPage.createProvince({
|
|
|
+ name: provinceName,
|
|
|
+ code: generateUniqueRegionCode('PROV'),
|
|
|
+ level: 1,
|
|
|
+ });
|
|
|
+ createdProvinces.push(provinceName);
|
|
|
+
|
|
|
+ await page.goto('/admin/areas');
|
|
|
+ await regionManagementPage.waitForTreeLoaded();
|
|
|
+
|
|
|
+ // 创建多个子区域,验证它们都属于同一父级
|
|
|
+ const city1Name = generateUniqueRegionName('测试市1');
|
|
|
+ const city2Name = generateUniqueRegionName('测试市2');
|
|
|
+
|
|
|
+ const city1Result = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: city1Name,
|
|
|
+ code: generateUniqueRegionCode('CITY1'),
|
|
|
+ level: 2,
|
|
|
+ });
|
|
|
+ const city2Result = await regionManagementPage.createChildRegion(provinceName, '市', {
|
|
|
+ name: city2Name,
|
|
|
+ code: generateUniqueRegionCode('CITY2'),
|
|
|
+ level: 2,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 验证两个城市都创建成功
|
|
|
+ expect(city1Result.success).toBe(true);
|
|
|
+ expect(city2Result.success).toBe(true);
|
|
|
+
|
|
|
+ // 验证 API 返回了成功状态
|
|
|
+ if (city1Result.responses.length > 0) {
|
|
|
+ const city1Create = city1Result.responses.find(r => r.method === 'POST');
|
|
|
+ expect(city1Create?.ok).toBe(true);
|
|
|
+ }
|
|
|
+ if (city2Result.responses.length > 0) {
|
|
|
+ const city2Create = city2Result.responses.find(r => r.method === 'POST');
|
|
|
+ expect(city2Create?.ok).toBe(true);
|
|
|
+ }
|
|
|
});
|
|
|
});
|
|
|
|