utils.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. import {StaticResponse} from 'cypress/types/net-stubbing';
  2. /** 点击select具体项 */
  3. export function selectClick(testid: string, eq = 0) {
  4. cy.getTestId(testid).click();
  5. cy.getTestId(testid)
  6. .find('.rc-virtual-list-holder-inner')
  7. .children()
  8. .eq(eq)
  9. .click();
  10. }
  11. /** 进入具体菜单 */
  12. export function intoMenu(parent: string, child: string) {
  13. cy.getTestId('menu')
  14. .children()
  15. .each(function (el) {
  16. const titleElement = el.find('.ant-menu-submenu-title');
  17. if (titleElement.text() === parent) {
  18. titleElement.trigger('click');
  19. el.find(`ul>li[title="${child}"]`).trigger('click');
  20. }
  21. });
  22. }
  23. /** 校验select */
  24. export function validateSelect(testid: string, value: string) {
  25. cy.getTestId(testid)
  26. .find('.ant-select-selection-item')
  27. .should('have.attr', 'title', value)
  28. .and('have.text', value);
  29. }
  30. /** 校验table内容 */
  31. export function validateTableList(tableName: string) {
  32. cy.getTestId(tableName)
  33. .find('table')
  34. .find('.ant-table-tbody')
  35. .children('.ant-table-row')
  36. .first()
  37. .find('td')
  38. .eq(1)
  39. .should('include.text', 'page-1');
  40. cy.getTestId(tableName)
  41. .siblings('.ant-pagination')
  42. .find('li[title="2"]')
  43. .click();
  44. cy.getTestId(tableName)
  45. .find('table')
  46. .find('.ant-table-tbody')
  47. .children('.ant-table-row')
  48. .first()
  49. .find('td')
  50. .eq(1)
  51. .should('include.text', 'page-2');
  52. }
  53. /** 选择时间组件 */
  54. export function clickDatePicker(id: string) {
  55. cy.getTestId(id).click();
  56. cy.get('.ant-picker-panels')
  57. .children()
  58. .eq(0)
  59. .find('.ant-picker-content')
  60. .find('tbody')
  61. .find('td')
  62. .eq(0)
  63. .click();
  64. cy.get('.ant-picker-panels')
  65. .children()
  66. .eq(1)
  67. .find('.ant-picker-content')
  68. .find('tbody')
  69. .find('td')
  70. .eq(0)
  71. .click();
  72. }
  73. /** 校验table search */
  74. export function validateTableSearch(
  75. tableName: string,
  76. keys: (
  77. | {id: string; type: 'select'; value: string; eq?: number}
  78. | {id: string; type: 'date'}
  79. | string
  80. )[],
  81. options: {
  82. toolId: string;
  83. url: string;
  84. },
  85. ) {
  86. const {toolId, url} = options;
  87. cy.getTestId(tableName)
  88. .siblings('.ant-pagination')
  89. .find('li[title="2"]')
  90. .click();
  91. function clear(data?: (typeof keys)[0]) {
  92. function clearData(key: (typeof keys)[0]) {
  93. if (typeof key === 'string') {
  94. cy.getTestId(toolId).find(`[data-testid="filter_${key}"]`).clear();
  95. } else {
  96. const {id} = key;
  97. cy.getTestId(toolId)
  98. .find(`[data-testid="filter_${id}"]`)
  99. .trigger('mouseover')
  100. .find('.ant-select-clear')
  101. .click();
  102. }
  103. }
  104. if (data) {
  105. return clearData(data);
  106. }
  107. keys.forEach(clearData);
  108. }
  109. function validate(text: string, reset?: boolean) {
  110. !reset && cy.getTestId(toolId).find('[data-testid="search_btn"]').click();
  111. cy.getTestId(toolId)
  112. .find('[data-testid="search_btn"]')
  113. .should('have.class', 'ant-btn-loading');
  114. cy.getTestId(tableName)
  115. .find('table')
  116. .find('.ant-table-tbody')
  117. .children('.ant-table-row')
  118. .first()
  119. .find('td')
  120. .eq(1)
  121. .should('include.text', text);
  122. cy.getTestId(tableName)
  123. .siblings('.ant-pagination')
  124. .find('li[title="1"]')
  125. .should('have.class', 'ant-pagination-item-active');
  126. cy.getTestId(toolId)
  127. .getTestId('search_btn')
  128. .should('not.have.class', 'ant-btn-loading');
  129. }
  130. keys.forEach(function (key, idx) {
  131. if (idx > 0) {
  132. clear(keys[idx - 1]);
  133. }
  134. if (typeof key === 'string') {
  135. cy.getTestId(toolId).find(`[data-testid="filter_${key}"]`).type(key);
  136. validate(key);
  137. } else {
  138. const {id, type} = key;
  139. switch (type) {
  140. case 'select':
  141. selectClick(`filter_${id}`, key?.eq ?? 0);
  142. validate(key.value);
  143. break;
  144. case 'date':
  145. clickDatePicker(`filter_${id}`);
  146. validate('searchTime');
  147. break;
  148. }
  149. }
  150. });
  151. // 校验重置功能
  152. cy.getTestId(toolId).find('[data-testid="reset_btn"]').click();
  153. validate('page-1', true);
  154. // 校验刷新功能
  155. cy.getTestId(tableName)
  156. .closest('.ant-card-body')
  157. .find('[data-testid="refresh_btn"]')
  158. .click();
  159. cy.getTestId(tableName)
  160. .closest('.ant-card-body')
  161. .find('[data-testid="refresh_btn"]')
  162. .should('have.class', 'ant-btn-loading');
  163. cy.wait(`@${url}`);
  164. cy.getTestId(tableName)
  165. .closest('.ant-card-body')
  166. .find('[data-testid="refresh_btn"]')
  167. .should('not.have.class', 'ant-btn-loading');
  168. }
  169. /** 表格内按钮点击 */
  170. export function tableBtnClick(tableName: string, index: number) {
  171. function getBtn() {
  172. return cy
  173. .getTestId(tableName)
  174. .find('table')
  175. .find('.ant-table-tbody')
  176. .children('.ant-table-row')
  177. .first()
  178. .find('td')
  179. .last()
  180. .children()
  181. .eq(index);
  182. }
  183. getBtn().click();
  184. return getBtn;
  185. }
  186. /** 弹窗按钮校验 */
  187. export function validateModalBtnGroup(modalName: string) {
  188. cy.getTestId(modalName)
  189. .getTestId('modal_btn_group')
  190. .find('.ant-btn')
  191. .should('have.class', 'ant-btn-loading');
  192. }
  193. // 校验antd message内容
  194. export function validateMessageContent(msg: string) {
  195. cy.get('.ant-message-notice-content').should('include.text', msg);
  196. }
  197. // 校验modal的操作结果
  198. export function validateModalOperation(modalName: string, text: string) {
  199. cy.getTestId(modalName).find('form').submit();
  200. validateModalBtnGroup(modalName);
  201. validateMessageContent(text);
  202. cy.getTestId(modalName).should('not.exist');
  203. }
  204. /** 校验新增或修改事件 */
  205. export function validatePut(
  206. modalName: string,
  207. tableName: string,
  208. options: {label: string},
  209. ) {
  210. const {label} = options;
  211. function validateAdd(
  212. keys: (
  213. | string
  214. | {id: string; type: 'select'}
  215. | {id: string; type: 'keySelect'}
  216. | {id: string; type: 'field'; value: string}
  217. )[],
  218. ) {
  219. cy.getTestId(tableName)
  220. .closest('.ant-card-body')
  221. .find('[data-testid="add_btn"]')
  222. .click();
  223. cy.getTestId(modalName).should('exist').and('be.visible');
  224. cy.getTestId(modalName).find('h3').should('include.text', `新增${label}`);
  225. keys.forEach(function (key) {
  226. if (typeof key === 'string') {
  227. cy.getTestId(`field_${key}`).type(key);
  228. } else {
  229. const {type, id} = key;
  230. switch (type) {
  231. case 'select':
  232. selectClick(`field_${id}`, 0);
  233. break;
  234. case 'field':
  235. cy.getTestId(`field_${id}`).clear().type(key.value);
  236. break;
  237. case 'keySelect':
  238. cy.get(`#field_${id}`).clear().type(id);
  239. selectClick(`field_${id}`, 0);
  240. break;
  241. }
  242. }
  243. });
  244. validateModalOperation(modalName, '新增成功');
  245. }
  246. function validateEdit(
  247. keys: {id: string; type: 'field' | 'select'; value: string}[],
  248. eq = 0,
  249. ) {
  250. tableBtnClick(tableName, eq);
  251. cy.getTestId(modalName).should('exist').and('be.visible');
  252. cy.getTestId(modalName).find('h3').should('include.text', `修改${label}`);
  253. keys.forEach(function ({id, type, value}) {
  254. switch (type) {
  255. case 'field':
  256. cy.getTestId(`field_${id}`).should('have.value', value);
  257. break;
  258. case 'select':
  259. validateSelect(`field_${id}`, value);
  260. break;
  261. }
  262. });
  263. validateModalOperation(modalName, '修改成功');
  264. }
  265. return {validateAdd, validateEdit};
  266. }
  267. /** 校验antd dialog信息 */
  268. export function validateDialog(
  269. title: string,
  270. content: string,
  271. options?: {confirm?: boolean},
  272. ) {
  273. const {confirm = true} = options ?? {};
  274. cy.get('.ant-modal-confirm-title').should('include.text', title);
  275. cy.get('.ant-modal-confirm-content').should('include.text', content);
  276. cy.get('.ant-modal-confirm-btns')
  277. .children()
  278. .eq(confirm ? 1 : 0)
  279. .click();
  280. }
  281. /** 校验删除 */
  282. export function validateDelete(
  283. tableName: string,
  284. label: string,
  285. options: {eq?: number; title: string},
  286. ) {
  287. const {eq = 1, title} = options;
  288. tableBtnClick(tableName, eq);
  289. cy.get('.ant-modal-content').should('be.visible');
  290. validateDialog(title, `你确定要删除当前${label}吗?`);
  291. // 删除按钮在加载
  292. cy.getTestId(tableName)
  293. .find('table')
  294. .find('.ant-table-tbody')
  295. .children('.ant-table-row')
  296. .first()
  297. .find('td')
  298. .last()
  299. .children()
  300. .eq(eq)
  301. .should('have.class', 'ant-btn-loading');
  302. // 其他按钮禁用
  303. cy.getTestId(tableName)
  304. .find('table')
  305. .find('.ant-table-tbody')
  306. .children('.ant-table-row')
  307. .first()
  308. .find('td')
  309. .last()
  310. .children()
  311. .each(function (el, idx) {
  312. if (idx !== eq) {
  313. expect(el).to.have.attr('disabled');
  314. }
  315. });
  316. validateMessageContent('删除成功');
  317. }
  318. /** 校验导出 */
  319. export function validateExport(tableName: string) {
  320. const card = cy.getTestId(tableName).closest('.ant-card-body');
  321. card.getTestId('export_btn').click();
  322. card.getTestId('export_btn').should('have.class', 'ant-btn-loading');
  323. card.getTestId('export_btn').should('not.have.class', 'ant-btn-loading');
  324. }
  325. /** 关闭modal */
  326. export function closeModal() {
  327. cy.get('.ReactModal__Overlay').trigger('click', 'topRight');
  328. }
  329. /** 选择所有的筛选框 */
  330. export function selectAllFilters(toolId: string, count: number) {
  331. indexedDB.deleteDatabase('filterGroup');
  332. cy.getTestId(toolId).getTestId('filter_btn').click();
  333. cy.get('.ant-transfer')
  334. .find('.ant-transfer-list')
  335. .first()
  336. .find('.ant-transfer-list-header')
  337. .find('input[type="checkbox"]')
  338. .check();
  339. cy.get('.ant-transfer')
  340. .find('.ant-transfer-operation')
  341. .find('button')
  342. .first()
  343. .click();
  344. cy.getTestId('filter_select_modal').find('form').submit();
  345. cy.getTestId(toolId)
  346. .children('.ant-space')
  347. .first()
  348. .children()
  349. .should('have.length', count + 1);
  350. }
  351. /** 生成返回内容 */
  352. export function generateResult<T extends Record<string, any>>(
  353. data: T,
  354. length: number,
  355. options: {
  356. limit: string;
  357. key?: string;
  358. isList?: boolean;
  359. title?: keyof T;
  360. value?: string;
  361. },
  362. ) {
  363. const {key = 'id', isList = false, title, value, limit} = options;
  364. const result = Array.from({length: Number(limit)}, function (_, idx) {
  365. const temp = {...data, [key]: idx + 1};
  366. return title ? {...temp, [title]: value ?? ''} : temp;
  367. });
  368. return {msg: '200', data: isList ? {total: length, list: result} : result};
  369. }
  370. /** 生成请求结果 */
  371. export function generateNetworkResult<
  372. T extends Record<string, unknown>,
  373. >(options: {
  374. search: URLSearchParams;
  375. basicData: T;
  376. reply: (params: StaticResponse) => void;
  377. title: keyof T;
  378. skipCondition?: (name: string) => boolean;
  379. }) {
  380. const {
  381. search,
  382. basicData,
  383. reply,
  384. title,
  385. skipCondition = () => false,
  386. } = options;
  387. const page = search.get('page'),
  388. limit = search.get('limit');
  389. for (const [name, searchValue] of search.entries()) {
  390. if (
  391. name === 'page' ||
  392. name === 'limit' ||
  393. name === 'id' ||
  394. skipCondition(name)
  395. )
  396. continue;
  397. if (searchValue) {
  398. return reply({
  399. body: generateResult(basicData, Number(limit) * 3, {
  400. limit,
  401. isList: true,
  402. title,
  403. value:
  404. name === 'startTime' || name === 'endTime'
  405. ? 'searchTime'
  406. : searchValue,
  407. }),
  408. });
  409. }
  410. }
  411. if (search.has('id') && search.get('id').length > 0) {
  412. return reply({
  413. body: generateResult(basicData, 1, {limit: '1', isList: true}),
  414. });
  415. }
  416. reply({
  417. body: generateResult(basicData, Number(limit) * 3, {
  418. limit,
  419. isList: true,
  420. title,
  421. value: `page-${page}`,
  422. }),
  423. });
  424. }