utils.ts 11 KB

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