2
0

platform-list.spec.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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('平台列表显示', () => {
  10. test.beforeEach(async ({ adminLoginPage, platformManagementPage }) => {
  11. // 以管理员身份登录后台
  12. await adminLoginPage.goto();
  13. await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
  14. await adminLoginPage.expectLoginSuccess();
  15. await platformManagementPage.goto();
  16. });
  17. test.describe('列表基础显示', () => {
  18. test('应该显示平台列表页面元素', async ({ platformManagementPage }) => {
  19. // 验证页面标题可见
  20. await expect(platformManagementPage.pageTitle).toBeVisible();
  21. // 验证创建平台按钮可见
  22. await expect(platformManagementPage.createPlatformButton).toBeVisible();
  23. // 验证搜索框可见
  24. await expect(platformManagementPage.searchInput).toBeVisible();
  25. await expect(platformManagementPage.searchButton).toBeVisible();
  26. // 验证表格存在
  27. await expect(platformManagementPage.platformTable).toBeVisible();
  28. });
  29. test('应该加载平台列表数据', async ({ platformManagementPage }) => {
  30. // 验证表格存在且可见
  31. await expect(platformManagementPage.platformTable).toBeVisible();
  32. // 检查表格是否有 tbody 元素
  33. const tbody = platformManagementPage.platformTable.locator('tbody');
  34. await expect(tbody).toBeVisible();
  35. });
  36. });
  37. test.describe('列表数据字段显示', () => {
  38. test('应该正确显示平台数据字段', async ({ platformManagementPage }) => {
  39. // 创建测试平台
  40. const timestamp = Date.now();
  41. const platformName = `列表测试平台_${timestamp}`;
  42. const contactPerson = `列表测试联系人_${timestamp}`;
  43. const contactPhone = '13800138000';
  44. const contactEmail = `listtest_${timestamp}@example.com`;
  45. await platformManagementPage.createPlatform({
  46. platformName,
  47. contactPerson,
  48. contactPhone,
  49. contactEmail,
  50. });
  51. // 刷新页面确保数据加载
  52. await platformManagementPage.page.reload();
  53. await platformManagementPage.goto();
  54. // 查找平台行
  55. const platformRow = platformManagementPage.platformTable
  56. .locator('tbody tr')
  57. .filter({ hasText: platformName });
  58. // 验证平台在列表中
  59. const rowCount = await platformRow.count();
  60. expect(rowCount).toBeGreaterThan(0);
  61. // 验证平台名称(第二列)
  62. const nameCell = platformRow.locator('td').nth(1);
  63. await expect(nameCell).toContainText(platformName);
  64. // 验证联系人(第三列)
  65. const personCell = platformRow.locator('td').nth(2);
  66. await expect(personCell).toContainText(contactPerson);
  67. // 验证联系电话(第四列)
  68. const phoneCell = platformRow.locator('td').nth(3);
  69. await expect(phoneCell).toContainText(contactPhone);
  70. // 验证联系邮箱(第五列)
  71. const emailCell = platformRow.locator('td').nth(4);
  72. await expect(emailCell).toContainText(contactEmail);
  73. // 清理测试数据
  74. await platformManagementPage.deletePlatform(platformName);
  75. });
  76. test('应该显示操作列的编辑和删除按钮', async ({ platformManagementPage }) => {
  77. // 创建测试平台
  78. const timestamp = Date.now();
  79. const platformName = `操作按钮测试_${timestamp}`;
  80. await platformManagementPage.createPlatform({
  81. platformName,
  82. contactPerson: `测试联系人_${timestamp}`,
  83. contactPhone: '13900139000',
  84. contactEmail: `button_${timestamp}@test.com`,
  85. });
  86. // 刷新页面
  87. await platformManagementPage.page.reload();
  88. await platformManagementPage.goto();
  89. // 查找平台行
  90. const platformRow = platformManagementPage.platformTable
  91. .locator('tbody tr')
  92. .filter({ hasText: platformName });
  93. // 验证编辑按钮存在
  94. const editButton = platformRow.getByRole('button', { name: '编辑' });
  95. await expect(editButton).toBeVisible();
  96. // 验证删除按钮存在
  97. const deleteButton = platformRow.getByRole('button', { name: '删除' });
  98. await expect(deleteButton).toBeVisible();
  99. // 清理测试数据
  100. await platformManagementPage.deletePlatform(platformName);
  101. });
  102. test('应该显示创建时间列', async ({ platformManagementPage }) => {
  103. // 创建测试平台
  104. const timestamp = Date.now();
  105. const platformName = `创建时间测试_${timestamp}`;
  106. await platformManagementPage.createPlatform({
  107. platformName,
  108. contactPerson: `测试联系人_${timestamp}`,
  109. contactPhone: '13700137000',
  110. contactEmail: `time_${timestamp}@test.com`,
  111. });
  112. // 刷新页面
  113. await platformManagementPage.page.reload();
  114. await platformManagementPage.goto();
  115. // 查找平台行
  116. const platformRow = platformManagementPage.platformTable
  117. .locator('tbody tr')
  118. .filter({ hasText: platformName });
  119. // 验证创建时间列(第六列)存在且有内容
  120. const timeCell = platformRow.locator('td').nth(5);
  121. const timeText = await timeCell.textContent();
  122. expect(timeText).toBeTruthy();
  123. expect(timeText?.trim()).not.toBe('');
  124. // 清理测试数据
  125. await platformManagementPage.deletePlatform(platformName);
  126. });
  127. });
  128. test.describe('列表搜索功能', () => {
  129. // 存储创建的平台名称,用于清理
  130. const createdPlatforms: string[] = [];
  131. let searchTestTimestamp: number;
  132. test.beforeEach(async ({ platformManagementPage }) => {
  133. // 创建几个测试平台用于搜索测试
  134. searchTestTimestamp = Date.now();
  135. const platformA = `搜索测试平台A_${searchTestTimestamp}`;
  136. const platformB = `搜索测试平台B_${searchTestTimestamp}`;
  137. const platformC = `搜索测试平台C_${searchTestTimestamp}`;
  138. createdPlatforms.push(platformA, platformB, platformC);
  139. await platformManagementPage.createPlatform({
  140. platformName: platformA,
  141. contactPerson: `搜索联系人A_${searchTestTimestamp}`,
  142. contactPhone: '13800001111',
  143. contactEmail: `search_a_${searchTestTimestamp}@test.com`,
  144. });
  145. await platformManagementPage.createPlatform({
  146. platformName: platformB,
  147. contactPerson: `搜索联系人B_${searchTestTimestamp}`,
  148. contactPhone: '13800002222',
  149. contactEmail: `search_b_${searchTestTimestamp}@test.com`,
  150. });
  151. await platformManagementPage.createPlatform({
  152. platformName: platformC,
  153. contactPerson: `搜索联系人C_${searchTestTimestamp}`,
  154. contactPhone: '13800003333',
  155. contactEmail: `search_c_${searchTestTimestamp}@test.com`,
  156. });
  157. // 刷新页面确保数据加载
  158. await platformManagementPage.page.reload();
  159. await platformManagementPage.goto();
  160. });
  161. test('应该能通过平台名称搜索', async ({ platformManagementPage }) => {
  162. // 使用 beforeEach 中创建的平台名称进行搜索
  163. const searchName = `搜索测试平台A_${searchTestTimestamp}`;
  164. // 搜索平台
  165. const found = await platformManagementPage.searchByName(searchName);
  166. expect(found).toBe(true);
  167. // 验证搜索结果只显示匹配的平台
  168. const platformRow = platformManagementPage.platformTable
  169. .locator('tbody tr')
  170. .filter({ hasText: searchName });
  171. const rowCount = await platformRow.count();
  172. expect(rowCount).toBeGreaterThan(0);
  173. });
  174. test('搜索不存在的平台应返回空结果', async ({ platformManagementPage }) => {
  175. // 搜索不存在的平台
  176. const nonExistentName = `不存在的平台_${Date.now()}`;
  177. await platformManagementPage.searchInput.fill(nonExistentName);
  178. await platformManagementPage.searchButton.click();
  179. // 等待搜索结果更新(使用表格内容变化而非固定超时)
  180. await platformManagementPage.page.waitForLoadState('networkidle');
  181. // 验证搜索结果为空
  182. const exists = await platformManagementPage.platformExists(nonExistentName);
  183. expect(exists).toBe(false);
  184. });
  185. test('应该能清空搜索条件', async ({ platformManagementPage }) => {
  186. // 先执行一次搜索
  187. await platformManagementPage.searchInput.fill(`搜索测试平台A_${searchTestTimestamp}`);
  188. await platformManagementPage.searchButton.click();
  189. // 等待搜索完成
  190. await platformManagementPage.page.waitForLoadState('networkidle');
  191. // 清空搜索
  192. await platformManagementPage.searchInput.fill('');
  193. await platformManagementPage.searchButton.click();
  194. // 等待列表刷新
  195. await platformManagementPage.page.waitForLoadState('networkidle');
  196. // 验证所有数据都显示出来了
  197. const tbody = platformManagementPage.platformTable.locator('tbody tr');
  198. const rowCount = await tbody.count();
  199. expect(rowCount).toBeGreaterThan(0);
  200. });
  201. test.afterEach(async ({ platformManagementPage }) => {
  202. // 清理测试数据(使用实际创建的平台名称)
  203. for (const platformName of createdPlatforms) {
  204. try {
  205. await platformManagementPage.deletePlatform(platformName);
  206. } catch (error) {
  207. // 忽略删除失败(平台可能已被删除或从未创建成功)
  208. console.debug(`清理平台 ${platformName} 时出错,忽略:`, error);
  209. }
  210. }
  211. // 清空数组
  212. createdPlatforms.length = 0;
  213. });
  214. });
  215. test.describe('空列表状态', () => {
  216. test('当列表为空时应显示空状态提示', async ({ platformManagementPage }) => {
  217. // 获取当前所有平台
  218. const tbody = platformManagementPage.platformTable.locator('tbody tr');
  219. const initialCount = await tbody.count();
  220. // 如果环境已有数据,跳过此测试
  221. // 注意:此测试需要在空数据环境中运行,或者需要实现删除所有数据的逻辑
  222. // 由于删除所有数据可能影响其他测试,这里使用条件跳过
  223. test.skip(
  224. initialCount > 0,
  225. `环境已有 ${initialCount} 个平台数据,跳过空状态测试。此测试需要在空数据环境中运行。`
  226. );
  227. // 以下代码仅在无数据环境中执行:
  228. // 验证空状态提示显示
  229. const emptyState = platformManagementPage.page.getByText(/暂无数据|无平台|empty/i);
  230. await expect(emptyState).toBeVisible();
  231. });
  232. test('空状态下创建平台按钮仍然可用', async ({ platformManagementPage }) => {
  233. // 无论列表是否为空,创建按钮都应该可用
  234. await expect(platformManagementPage.createPlatformButton).toBeVisible();
  235. await expect(platformManagementPage.createPlatformButton).toBeEnabled();
  236. });
  237. });
  238. test.describe('列表数据刷新', () => {
  239. test('创建新平台后列表应该自动更新', async ({ platformManagementPage }) => {
  240. const timestamp = Date.now();
  241. const platformName = `刷新测试平台_${timestamp}`;
  242. // 创建平台
  243. await platformManagementPage.createPlatform({
  244. platformName,
  245. contactPerson: `刷新测试联系人_${timestamp}`,
  246. contactPhone: '13600136000',
  247. contactEmail: `refresh_${timestamp}@test.com`,
  248. });
  249. // 验证平台出现在列表中(使用重试机制)
  250. await expect(async () => {
  251. const exists = await platformManagementPage.platformExists(platformName);
  252. expect(exists).toBe(true);
  253. }).toPass({ timeout: TIMEOUTS.DIALOG });
  254. // 清理测试数据
  255. await platformManagementPage.deletePlatform(platformName);
  256. });
  257. test('删除平台后列表应该自动更新', async ({ platformManagementPage }) => {
  258. const timestamp = Date.now();
  259. const platformName = `删除刷新测试_${timestamp}`;
  260. // 创建平台
  261. await platformManagementPage.createPlatform({
  262. platformName,
  263. contactPerson: `删除刷新联系人_${timestamp}`,
  264. contactPhone: '13500135000',
  265. contactEmail: `delete_refresh_${timestamp}@test.com`,
  266. });
  267. // 验证平台存在
  268. expect(await platformManagementPage.platformExists(platformName)).toBe(true);
  269. // 删除平台
  270. await platformManagementPage.deletePlatform(platformName);
  271. // 验证平台已从列表中移除
  272. await expect(async () => {
  273. const exists = await platformManagementPage.platformExists(platformName);
  274. expect(exists).toBe(false);
  275. }).toPass({ timeout: TIMEOUTS.DIALOG });
  276. });
  277. });
  278. test.describe('列表表格结构', () => {
  279. test('应该有正确的表头', async ({ platformManagementPage }) => {
  280. // 验证表格存在
  281. const table = platformManagementPage.platformTable;
  282. await expect(table).toBeVisible();
  283. // 验证表头存在
  284. const thead = table.locator('thead');
  285. await expect(thead).toBeVisible();
  286. // 验证表头包含预期的列
  287. await expect(thead).toContainText('ID');
  288. await expect(thead).toContainText('平台名称');
  289. await expect(thead).toContainText('联系人');
  290. await expect(thead).toContainText('联系电话');
  291. await expect(thead).toContainText('联系邮箱');
  292. });
  293. test('表格应该有tbody元素', async ({ platformManagementPage }) => {
  294. const tbody = platformManagementPage.platformTable.locator('tbody');
  295. await expect(tbody).toBeVisible();
  296. });
  297. });
  298. test.describe('分页功能(如果适用)', () => {
  299. // 检查是否有分页组件的辅助函数
  300. let hasPaginationComponent = false;
  301. test.beforeAll(async ({ platformManagementPage }) => {
  302. // 在所有测试前检查分页组件是否存在
  303. const pagination = platformManagementPage.page.locator('.pagination, [data-testid="pagination"]');
  304. hasPaginationComponent = await pagination.count() > 0;
  305. });
  306. test('检查分页组件是否存在', async ({ platformManagementPage }) => {
  307. // 如果没有分页组件,跳过整个 describe 块的测试
  308. test.skip(!hasPaginationComponent, '当前列表没有分页功能,跳过分页相关测试');
  309. // 如果存在分页,验证其可见性
  310. const pagination = platformManagementPage.page.locator('.pagination, [data-testid="pagination"]');
  311. await expect(pagination.first()).toBeVisible();
  312. });
  313. // 注意:以下测试需要分页组件存在,并需要创建足够的测试数据(超过一页的数据量)
  314. // 由于创建大量测试数据可能影响测试速度和稳定性,这里暂时跳过
  315. // 如果需要实现完整的分页测试,需要:
  316. // 1. 创建超过每页显示数量的平台数据
  317. // 2. 验证分页切换功能
  318. // 3. 验证每页显示数量选择
  319. test.skip(true, '分页功能完整测试需要创建大量测试数据,暂时跳过。如需测试,请在测试环境创建足够的数据后运行。');
  320. });
  321. test.describe('列表交互测试', () => {
  322. test('点击编辑按钮应该打开编辑对话框', async ({ platformManagementPage }) => {
  323. // 创建测试平台
  324. const timestamp = Date.now();
  325. const platformName = `编辑交互测试_${timestamp}`;
  326. await platformManagementPage.createPlatform({
  327. platformName,
  328. contactPerson: `编辑测试联系人_${timestamp}`,
  329. contactPhone: '13400134000',
  330. contactEmail: `edit_interact_${timestamp}@test.com`,
  331. });
  332. // 刷新页面
  333. await platformManagementPage.page.reload();
  334. await platformManagementPage.goto();
  335. // 点击编辑按钮
  336. await platformManagementPage.openEditDialog(platformName);
  337. // 验证编辑对话框打开
  338. const dialog = platformManagementPage.page.locator('[role="dialog"]');
  339. await expect(dialog).toBeVisible();
  340. // 验证编辑对话框标题
  341. await expect(platformManagementPage.editDialogTitle).toBeVisible();
  342. // 关闭对话框
  343. await platformManagementPage.cancelDialog();
  344. // 清理测试数据
  345. await platformManagementPage.deletePlatform(platformName);
  346. });
  347. test('点击删除按钮应该打开删除确认对话框', async ({ platformManagementPage }) => {
  348. // 创建测试平台
  349. const timestamp = Date.now();
  350. const platformName = `删除交互测试_${timestamp}`;
  351. await platformManagementPage.createPlatform({
  352. platformName,
  353. contactPerson: `删除测试联系人_${timestamp}`,
  354. contactPhone: '13300133000',
  355. contactEmail: `delete_interact_${timestamp}@test.com`,
  356. });
  357. // 刷新页面
  358. await platformManagementPage.page.reload();
  359. await platformManagementPage.goto();
  360. // 点击删除按钮
  361. await platformManagementPage.openDeleteDialog(platformName);
  362. // 验证删除确认对话框打开
  363. const dialog = platformManagementPage.page.locator('[role="alertdialog"]');
  364. await expect(dialog).toBeVisible();
  365. // 取消删除
  366. await platformManagementPage.cancelDelete();
  367. // 验证平台仍然存在
  368. expect(await platformManagementPage.platformExists(platformName)).toBe(true);
  369. // 清理测试数据
  370. await platformManagementPage.deletePlatform(platformName);
  371. });
  372. });
  373. });