import {StaticResponse} from 'cypress/types/net-stubbing'; import menuJson from '../../fixtures/menu/basic.json'; /** 点击select具体项 */ export function selectClick(testid: string, eq = 0) { cy.getTestId(testid).click(); cy.getTestId(testid) .find('.rc-virtual-list-holder-inner') .children('.ant-select-item') .eq(eq) .click(); } /** 进入具体菜单 */ export function intoMenu(parent: string, child: string) { cy.wait('@loginIntercept'); const list = menuJson.data; const menu = list.find(val => val.name === child); menu && cy.visit(menu); } /** 校验select */ export function validateSelect(testid: string, value: string) { cy.getTestId(testid) .find('.ant-select-selection-item') .should('have.attr', 'title', value) .and('have.text', value); } /** 校验table内容 */ export function validateTableList(tableName: string) { cy.getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .eq(1) .should('have.text', 'page-1'); cy.getTestId(tableName) .siblings('.ant-pagination') .find('li[title="2"]') .click(); cy.getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .eq(1) .should('have.text', 'page-2'); } /** 选择时间组件 */ export function clickDatePicker(id: string) { cy.getTestId(id).click(); cy.get('.ant-picker-panels') .children() .eq(0) .find('.ant-picker-content') .find('tbody') .find('td') .eq(0) .click(); cy.get('.ant-picker-panels') .children() .eq(1) .find('.ant-picker-content') .find('tbody') .find('td') .eq(0) .click(); } /** 校验table search */ export function validateTableSearch( tableName: string, keys: ( | { id: string; type: 'select'; value: string; eq?: number; defaultValue?: string; } | {id: string; type: 'date'} | string )[], options: { toolId: string; url: string; }, ) { const {toolId, url} = options; cy.getTestId(tableName) .siblings('.ant-pagination') .find('li[title="2"]') .click(); function clear(data?: (typeof keys)[0]) { function clearData(key: (typeof keys)[0]) { if (typeof key === 'string') { cy.getTestId(toolId).find(`[data-testid="filter_${key}"]`).clear(); } else { const {id, type} = key; const clearId = type === 'select' ? '.ant-select-clear' : '.ant-picker-clear'; cy.getTestId(toolId) .find(`[data-testid="filter_${id}"]`) .trigger('mouseover') .find(clearId) .click(); } } if (data) { return clearData(data); } keys.forEach(clearData); } function validate(text: string, reset?: boolean) { !reset && cy.getTestId(toolId).find('[data-testid="search_btn"]').click(); cy.getTestId(toolId) .find('[data-testid="search_btn"]') .should('have.class', 'ant-btn-loading'); cy.getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .eq(1) .should('have.text', text); cy.getTestId(tableName) .siblings('.ant-pagination') .find('li[title="1"]') .should('have.class', 'ant-pagination-item-active'); cy.getTestId(toolId) .getTestId('search_btn') .should('not.have.class', 'ant-btn-loading'); } function eachAllField(skipValidate = false) { keys.forEach(function (key, idx) { if (idx > 0 && !skipValidate) { clear(keys[idx - 1]); } let validateText: string; if (typeof key === 'string') { cy.getTestId(toolId).find(`[data-testid="filter_${key}"]`).type(key); validateText = key; } else { const {id, type} = key; switch (type) { case 'select': selectClick(`filter_${id}`, key?.eq ?? 0); validateText = key.value; break; case 'date': clickDatePicker(`filter_${id}`); validateText = 'searchTime'; break; } } !skipValidate && validate(validateText); }); } eachAllField(); // 校验重置功能 eachAllField(true); cy.getTestId(toolId).find('[data-testid="reset_btn"]').click(); keys.forEach(function (key) { if (typeof key === 'string') { cy.getTestId(`filter_${key}`).invoke('val').should('be.empty'); } else { switch (key.type) { case 'select': if (key.defaultValue) { validateSelect(`filter_${key.id}`, key.defaultValue); break; } cy.getTestId(`filter_${key.id}`) .find('.ant-select-selection-placeholder') .should('exist'); break; case 'date': cy.getTestId(`filter_${key.id}`) .children('.ant-picker-input') .first() .find('input') .invoke('val') .should('be.empty'); cy.getTestId(`filter_${key.id}`) .children('.ant-picker-input') .last() .find('input') .invoke('val') .should('be.empty'); break; } } }); validate('page-1', true); // 校验刷新功能 cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="refresh_btn"]') .click(); cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="refresh_btn"]') .should('have.class', 'ant-btn-loading'); cy.wait(`@${url}`); cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="refresh_btn"]') .should('not.have.class', 'ant-btn-loading'); } /** 表格内按钮点击 */ export function tableBtnClick(tableName: string, index: number) { function getBtn() { return cy .getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .last() .children() .eq(index); } getBtn().click(); return getBtn; } /** 弹窗按钮校验 */ export function validateModalBtnGroup(modalName: string) { cy.getTestId(modalName) .getTestId('modal_btn_group') .find('.ant-btn') .should('have.class', 'ant-btn-loading'); } // 校验antd message内容 export function validateMessageContent(msg: string) { cy.get('.ant-message-notice-content').should('include.text', msg); } // 校验modal的操作结果 export function validateModalOperation(modalName: string, text: string) { cy.getTestId(modalName).find('form').submit(); validateModalBtnGroup(modalName); validateMessageContent(text); cy.getTestId(modalName).should('not.exist'); } /** 校验新增或修改事件 */ export function validatePut( modalName: string, tableName: string, options: {label: string}, ) { const {label} = options; function validateAdd( keys: ( | string | {id: string; type: 'select'} | {id: string; type: 'keySelect'} | {id: string; type: 'field'; value: string} )[], ) { cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="add_btn"]') .click(); cy.getTestId(modalName).should('exist').and('be.visible'); cy.getTestId(modalName).find('h3').should('have.text', `新增${label}`); keys.forEach(function (key) { if (typeof key === 'string') { cy.getTestId(`field_${key}`).type(key); } else { const {type, id} = key; switch (type) { case 'select': selectClick(`field_${id}`, 0); break; case 'field': cy.getTestId(`field_${id}`).clear().type(key.value); break; case 'keySelect': cy.get(`#field_${id}`).clear().type(id); selectClick(`field_${id}`, 0); break; } } }); validateModalOperation(modalName, '新增成功'); } function validateEdit( keys: {id: string; type: 'field' | 'select'; value: string}[], eq = 0, ) { tableBtnClick(tableName, eq); cy.getTestId(modalName).should('exist').and('be.visible'); cy.getTestId(modalName).find('h3').should('include.text', `修改${label}`); keys.forEach(function ({id, type, value}) { switch (type) { case 'field': cy.getTestId(`field_${id}`).should('have.value', value); break; case 'select': validateSelect(`field_${id}`, value); break; } }); validateModalOperation(modalName, '修改成功'); } return {validateAdd, validateEdit}; } /** 校验antd dialog信息 */ export function validateDialog( title: string, content: string, options?: {confirm?: boolean}, ) { const {confirm = true} = options ?? {}; cy.get('.ant-modal-confirm-title').should('include.text', title); cy.get('.ant-modal-confirm-content').should('include.text', content); cy.get('.ant-modal-confirm-btns') .children() .eq(confirm ? 1 : 0) .click(); } /** 校验删除 */ export function validateDelete( tableName: string, label: string, options: {eq?: number; title: string}, ) { const {eq = 1, title} = options; tableBtnClick(tableName, eq); cy.get('.ant-modal-content').should('be.visible'); validateDialog(title, `你确定要删除当前${label}吗?`); // 删除按钮在加载 cy.getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .last() .children() .eq(eq) .should('have.class', 'ant-btn-loading'); // 其他按钮禁用 cy.getTestId(tableName) .find('table') .find('.ant-table-tbody') .children('.ant-table-row') .first() .find('td') .last() .children() .each(function (el, idx) { if (idx !== eq) { expect(el).to.have.attr('disabled'); } }); validateMessageContent('删除成功'); } /** 校验导出 */ export function validateExport(tableName: string) { cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="export_btn"]') .click(); cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="export_btn"]') .should('have.class', 'ant-btn-loading'); cy.getTestId(tableName) .closest('.ant-card-body') .find('[data-testid="export_btn"]') .should('not.have.class', 'ant-btn-loading'); } /** 关闭modal */ export function closeModal() { cy.get('.ReactModal__Overlay').trigger('click', 'topRight'); } /** 选择所有的筛选框 */ export function selectAllFilters(toolId: string, count: number) { cy.getTestId(toolId).getTestId('filter_btn').click(); cy.get('.ant-transfer') .find('.ant-transfer-list') .first() .find('.ant-transfer-list-header') .find('input[type="checkbox"]') .check(); cy.get('.ant-transfer') .find('.ant-transfer-operation') .find('button') .first() .click(); cy.getTestId('filter_select_modal').find('form').submit(); cy.getTestId(toolId) .children('.ant-space') .first() .children() .should('have.length', count + 1); } /** 生成返回内容 */ export function generateResult>( data: T, length: number, options: { limit: string; key?: string; isList?: boolean; title?: keyof T; value?: string; }, ) { const {key = 'id', isList = false, title, value, limit} = options; const result = Array.from({length: Number(limit)}, function (_, idx) { const temp = {...data, [key]: idx + 1}; return title ? {...temp, [title]: value ?? ''} : temp; }); return {msg: '200', data: isList ? {total: length, list: result} : result}; } /** 生成请求结果 */ export function generateNetworkResult< T extends Record, >(options: { search: URLSearchParams; basicData: T; reply: (params: StaticResponse) => void; title: keyof T; skipCondition?: (name: string) => boolean; replaceValue?: string; }) { const { search, basicData, reply, title, skipCondition = () => false, replaceValue, } = options; const page = search.get('page'), limit = search.get('limit'); for (const [name, searchValue] of search.entries()) { if ( name === 'page' || name === 'limit' || name === 'id' || skipCondition(name) ) continue; if (searchValue) { return reply({ body: generateResult(basicData, Number(limit) * 3, { limit, isList: true, title, value: name === 'startTime' || name === 'endTime' ? 'searchTime' : replaceValue ?? searchValue, }), }); } } if (search.has('id') && search.get('id').length > 0) { return reply({ body: generateResult(basicData, 1, {limit: '1', isList: true}), }); } reply({ body: generateResult(basicData, Number(limit) * 3, { limit, isList: true, title, value: replaceValue ?? `page-${page}`, }), }); }