order-person.spec.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. import { test, expect } from '../../utils/test-setup';
  2. import { readFileSync } from 'fs';
  3. import { join, dirname } from 'path';
  4. import { fileURLToPath } from 'url';
  5. const __filename = fileURLToPath(import.meta.url);
  6. const __dirname = dirname(__filename);
  7. const testUsers = JSON.parse(readFileSync(join(__dirname, '../../fixtures/test-users.json'), 'utf-8'));
  8. async function selectDisabledPersonInAddDialog(
  9. page: Parameters<typeof test>[0]['prototype'],
  10. personName?: string
  11. ): Promise<boolean> {
  12. const selectPersonButton = page.getByRole('button', { name: '选择残疾人' });
  13. await selectPersonButton.click();
  14. await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 5000 });
  15. let hasData = false;
  16. try {
  17. if (personName) {
  18. const personRow = page.locator('table tbody tr').filter({ hasText: personName }).first();
  19. const rowCount = await personRow.count();
  20. if (rowCount > 0) {
  21. const checkbox = personRow.locator('input[type="checkbox"]').first();
  22. await checkbox.check();
  23. console.debug('已选择残疾人: ' + personName);
  24. hasData = true;
  25. } else {
  26. console.debug('未找到残疾人: ' + personName);
  27. }
  28. } else {
  29. const firstCheckbox = page.locator('table tbody tr').first().locator('input[type="checkbox"]').first();
  30. await firstCheckbox.waitFor({ state: 'visible', timeout: 3000 });
  31. await firstCheckbox.check();
  32. console.debug('已选择第一个残疾人');
  33. hasData = true;
  34. }
  35. } catch (error) {
  36. console.debug('没有可用的残疾人数据');
  37. hasData = false;
  38. }
  39. if (hasData) {
  40. const confirmButton = page.getByRole('button', { name: /^(确定|确认|选择)$/ });
  41. await confirmButton.click().catch(() => {
  42. console.debug('没有找到确认按钮,尝试关闭对话框');
  43. page.keyboard.press('Escape');
  44. });
  45. } else {
  46. await page.keyboard.press('Escape').catch(() => {
  47. console.debug('无法关闭对话框,可能已经自动关闭');
  48. });
  49. }
  50. await page.waitForTimeout(500);
  51. return hasData;
  52. }
  53. function generateUniqueTestData() {
  54. const timestamp = Date.now();
  55. const random = Math.floor(Math.random() * 10000);
  56. return {
  57. orderName: '测试订单_' + timestamp + '_' + random,
  58. personName: '测试残疾人_' + timestamp + '_' + random,
  59. hireDate: '2025-01-15',
  60. salary: 5000,
  61. };
  62. }
  63. test.describe('订单人员关联测试', () => {
  64. test.beforeEach(async ({ adminLoginPage, orderManagementPage }) => {
  65. await adminLoginPage.goto();
  66. await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
  67. await adminLoginPage.expectLoginSuccess();
  68. await orderManagementPage.goto();
  69. });
  70. test.describe('添加人员到订单', () => {
  71. test('应该能打开订单人员管理对话框', async ({ orderManagementPage }) => {
  72. const testData = generateUniqueTestData();
  73. await orderManagementPage.openCreateDialog();
  74. await orderManagementPage.page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  75. await orderManagementPage.page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  76. const hasDisabledPerson = await selectDisabledPersonInAddDialog(orderManagementPage.page);
  77. if (!hasDisabledPerson) {
  78. await orderManagementPage.cancelDialog();
  79. test.skip();
  80. return;
  81. }
  82. await orderManagementPage.submitForm();
  83. await orderManagementPage.waitForDialogClosed();
  84. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  85. const dialog = orderManagementPage.page.locator('[role="dialog"]');
  86. await expect(dialog).toBeVisible();
  87. await orderManagementPage.closeDetailDialog();
  88. });
  89. test('应该能添加残疾人到订单', async ({ orderManagementPage, page }) => {
  90. const testData = generateUniqueTestData();
  91. await orderManagementPage.openCreateDialog();
  92. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  93. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  94. const hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  95. if (!hasDisabledPerson) {
  96. await orderManagementPage.cancelDialog();
  97. test.skip();
  98. return;
  99. }
  100. await orderManagementPage.submitForm();
  101. await orderManagementPage.waitForDialogClosed();
  102. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  103. const addButton = page.getByRole('button', { name: /添加人员|新增人员/ });
  104. await addButton.click();
  105. await page.waitForTimeout(300);
  106. const selected = await selectDisabledPersonInAddDialog(page);
  107. if (!selected) {
  108. await page.keyboard.press('Escape');
  109. await orderManagementPage.closeDetailDialog();
  110. test.skip();
  111. return;
  112. }
  113. await page.getByLabel(/入职日期/).fill(testData.hireDate);
  114. await page.getByLabel(/薪资|工资/).fill(String(testData.salary));
  115. const submitButton = page.getByRole('button', { name: /^(添加|确定|保存)$/ });
  116. await submitButton.click();
  117. await page.waitForLoadState('networkidle');
  118. await page.waitForTimeout(1000);
  119. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  120. const hasSuccess = await successToast.count() > 0;
  121. expect(hasSuccess).toBe(true);
  122. await orderManagementPage.closeDetailDialog();
  123. });
  124. test('添加的人员应该出现在订单详情中', async ({ orderManagementPage, page }) => {
  125. const testData = generateUniqueTestData();
  126. await orderManagementPage.openCreateDialog();
  127. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  128. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  129. const hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  130. if (!hasDisabledPerson) {
  131. await orderManagementPage.cancelDialog();
  132. test.skip();
  133. return;
  134. }
  135. await orderManagementPage.submitForm();
  136. await orderManagementPage.waitForDialogClosed();
  137. await orderManagementPage.openDetailDialog(testData.orderName);
  138. const personList = await orderManagementPage.getPersonListFromDetail();
  139. expect(personList.length).toBeGreaterThan(0);
  140. await orderManagementPage.closeDetailDialog();
  141. });
  142. });
  143. test.describe('管理工作状态', () => {
  144. test('应该能修改人员工作状态:未就业 → 待就业', async ({ orderManagementPage, page }) => {
  145. const testData = generateUniqueTestData();
  146. await orderManagementPage.openCreateDialog();
  147. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  148. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  149. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  150. if (!hasDisabledPerson) {
  151. await orderManagementPage.cancelDialog();
  152. test.skip();
  153. return;
  154. }
  155. await orderManagementPage.submitForm();
  156. await orderManagementPage.waitForDialogClosed();
  157. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  158. const initialPersonList = await orderManagementPage.getPersonListFromDetail();
  159. if (initialPersonList.length === 0 || !initialPersonList[0].name) {
  160. await orderManagementPage.closeDetailDialog();
  161. test.skip();
  162. return;
  163. }
  164. await orderManagementPage.updatePersonWorkStatus(initialPersonList[0].name, 'pending');
  165. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  166. const hasSuccess = await successToast.count() > 0;
  167. expect(hasSuccess).toBe(true);
  168. await orderManagementPage.closeDetailDialog();
  169. });
  170. test('应该能修改人员工作状态:待就业 → 已就业', async ({ orderManagementPage, page }) => {
  171. const testData = generateUniqueTestData();
  172. await orderManagementPage.openCreateDialog();
  173. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  174. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  175. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  176. if (!hasDisabledPerson) {
  177. await orderManagementPage.cancelDialog();
  178. test.skip();
  179. return;
  180. }
  181. await orderManagementPage.submitForm();
  182. await orderManagementPage.waitForDialogClosed();
  183. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  184. const personList = await orderManagementPage.getPersonListFromDetail();
  185. if (personList.length === 0 || !personList[0].name) {
  186. await orderManagementPage.closeDetailDialog();
  187. test.skip();
  188. return;
  189. }
  190. await orderManagementPage.updatePersonWorkStatus(personList[0].name, 'employed');
  191. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  192. const hasSuccess = await successToast.count() > 0;
  193. expect(hasSuccess).toBe(true);
  194. await orderManagementPage.closeDetailDialog();
  195. });
  196. test('应该能修改人员工作状态:已就业 → 已离职', async ({ orderManagementPage, page }) => {
  197. const testData = generateUniqueTestData();
  198. await orderManagementPage.openCreateDialog();
  199. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  200. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  201. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  202. if (!hasDisabledPerson) {
  203. await orderManagementPage.cancelDialog();
  204. test.skip();
  205. return;
  206. }
  207. await orderManagementPage.submitForm();
  208. await orderManagementPage.waitForDialogClosed();
  209. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  210. const personList = await orderManagementPage.getPersonListFromDetail();
  211. if (personList.length === 0 || !personList[0].name) {
  212. await orderManagementPage.closeDetailDialog();
  213. test.skip();
  214. return;
  215. }
  216. await orderManagementPage.updatePersonWorkStatus(personList[0].name, 'resigned');
  217. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  218. const hasSuccess = await successToast.count() > 0;
  219. expect(hasSuccess).toBe(true);
  220. await orderManagementPage.closeDetailDialog();
  221. });
  222. });
  223. test.describe('设置实际入职日期', () => {
  224. test('应该能设置人员的实际入职日期', async ({ orderManagementPage, page }) => {
  225. const testData = generateUniqueTestData();
  226. const actualHireDate = '2025-02-01';
  227. await orderManagementPage.openCreateDialog();
  228. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  229. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  230. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  231. if (!hasDisabledPerson) {
  232. await orderManagementPage.cancelDialog();
  233. test.skip();
  234. return;
  235. }
  236. await orderManagementPage.submitForm();
  237. await orderManagementPage.waitForDialogClosed();
  238. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  239. const personList = await orderManagementPage.getPersonListFromDetail();
  240. if (personList.length === 0 || !personList[0].name) {
  241. await orderManagementPage.closeDetailDialog();
  242. test.skip();
  243. return;
  244. }
  245. const personRow = page.locator('[role="dialog"]').locator('table tbody tr').filter({ hasText: personList[0].name }).first();
  246. const editButton = personRow.getByRole('button', { name: /编辑|修改/ });
  247. await editButton.click();
  248. await page.waitForTimeout(300);
  249. const actualHireDateInput = page.getByLabel(/实际入职日期/);
  250. await actualHireDateInput.fill(actualHireDate);
  251. const submitButton = page.getByRole('button', { name: /^(更新|保存|确定)$/ });
  252. await submitButton.click();
  253. await page.waitForLoadState('networkidle');
  254. await page.waitForTimeout(1000);
  255. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  256. const hasSuccess = await successToast.count() > 0;
  257. expect(hasSuccess).toBe(true);
  258. await orderManagementPage.closeDetailDialog();
  259. });
  260. });
  261. test.describe('人员离职', () => {
  262. test('应该能设置人员为已离职状态并设置离职日期', async ({ orderManagementPage, page }) => {
  263. const testData = generateUniqueTestData();
  264. const resignDate = '2025-03-15';
  265. await orderManagementPage.openCreateDialog();
  266. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  267. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  268. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  269. if (!hasDisabledPerson) {
  270. await orderManagementPage.cancelDialog();
  271. test.skip();
  272. return;
  273. }
  274. await orderManagementPage.submitForm();
  275. await orderManagementPage.waitForDialogClosed();
  276. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  277. const personList = await orderManagementPage.getPersonListFromDetail();
  278. if (personList.length === 0 || !personList[0].name) {
  279. await orderManagementPage.closeDetailDialog();
  280. test.skip();
  281. return;
  282. }
  283. const personRow = page.locator('[role="dialog"]').locator('table tbody tr').filter({ hasText: personList[0].name }).first();
  284. const editButton = personRow.getByRole('button', { name: /编辑|修改/ });
  285. await editButton.click();
  286. await page.waitForTimeout(300);
  287. await page.getByLabel(/工作状态/).click();
  288. await page.getByRole('option', { name: '已离职' }).click();
  289. const resignDateInput = page.getByLabel(/离职日期/);
  290. await resignDateInput.fill(resignDate);
  291. const submitButton = page.getByRole('button', { name: /^(更新|保存|确定)$/ });
  292. await submitButton.click();
  293. await page.waitForLoadState('networkidle');
  294. await page.waitForTimeout(1000);
  295. const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  296. const hasSuccess = await successToast.count() > 0;
  297. expect(hasSuccess).toBe(true);
  298. await orderManagementPage.closeDetailDialog();
  299. });
  300. test('离职后人员状态应显示为已离职', async ({ orderManagementPage, page }) => {
  301. const testData = generateUniqueTestData();
  302. await orderManagementPage.openCreateDialog();
  303. await page.getByLabel(/订单名称|名称/).fill(testData.orderName);
  304. await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
  305. let hasDisabledPerson = await selectDisabledPersonInAddDialog(page);
  306. if (!hasDisabledPerson) {
  307. await orderManagementPage.cancelDialog();
  308. test.skip();
  309. return;
  310. }
  311. await orderManagementPage.submitForm();
  312. await orderManagementPage.waitForDialogClosed();
  313. await orderManagementPage.openPersonManagementDialog(testData.orderName);
  314. const personList = await orderManagementPage.getPersonListFromDetail();
  315. if (personList.length === 0 || !personList[0].name) {
  316. await orderManagementPage.closeDetailDialog();
  317. test.skip();
  318. return;
  319. }
  320. const personRow = page.locator('[role="dialog"]').locator('table tbody tr').filter({ hasText: personList[0].name }).first();
  321. const editButton = personRow.getByRole('button', { name: /编辑|修改/ });
  322. await editButton.click();
  323. await page.waitForTimeout(300);
  324. await page.getByLabel(/工作状态/).click();
  325. await page.getByRole('option', { name: '已离职' }).click();
  326. const submitButton = page.getByRole('button', { name: /^(更新|保存|确定)$/ });
  327. await submitButton.click();
  328. await page.waitForLoadState('networkidle');
  329. await page.waitForTimeout(1000);
  330. const updatedPersonList = await orderManagementPage.getPersonListFromDetail();
  331. const resignedPerson = updatedPersonList.find(p => p.name === personList[0].name);
  332. expect(resignedPerson).toBeDefined();
  333. expect(resignedPerson?.workStatus).toBe('已离职');
  334. await orderManagementPage.closeDetailDialog();
  335. });
  336. });
  337. });