company-list.spec.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. import { TIMEOUTS } from '../../utils/timeouts';
  2. import { test, expect } from '../../utils/test-setup';
  3. /**
  4. * 公司列表表格列索引常量
  5. */
  6. const TABLE_COLUMNS = {
  7. /** 公司名称 */
  8. NAME: 0,
  9. /** 平台 */
  10. PLATFORM: 1,
  11. /** 联系人 */
  12. CONTACT_PERSON: 2,
  13. /** 联系电话 */
  14. CONTACT_PHONE: 3,
  15. /** 状态 */
  16. STATUS: 4,
  17. /** 创建时间 */
  18. CREATED_AT: 5,
  19. /** 操作 */
  20. ACTIONS: 6,
  21. } as const;
  22. /**
  23. * 生成唯一的测试数据名称
  24. */
  25. function generateTestName(prefix: string): string {
  26. const timestamp = Date.now();
  27. const random = Math.floor(Math.random() * 1000);
  28. return `${prefix}_${timestamp}_${random}`;
  29. }
  30. test.describe('公司列表管理', () => {
  31. // 测试数据名称
  32. let testCompanyName: string;
  33. test.beforeEach(async ({ adminLoginPage, companyManagementPage }) => {
  34. // 生成唯一的测试数据名称
  35. testCompanyName = generateTestName('E2E测试公司');
  36. // 以管理员身份登录后台
  37. await adminLoginPage.goto();
  38. await adminLoginPage.login('admin', 'admin123');
  39. await companyManagementPage.goto();
  40. // 创建测试数据(如果不存在)
  41. const exists = await companyManagementPage.companyExists(testCompanyName);
  42. if (!exists) {
  43. // 先需要选择平台,使用 "测试平台"(如果存在)
  44. const result = await companyManagementPage.createCompany({
  45. companyName: testCompanyName,
  46. contactPerson: 'E2E测试联系人',
  47. contactPhone: '13900139000',
  48. }, '测试平台');
  49. // 如果创建失败(可能是平台不存在),尝试不选平台创建
  50. if (!result.success && result.errorMessage?.includes('平台')) {
  51. await companyManagementPage.createCompany({
  52. companyName: testCompanyName,
  53. contactPerson: 'E2E测试联系人',
  54. contactPhone: '13900139000',
  55. });
  56. }
  57. }
  58. });
  59. test.afterEach(async ({ companyManagementPage }) => {
  60. // 清理测试数据
  61. await companyManagementPage.deleteCompany(testCompanyName);
  62. });
  63. test.describe('页面加载验证', () => {
  64. test('应该成功导航到公司管理页面', async ({ companyManagementPage, page }) => {
  65. // 验证页面 URL
  66. await expect(page).toHaveURL(/\/admin\/companies/);
  67. });
  68. test('应该显示正确的页面标题', async ({ companyManagementPage }) => {
  69. await expect(companyManagementPage.pageTitle).toBeVisible();
  70. await expect(companyManagementPage.pageTitle).toHaveText('公司管理');
  71. });
  72. test('应该加载公司列表表格', async ({ companyManagementPage }) => {
  73. await expect(companyManagementPage.companyTable).toBeVisible();
  74. });
  75. });
  76. test.describe('公司数据展示验证', () => {
  77. test('应该正确显示公司名称', async ({ companyManagementPage }) => {
  78. // 使用 filter 精确匹配测试公司行
  79. const companyRow = companyManagementPage.companyTable
  80. .locator('tbody tr')
  81. .filter({ hasText: testCompanyName });
  82. await expect(companyRow).toBeVisible();
  83. // 验证第0列(公司名称)
  84. const nameCell = companyRow.locator('td').nth(TABLE_COLUMNS.NAME);
  85. await expect(nameCell).toBeVisible();
  86. const actualName = await nameCell.textContent();
  87. expect(actualName?.trim()).toBe(testCompanyName);
  88. });
  89. test('应该正确显示关联平台', async ({ companyManagementPage }) => {
  90. const companyRow = companyManagementPage.companyTable
  91. .locator('tbody tr')
  92. .filter({ hasText: testCompanyName });
  93. await expect(companyRow).toBeVisible();
  94. // 验证第1列(平台)
  95. const platformCell = companyRow.locator('td').nth(TABLE_COLUMNS.PLATFORM);
  96. await expect(platformCell).toBeVisible();
  97. });
  98. test('应该正确显示联系人信息', async ({ companyManagementPage }) => {
  99. const companyRow = companyManagementPage.companyTable
  100. .locator('tbody tr')
  101. .filter({ hasText: testCompanyName });
  102. await expect(companyRow).toBeVisible();
  103. // 验证第2列(联系人)
  104. const contactPersonCell = companyRow.locator('td').nth(TABLE_COLUMNS.CONTACT_PERSON);
  105. await expect(contactPersonCell).toBeVisible();
  106. const contactPerson = await contactPersonCell.textContent();
  107. expect(contactPerson?.trim()).toBe('E2E测试联系人');
  108. // 验证第3列(联系电话)
  109. const contactPhoneCell = companyRow.locator('td').nth(TABLE_COLUMNS.CONTACT_PHONE);
  110. await expect(contactPhoneCell).toBeVisible();
  111. const contactPhone = await contactPhoneCell.textContent();
  112. expect(contactPhone?.trim()).toBe('13900139000');
  113. });
  114. test('应该正确显示状态徽章', async ({ companyManagementPage }) => {
  115. const companyRow = companyManagementPage.companyTable
  116. .locator('tbody tr')
  117. .filter({ hasText: testCompanyName });
  118. await expect(companyRow).toBeVisible();
  119. // 验证第4列(状态:启用/禁用)
  120. const statusCell = companyRow.locator('td').nth(TABLE_COLUMNS.STATUS);
  121. await expect(statusCell).toBeVisible();
  122. // 验证状态文本是"启用"或"禁用"
  123. const statusText = await statusCell.textContent();
  124. expect(statusText).toBeTruthy();
  125. expect(['启用', '禁用']).toContain(statusText!.trim());
  126. });
  127. test('应该正确显示创建时间', async ({ companyManagementPage }) => {
  128. const companyRow = companyManagementPage.companyTable
  129. .locator('tbody tr')
  130. .filter({ hasText: testCompanyName });
  131. await expect(companyRow).toBeVisible();
  132. // 验证第5列(创建时间)
  133. const createdAtCell = companyRow.locator('td').nth(TABLE_COLUMNS.CREATED_AT);
  134. await expect(createdAtCell).toBeVisible();
  135. // 验证日期格式(应该包含日期分隔符)
  136. const createdAt = await createdAtCell.textContent();
  137. expect(createdAt).toBeTruthy();
  138. expect(createdAt).toMatch(/\d{4}[-/]\d{1,2}[-/]\d{1,2}/);
  139. });
  140. });
  141. test.describe('列表功能验证', () => {
  142. test('应该显示创建公司按钮', async ({ companyManagementPage }) => {
  143. await expect(companyManagementPage.createCompanyButton).toBeVisible();
  144. });
  145. test('应该显示搜索输入框和按钮', async ({ companyManagementPage }) => {
  146. await expect(companyManagementPage.searchInput).toBeVisible();
  147. await expect(companyManagementPage.searchButton).toBeVisible();
  148. });
  149. test('应该能够按公司名称搜索', async ({ companyManagementPage }) => {
  150. // 搜索测试公司
  151. const searchResult = await companyManagementPage.searchByName(testCompanyName);
  152. // 验证搜索结果包含测试公司
  153. expect(searchResult).toBe(true);
  154. });
  155. test('应该显示操作按钮', async ({ companyManagementPage }) => {
  156. const companyRow = companyManagementPage.companyTable
  157. .locator('tbody tr')
  158. .filter({ hasText: testCompanyName });
  159. await expect(companyRow).toBeVisible();
  160. // 验证第6列(操作列)包含按钮
  161. const actionCell = companyRow.locator('td').nth(TABLE_COLUMNS.ACTIONS);
  162. await expect(actionCell).toBeVisible();
  163. // 验证操作列中有按钮(编辑和删除按钮使用图标,没有文本)
  164. const buttons = actionCell.getByRole('button');
  165. const buttonCount = await buttons.count();
  166. expect(buttonCount).toBeGreaterThanOrEqual(1);
  167. });
  168. });
  169. test.describe('空数据状态验证', () => {
  170. test('当搜索无结果时应该显示提示', async ({ companyManagementPage, page }) => {
  171. // 搜索一个不存在的公司名称
  172. const nonExistentName = generateTestName('不存在的公司');
  173. await companyManagementPage.searchInput.fill(nonExistentName);
  174. await companyManagementPage.searchButton.click();
  175. // 等待搜索完成
  176. await page.waitForTimeout(TIMEOUTS.LONG);
  177. // 验证:可能显示"暂无数据"提示,或表格为空
  178. const tableBody = companyManagementPage.companyTable.locator('tbody tr');
  179. const rowCount = await tableBody.count();
  180. if (rowCount === 0) {
  181. // 如果表格为空,检查是否有无数据提示
  182. const emptyMessages = [
  183. page.getByText(/暂无数据/),
  184. page.getByText(/无数据/),
  185. page.getByText(/No data/),
  186. page.getByText(/没有找到/),
  187. ];
  188. let foundEmptyMessage = false;
  189. for (const message of emptyMessages) {
  190. if (await message.count() > 0) {
  191. foundEmptyMessage = true;
  192. break;
  193. }
  194. }
  195. // 如果没有找到无数据提示,测试仍然通过(表格为空已说明问题)
  196. expect(rowCount).toBe(0);
  197. } else {
  198. // 如果有数据,至少说明搜索功能在工作
  199. expect(rowCount).toBeGreaterThanOrEqual(0);
  200. }
  201. });
  202. });
  203. test.describe('分页功能验证', () => {
  204. test('应该能够看到分页控件(如果存在)', async ({ companyManagementPage, page }) => {
  205. // 检查是否有分页控件
  206. const paginationSelectors = [
  207. page.getByRole('navigation', { name: /pagination|分页/i }),
  208. page.getByLabel(/pagination|分页/i),
  209. page.locator('[data-testid="pagination"]'),
  210. ];
  211. let hasPagination = false;
  212. for (const selector of paginationSelectors) {
  213. if (await selector.count() > 0) {
  214. hasPagination = true;
  215. await expect(selector.first()).toBeVisible();
  216. break;
  217. }
  218. }
  219. // 如果没有分页控件,说明数据量不足触发分页
  220. // 这是一个合理的测试结果
  221. if (!hasPagination) {
  222. // 验证至少有数据在表格中
  223. const rowCount = await companyManagementPage.companyTable.locator('tbody tr').count();
  224. expect(rowCount).toBeGreaterThanOrEqual(1);
  225. }
  226. });
  227. });
  228. });