region-list.spec.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import { TIMEOUTS } from '../../utils/timeouts';
  2. import { test, expect } from '../../utils/test-setup';
  3. import { readFileSync } from 'fs';
  4. import { join, dirname } from 'path';
  5. import { fileURLToPath } from 'url';
  6. const __filename = fileURLToPath(import.meta.url);
  7. const __dirname = dirname(__filename);
  8. const testUsers = JSON.parse(readFileSync(join(__dirname, '../../fixtures/test-users.json'), 'utf-8'));
  9. test.describe.serial('区域列表查看测试', () => {
  10. test.beforeEach(async ({ adminLoginPage, regionManagementPage }) => {
  11. // 以管理员身份登录后台
  12. await adminLoginPage.goto();
  13. await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
  14. await adminLoginPage.expectLoginSuccess();
  15. await regionManagementPage.goto();
  16. });
  17. test.describe('页面加载验证', () => {
  18. test('应该显示区域列表页面标题', async ({ regionManagementPage }) => {
  19. await expect(regionManagementPage.pageTitle).toBeVisible();
  20. await expect(regionManagementPage.pageTitle).toContainText('省市区树形管理');
  21. });
  22. test('应该显示新增省按钮', async ({ regionManagementPage }) => {
  23. await expect(regionManagementPage.addProvinceButton).toBeVisible();
  24. await expect(regionManagementPage.addProvinceButton).toContainText('新增省');
  25. });
  26. test('应该等待树结构加载完成', async ({ regionManagementPage }) => {
  27. await regionManagementPage.waitForTreeLoaded();
  28. await expect(regionManagementPage.treeContainer).toBeVisible();
  29. });
  30. });
  31. test.describe('区域数据展示验证', () => {
  32. test('应该显示默认省份数据', async ({ regionManagementPage }) => {
  33. await regionManagementPage.waitForTreeLoaded();
  34. // 验证树形容器可见
  35. await expect(regionManagementPage.treeContainer).toBeVisible();
  36. // 验证树结构中包含至少一个省份
  37. const provinces = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/);
  38. const count = await provinces.count();
  39. expect(count).toBeGreaterThan(0);
  40. // 验证第一个省份名称存在
  41. const firstProvince = await provinces.first().textContent();
  42. expect(firstProvince).toBeTruthy();
  43. expect(firstProvince!.trim()).toMatch(/^[\u4e00-\u9fa5]+省$/);
  44. });
  45. test('应该能获取区域状态', async ({ regionManagementPage, page }) => {
  46. await regionManagementPage.waitForTreeLoaded();
  47. // 获取树中的第一个区域节点
  48. const firstRegion = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/).first();
  49. const count = await firstRegion.count();
  50. if (count > 0) {
  51. const regionName = await firstRegion.textContent();
  52. if (regionName) {
  53. const status = await regionManagementPage.getRegionStatus(regionName.trim());
  54. // 验证状态是有效的值(启用、禁用或null)
  55. expect(status === null || status === '启用' || status === '禁用').toBe(true);
  56. }
  57. }
  58. });
  59. test('应该能展开和收起区域节点', async ({ regionManagementPage }) => {
  60. await regionManagementPage.waitForTreeLoaded();
  61. // 查找一个有子节点的省份
  62. const province = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/).first();
  63. const count = await province.count();
  64. if (count > 0) {
  65. const provinceName = await province.textContent();
  66. if (provinceName) {
  67. const name = provinceName.trim();
  68. // 尝试展开节点
  69. await regionManagementPage.expandNode(name);
  70. console.debug(`已展开节点: ${name}`);
  71. // 等待一下让展开动画完成
  72. await regionManagementPage.page.waitForTimeout(TIMEOUTS.MEDIUM);
  73. // 尝试收起节点
  74. await regionManagementPage.collapseNode(name);
  75. console.debug(`已收起节点: ${name}`);
  76. }
  77. }
  78. });
  79. test('应该能检查区域是否存在', async ({ regionManagementPage }) => {
  80. await regionManagementPage.waitForTreeLoaded();
  81. // 测试检查不存在的区域
  82. const notExists = await regionManagementPage.regionExists('不存在的测试区域XYZ123');
  83. expect(notExists).toBe(false);
  84. // 获取树中的实际区域名称进行测试
  85. const firstRegion = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/).first();
  86. const count = await firstRegion.count();
  87. if (count > 0) {
  88. const regionName = await firstRegion.textContent();
  89. if (regionName) {
  90. // 测试检查存在的区域
  91. const exists = await regionManagementPage.regionExists(regionName.trim());
  92. expect(exists).toBe(true);
  93. }
  94. }
  95. });
  96. });
  97. test.describe('树形结构交互', () => {
  98. test('应该能连续展开多个省份', async ({ regionManagementPage }) => {
  99. await regionManagementPage.waitForTreeLoaded();
  100. // 获取所有省份
  101. const provinces = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/);
  102. const count = await provinces.count();
  103. if (count > 0) {
  104. // 最多展开前3个省份
  105. const maxExpand = Math.min(count, 3);
  106. for (let i = 0; i < maxExpand; i++) {
  107. const province = provinces.nth(i);
  108. const provinceName = await province.textContent();
  109. if (provinceName) {
  110. await regionManagementPage.expandNode(provinceName.trim());
  111. console.debug(`展开省份 ${i + 1}: ${provinceName}`);
  112. await regionManagementPage.page.waitForTimeout(TIMEOUTS.SHORT);
  113. }
  114. }
  115. }
  116. });
  117. test('页面刷新后树结构应该正常显示', async ({ regionManagementPage, page }) => {
  118. await regionManagementPage.waitForTreeLoaded();
  119. // 刷新页面
  120. await page.reload();
  121. await page.waitForLoadState('domcontentloaded');
  122. // 重新导航到区域管理页面
  123. await regionManagementPage.goto();
  124. // 验证树结构再次加载
  125. await regionManagementPage.waitForTreeLoaded();
  126. await expect(regionManagementPage.treeContainer).toBeVisible();
  127. });
  128. });
  129. test.describe('导航功能', () => {
  130. test('应该能从其他页面导航到区域管理', async ({ adminLoginPage, regionManagementPage, page }) => {
  131. // 先访问其他页面
  132. await page.goto('/admin/dashboard');
  133. await page.waitForLoadState('domcontentloaded');
  134. // 然后导航到区域管理页面
  135. await regionManagementPage.goto();
  136. // 验证页面正常加载
  137. await expect(regionManagementPage.pageTitle).toBeVisible();
  138. await expect(regionManagementPage.treeContainer).toBeVisible();
  139. });
  140. });
  141. test.describe('区域层级标识验证', () => {
  142. test('应该能验证省份层级标识', async ({ regionManagementPage }) => {
  143. await regionManagementPage.waitForTreeLoaded();
  144. // 验证省份存在(以"省"结尾)
  145. const provinces = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/);
  146. const count = await provinces.count();
  147. expect(count).toBeGreaterThan(0);
  148. console.debug(`找到 ${count} 个省份`);
  149. });
  150. test('应该能展开省份并验证市级子节点', async ({ regionManagementPage }) => {
  151. await regionManagementPage.waitForTreeLoaded();
  152. // 查找第一个省份
  153. const province = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/).first();
  154. const provinceCount = await province.count();
  155. if (provinceCount > 0) {
  156. const provinceName = await province.textContent();
  157. if (provinceName) {
  158. // 展开省份
  159. await regionManagementPage.expandNode(provinceName.trim());
  160. await regionManagementPage.page.waitForTimeout(TIMEOUTS.MEDIUM);
  161. // 验证市级子节点存在(以"市"结尾)
  162. const cities = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+市$/);
  163. const cityCount = await cities.count();
  164. console.debug(`展开 ${provinceName.trim()} 后找到 ${cityCount} 个市`);
  165. // 验证至少有一个市(如果省份有子节点)
  166. if (cityCount > 0) {
  167. const firstCity = await cities.first().textContent();
  168. expect(firstCity).toBeTruthy();
  169. expect(firstCity!.trim()).toMatch(/^[\u4e00-\u9fa5]+市$/);
  170. }
  171. }
  172. }
  173. });
  174. test('应该能展开市并验证区级子节点', async ({ regionManagementPage }) => {
  175. await regionManagementPage.waitForTreeLoaded();
  176. // 查找第一个省份并展开
  177. const province = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+省$/).first();
  178. const provinceCount = await province.count();
  179. if (provinceCount > 0) {
  180. const provinceName = await province.textContent();
  181. if (provinceName) {
  182. await regionManagementPage.expandNode(provinceName.trim());
  183. await regionManagementPage.page.waitForTimeout(TIMEOUTS.MEDIUM);
  184. // 查找第一个市并展开
  185. const city = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+市$/).first();
  186. const cityCount = await city.count();
  187. if (cityCount > 0) {
  188. const cityName = await city.textContent();
  189. if (cityName) {
  190. await regionManagementPage.expandNode(cityName.trim());
  191. await regionManagementPage.page.waitForTimeout(TIMEOUTS.MEDIUM);
  192. // 验证区级子节点存在(以"区"或"县"结尾)
  193. const districts = regionManagementPage.treeContainer.getByText(/^[\u4e00-\u9fa5]+(区|县)$/);
  194. const districtCount = await districts.count();
  195. console.debug(`展开 ${cityName.trim()} 后找到 ${districtCount} 个区/县`);
  196. if (districtCount > 0) {
  197. const firstDistrict = await districts.first().textContent();
  198. expect(firstDistrict).toBeTruthy();
  199. }
  200. }
  201. }
  202. }
  203. }
  204. });
  205. });
  206. });