Compare commits
2 Commits
c7f923d834
...
135718a8c3
| Author | SHA1 | Date | |
|---|---|---|---|
| 135718a8c3 | |||
| e55b84e3cc |
@ -1,4 +1,4 @@
|
|||||||
import { NumberInput } from '@/pages/components/numberInput';
|
import { NumberInput } from './numberInput';
|
||||||
import { PopupContent } from '@/pages/components/popupContent';
|
import { PopupContent } from './popupContent';
|
||||||
|
|
||||||
export { NumberInput, PopupContent };
|
export { NumberInput, PopupContent };
|
||||||
|
|||||||
@ -3,12 +3,13 @@ import { Locator, Page } from '@playwright/test';
|
|||||||
export class NumberInput {
|
export class NumberInput {
|
||||||
private readonly page: Page;
|
private readonly page: Page;
|
||||||
private readonly popupLocator: Locator;
|
private readonly popupLocator: Locator;
|
||||||
private readonly inputLocator: Locator;
|
private readonly inputLocators: { [key: string]: Locator } = {};
|
||||||
private readonly confirmButtonLocator: Locator;
|
private readonly confirmButtonLocator: Locator;
|
||||||
private readonly delButtonLocator: Locator;
|
private readonly delButtonLocator: Locator;
|
||||||
private readonly delAllButtonLocator: Locator;
|
private readonly delAllButtonLocator: Locator;
|
||||||
private readonly pointInputLocator: Locator;
|
// private readonly inputLocator: Locator;
|
||||||
private readonly commonInputLocator: Locator;
|
// private readonly pointInputLocator: Locator;
|
||||||
|
// private readonly commonInputLocator: Locator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数字键盘组件
|
* 数字键盘组件
|
||||||
@ -17,41 +18,60 @@ export class NumberInput {
|
|||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.popupLocator = this.page.locator('div.popup_content');
|
this.popupLocator = this.page.locator('div.popup_content');
|
||||||
this.commonInputLocator = this.popupLocator.getByPlaceholder('');
|
this.inputLocators = {
|
||||||
this.inputLocator = this.popupLocator.getByPlaceholder('请输入内容');
|
common: this.popupLocator.getByPlaceholder(''),
|
||||||
this.pointInputLocator = this.popupLocator.getByPlaceholder('请输入积分');
|
normal: this.popupLocator.getByPlaceholder('请输入内容'),
|
||||||
|
point: this.popupLocator.getByPlaceholder('请输入积分'),
|
||||||
|
};
|
||||||
|
// this.commonInputLocator = this.popupLocator.getByPlaceholder('');
|
||||||
|
// this.inputLocator = this.popupLocator.getByPlaceholder('请输入内容');
|
||||||
|
// this.pointInputLocator = this.popupLocator.getByPlaceholder('请输入积分');
|
||||||
this.confirmButtonLocator = this.popupLocator.locator('button.sure');
|
this.confirmButtonLocator = this.popupLocator.locator('button.sure');
|
||||||
this.delButtonLocator = this.popupLocator.locator('button.del');
|
this.delButtonLocator = this.popupLocator.locator('button.del');
|
||||||
this.delAllButtonLocator = this.popupLocator.locator('button.delAll');
|
this.delAllButtonLocator = this.popupLocator.locator('button.delAll');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置值
|
||||||
|
* @param type 输入框类型 (common, normal, point)
|
||||||
|
* @param value 输入值
|
||||||
|
*/
|
||||||
|
async setValue(type: 'common' | 'normal' | 'point', value: number | string): Promise<void> {
|
||||||
|
const locator = this.inputLocators[type];
|
||||||
|
if (!locator) {
|
||||||
|
throw new Error(`Invalid input type: ${type}`);
|
||||||
|
}
|
||||||
|
await locator.fill(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置通用值
|
* 设置通用值
|
||||||
*/
|
*/
|
||||||
async setCommonValue(value: number): Promise<void> {
|
// async setCommonValue(value: number): Promise<void> {
|
||||||
await this.commonInputLocator.fill(value.toString());
|
// await this.commonInputLocator.fill(value.toString());
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置值
|
* 设置值
|
||||||
*/
|
*/
|
||||||
async setValue(value: number): Promise<void> {
|
// async setValue(value: number): Promise<void> {
|
||||||
await this.inputLocator.fill(value.toString());
|
// await this.inputLocator.fill(value.toString());
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置文本
|
|
||||||
*/
|
|
||||||
async setString(value: string): Promise<void> {
|
|
||||||
await this.inputLocator.fill(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置积分值
|
* 设置积分值
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
async setPointValue(value: number): Promise<void> {
|
// async setPointValue(value: number): Promise<void> {
|
||||||
await this.pointInputLocator.fill(value.toString());
|
// await this.pointInputLocator.fill(value.toString());
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文本
|
||||||
|
*/
|
||||||
|
async setString(value: string): Promise<void> {
|
||||||
|
// await this.inputLocator.fill(value);
|
||||||
|
await this.inputLocators.normal.fill(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -14,20 +14,23 @@ export class CustomerAnalysisPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到子页面
|
* 跳转到子页面
|
||||||
* @param {string} subPageName
|
* @param {string} subPageName - 子页面名称,支持以下选项:
|
||||||
* - 项目余量分析
|
* - "项目余量分析"
|
||||||
* - 套餐消耗升单分析
|
* - "套餐消耗升单分析"
|
||||||
* - 顾客项目分析
|
* - "顾客项目分析"
|
||||||
*/
|
*/
|
||||||
gotoSubPage = async (subPageName: string) => {
|
gotoSubPage = async (subPageName: string) => {
|
||||||
if (!this.subPages.some(({ name }) => name === subPageName)) {
|
// 输入验证
|
||||||
|
if (!subPageName || typeof subPageName !== 'string') {
|
||||||
|
throw new Error('Invalid subPageName parameter');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常处理
|
||||||
|
if (!this.subPages || !this.subPages.some(({ name }) => name === subPageName)) {
|
||||||
throw new Error(`${subPageName} is not a valid sub page name`);
|
throw new Error(`${subPageName} is not a valid sub page name`);
|
||||||
}
|
}
|
||||||
const $dropDown = this.page
|
|
||||||
.locator('.top_tab .tab_item', {
|
const $dropDown = this.page.locator('.top_tab .tab_item', { hasText: '顾客分析' }).locator('.ant-dropdown-link');
|
||||||
hasText: '顾客分析',
|
|
||||||
})
|
|
||||||
.locator('.ant-dropdown-link');
|
|
||||||
|
|
||||||
await $dropDown.click();
|
await $dropDown.click();
|
||||||
await this.page.getByRole('menuitem', { name: subPageName }).click();
|
await this.page.getByRole('menuitem', { name: subPageName }).click();
|
||||||
|
|||||||
@ -8,7 +8,12 @@ export class CustomerDetailsPage {
|
|||||||
*/
|
*/
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.subPages = [{ name: '基本资料' }, { name: '流水' }, { name: '动态' }, { name: '日志' }];
|
this.subPages = [
|
||||||
|
{ name: '基本资料' },
|
||||||
|
{ name: '流水' },
|
||||||
|
{ name: '动态' },
|
||||||
|
{ name: '日志' }
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,12 +25,22 @@ export class CustomerDetailsPage {
|
|||||||
* - 日志
|
* - 日志
|
||||||
*/
|
*/
|
||||||
gotoSubPage = async (subPageName: string) => {
|
gotoSubPage = async (subPageName: string) => {
|
||||||
if (!this.subPages.findIndex(e => e.name === subPageName)) {
|
// 标准化输入字符串,去除前后空格并统一为小写
|
||||||
|
const normalizedSubPageName = subPageName.trim().toLowerCase();
|
||||||
|
|
||||||
|
// 检查子页面是否存在
|
||||||
|
if (!this.subPages.some(e => e.name.trim().toLowerCase() === normalizedSubPageName)) {
|
||||||
throw new Error(`${subPageName} is not in the subPages list`);
|
throw new Error(`${subPageName} is not in the subPages list`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取子页面元素并点击
|
||||||
const $subPage = this.page.getByRole('tab', { name: subPageName });
|
const $subPage = this.page.getByRole('tab', { name: subPageName });
|
||||||
await $subPage.click();
|
await $subPage.click();
|
||||||
await expect($subPage).toHaveClass(/active/);
|
await expect($subPage).toHaveClass(/active/);
|
||||||
await this.page.waitForLoadState();
|
} catch (error) {
|
||||||
|
// 捕获并抛出更明确的错误信息
|
||||||
|
throw new Error(`Failed to navigate to ${subPageName}: ${error.message}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,8 +60,14 @@ export class CustomerPage {
|
|||||||
* - 服务日志
|
* - 服务日志
|
||||||
*/
|
*/
|
||||||
gotoSubPage = async (subPageName: string) => {
|
gotoSubPage = async (subPageName: string) => {
|
||||||
|
// 输入验证
|
||||||
|
if (!subPageName || typeof subPageName !== 'string' || subPageName.trim() === '') {
|
||||||
|
throw new Error('子页面名称不能为空或无效');
|
||||||
|
}
|
||||||
|
|
||||||
const subPage = this.subPages.find(e => e.name === subPageName);
|
const subPage = this.subPages.find(e => e.name === subPageName);
|
||||||
if (!subPage) {
|
if (!subPage) {
|
||||||
|
console.error(`子页面 ${subPageName} 不存在`);
|
||||||
throw new Error(`子页面 ${subPageName} 不存在`);
|
throw new Error(`子页面 ${subPageName} 不存在`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,18 +75,24 @@ export class CustomerPage {
|
|||||||
|
|
||||||
await $subPageTab.waitFor();
|
await $subPageTab.waitFor();
|
||||||
|
|
||||||
|
try {
|
||||||
const classAttribute = await $subPageTab.getAttribute('class', { timeout: 5000 });
|
const classAttribute = await $subPageTab.getAttribute('class', { timeout: 5000 });
|
||||||
if (classAttribute && classAttribute.includes('active')) {
|
if (classAttribute && classAttribute.includes('active')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`获取子页面 ${subPageName} 的 class 属性超时`);
|
||||||
|
throw new Error(`获取子页面 ${subPageName} 的 class 属性超时`);
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all([
|
try {
|
||||||
expect(async () => {
|
|
||||||
await $subPageTab.click();
|
await $subPageTab.click();
|
||||||
await expect($subPageTab).toHaveClass(/active/);
|
await expect($subPageTab).toHaveClass(/active/, { timeout: 5000 });
|
||||||
}).toPass(),
|
await waitSpecifyApiLoad(this.page, subPage.url);
|
||||||
waitSpecifyApiLoad(this.page, subPage.url),
|
} catch (error) {
|
||||||
]);
|
console.error(`点击子页面 ${subPageName} 或等待 API 加载失败`);
|
||||||
|
throw new Error(`点击子页面 ${subPageName} 或等待 API 加载失败`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { type Locator, type Page } from '@playwright/test';
|
import { type Locator, type Page } from '@playwright/test';
|
||||||
import { waitSpecifyApiLoad } from '@/utils/utils.js';
|
import { waitSpecifyApiLoad } from '@/utils/utils';
|
||||||
|
|
||||||
export class MarketingInviteGuestsPage {
|
export class MarketingInviteGuestsPage {
|
||||||
page: Page;
|
page: Page;
|
||||||
|
|||||||
@ -280,9 +280,17 @@ test.describe('挂单', () => {
|
|||||||
await page.getByText('已过期 / 删除单据').click();
|
await page.getByText('已过期 / 删除单据').click();
|
||||||
await page.getByText('警告:已过期服务无法取单结算,请至收银台处理').waitFor();
|
await page.getByText('警告:已过期服务无法取单结算,请至收银台处理').waitFor();
|
||||||
await $slidingMenu.locator('div.item_box').first().waitFor();
|
await $slidingMenu.locator('div.item_box').first().waitFor();
|
||||||
await expect($slidingMenu.locator('div.item_box').first().getByRole('button', { name: /^取\s单$/ })).not.toBeVisible();
|
await expect(
|
||||||
|
$slidingMenu
|
||||||
|
.locator('div.item_box')
|
||||||
|
.first()
|
||||||
|
.getByRole('button', { name: /^取\s单$/ }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
const $delete = $slidingMenu.locator('div.item_box').first().locator('.comment > div:nth-child(2) > .touchIcon');
|
const $delete = $slidingMenu
|
||||||
|
.locator('div.item_box')
|
||||||
|
.first()
|
||||||
|
.locator('.comment > div:nth-child(2) > .touchIcon');
|
||||||
await $delete.click();
|
await $delete.click();
|
||||||
await page.getByPlaceholder('请输入1-100个字符备注内容').click();
|
await page.getByPlaceholder('请输入1-100个字符备注内容').click();
|
||||||
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试备注');
|
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试备注');
|
||||||
@ -1256,7 +1264,7 @@ test.describe('收银-开单&结算', () => {
|
|||||||
await page.getByText('卡金').nth(4).click();
|
await page.getByText('卡金').nth(4).click();
|
||||||
await page.getByRole('button', { name: '增加收款' }).click();
|
await page.getByRole('button', { name: '增加收款' }).click();
|
||||||
// 输入金额
|
// 输入金额
|
||||||
await numberInput.setCommonValue(100);
|
await numberInput.setValue('common', 100);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
// 选择赠送金支付
|
// 选择赠送金支付
|
||||||
await page.getByText('赠金').nth(2).click();
|
await page.getByText('赠金').nth(2).click();
|
||||||
|
|||||||
@ -1041,11 +1041,6 @@ test.describe('顾客详情', () => {
|
|||||||
|
|
||||||
test('操作套餐', async ({ page, homeNavigation, customerPage, createCustomer }) => {
|
test('操作套餐', async ({ page, homeNavigation, customerPage, createCustomer }) => {
|
||||||
let billNo: string;
|
let billNo: string;
|
||||||
const date = new Date();
|
|
||||||
const currentYear = date.getFullYear();
|
|
||||||
const currentMonth = date.getMonth() + 1;
|
|
||||||
const currentDay = date.getDate();
|
|
||||||
const dayStr = currentDay >= 10 ? `${currentDay}` : `0${currentDay}`;
|
|
||||||
// 套餐的名称
|
// 套餐的名称
|
||||||
const $setMeal = page.getByText('护理修护全套');
|
const $setMeal = page.getByText('护理修护全套');
|
||||||
// 套餐的所有项目
|
// 套餐的所有项目
|
||||||
@ -1071,14 +1066,24 @@ test.describe('顾客详情', () => {
|
|||||||
|
|
||||||
// 结算
|
// 结算
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
page.waitForResponse(async res => {
|
page.waitForResponse(res => res.url().includes('/bill') && res.status() === 200 && res.request().method() === 'POST'),
|
||||||
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
|
|
||||||
}),
|
|
||||||
page.getByRole('button', { name: /跳\s过/ }).click(),
|
page.getByRole('button', { name: /跳\s过/ }).click(),
|
||||||
]);
|
]);
|
||||||
const responseBody = await response.json();
|
|
||||||
billNo = responseBody?.content?.billNo;
|
billNo = (await response.json())?.content?.billNo;
|
||||||
expect(billNo).not.toBeNull();
|
|
||||||
|
await page.waitForResponse(async res => {
|
||||||
|
if (
|
||||||
|
res.url().includes('/bill_status') &&
|
||||||
|
res.status() === 200 &&
|
||||||
|
res.request().method() === 'GET'
|
||||||
|
) {
|
||||||
|
const responseBody = await res.json(); // 等待解析 JSON
|
||||||
|
return responseBody?.content?.status === 'SETTLED';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
await page.getByRole('button', { name: '不寄存' }).click();
|
await page.getByRole('button', { name: '不寄存' }).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1103,19 +1108,17 @@ test.describe('顾客详情', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await test.step('冻结有效期-解冻有效期', async () => {
|
await test.step('冻结有效期-解冻有效期', async () => {
|
||||||
// 冻结日期
|
|
||||||
const freezeStr = `${currentYear}-${currentMonth}-${dayStr}冻结`;
|
|
||||||
// 冻结有效期
|
// 冻结有效期
|
||||||
await $$treatCard.first().locator('svg').last().click();
|
await $$treatCard.first().locator('svg').last().click();
|
||||||
await page.getByText('冻结有效期').click();
|
await page.getByText('冻结有效期').click();
|
||||||
await Promise.all([page.getByRole('button', { name: /确\s认/ }).click(), page.waitForLoadState()]);
|
await Promise.all([page.getByRole('button', { name: /确\s认/ }).click(), page.waitForLoadState()]);
|
||||||
await expect(page.locator('.ant-message')).toContainText('修改成功');
|
await expect(page.locator('.ant-message')).toContainText('修改成功');
|
||||||
await expect($$treatCard.first().locator('.deadline_row span')).toContainText(freezeStr);
|
await expect($$treatCard.first().locator('.deadline_row span')).toContainText('冻结');
|
||||||
// 解冻有效期
|
// 解冻有效期
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await $$treatCard.first().locator('svg').last().click();
|
await $$treatCard.first().locator('svg').last().click();
|
||||||
await page.getByText('解冻有效期').click({ timeout: 2000 });
|
await page.getByText('解冻有效期').click({ timeout: 2000 });
|
||||||
await expect($$treatCard.first().locator('.deadline_row span')).not.toContainText(freezeStr, {
|
await expect($$treatCard.first().locator('.deadline_row span')).not.toContainText('冻结', {
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
});
|
});
|
||||||
}).toPass();
|
}).toPass();
|
||||||
@ -1417,35 +1420,37 @@ test.describe('顾客详情', () => {
|
|||||||
const currentMonth = date.getMonth() + 1;
|
const currentMonth = date.getMonth() + 1;
|
||||||
const currentDay = date.getDate();
|
const currentDay = date.getDate();
|
||||||
|
|
||||||
/**@type {string} */
|
let billNo: string;
|
||||||
let billNo = '';
|
|
||||||
await test.step('开单拿取单号', async () => {
|
await test.step('开单拿取单号', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.phone);
|
await customerPage.searchCustomer(customer.phone);
|
||||||
await page.getByText('搜索', { exact: true }).click();
|
await customerPage.selectSearchCustomer(customer.phone);
|
||||||
await page.locator('.member_list_li').filter({ hasText: customer.phone }).click();
|
|
||||||
await page.locator('.list_box .project_list').first().click();
|
await page.locator('.list_box .project_list').first().click();
|
||||||
await page
|
await page.locator('div.pay_btn').filter({ hasText: /^结\s算$/ }).click();
|
||||||
.locator('.pay_btn')
|
|
||||||
.filter({ hasText: /^结\s算$/ })
|
|
||||||
.click();
|
|
||||||
//取消推送消息提醒
|
|
||||||
await page.getByLabel('推送消费提醒').uncheck();
|
await page.getByLabel('推送消费提醒').uncheck();
|
||||||
//取消结算签字
|
|
||||||
await page.getByLabel('结算签字').uncheck();
|
await page.getByLabel('结算签字').uncheck();
|
||||||
await page.locator('.paymentInfoItem').first().click();
|
await page.locator('.paymentInfoItem').first().click();
|
||||||
|
|
||||||
// 结算
|
// 结算
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
page.waitForResponse(async res => {
|
page.waitForResponse(res => res.url().includes('/bill') && res.status() === 200 && res.request().method() === 'POST'),
|
||||||
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
|
page.getByRole('button', { name: /结\s算/ }).click(),
|
||||||
}),
|
|
||||||
page.getByRole('button', { name: /^结\s算$/ }).click(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
billNo = (await response.json())?.content?.billNo;
|
billNo = (await response.json())?.content?.billNo;
|
||||||
expect(billNo).not.toBeNull();
|
|
||||||
|
await page.waitForResponse(async res => {
|
||||||
|
if (
|
||||||
|
res.url().includes('/bill_status') &&
|
||||||
|
res.status() === 200 &&
|
||||||
|
res.request().method() === 'GET'
|
||||||
|
) {
|
||||||
|
const responseBody = await res.json(); // 等待解析 JSON
|
||||||
|
return responseBody?.content?.status === 'SETTLED';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('进入顾客详情页面', async () => {
|
await test.step('进入顾客详情页面', async () => {
|
||||||
@ -1482,36 +1487,32 @@ test.describe('顾客详情', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 今年所有月份的动态
|
// 今年所有月份的动态
|
||||||
const $$dynamic = page.locator('.calendar_year_list', { hasText: `${currentYear}` }).locator('.dynamic_list');
|
const $$dynamic = page.locator('div.calendar_year_list', { hasText: `${currentYear}` }).locator('.dynamic_list');
|
||||||
// 当前月份的动态
|
// 当前月份的动态
|
||||||
const $currentForMonthDynamic = $$dynamic.filter({
|
const $currentMonthDynamic = $$dynamic.filter({
|
||||||
has: page.locator('.month_box', { hasText: `${currentMonth}` }),
|
has: page.locator('.month_box').getByText(`${currentMonth}`, { exact: true }),
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('查看月动态-缩略', async () => {
|
await test.step('查看月动态-缩略', async () => {
|
||||||
await page
|
await page.locator('div').filter({ hasText: /^日月$/ }).getByRole('switch').click();
|
||||||
.locator('div')
|
|
||||||
.filter({ hasText: /^日月$/ })
|
|
||||||
.getByRole('switch')
|
|
||||||
.click();
|
|
||||||
await expect(page.getByText('月', { exact: true })).toHaveClass('selected_btn');
|
await expect(page.getByText('月', { exact: true })).toHaveClass('selected_btn');
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await $currentForMonthDynamic.click();
|
await $currentMonthDynamic.click();
|
||||||
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
|
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
|
||||||
}).toPass();
|
}).toPass();
|
||||||
await page.locator('.action_detail > .container > .m_sliding_menu > .box > .top > .anticon').click();
|
|
||||||
|
await page.locator('div.action_detail div.m_sliding_menu div.top i.anticon').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('查看月动态-日期', async () => {
|
await test.step('查看月动态-日期', async () => {
|
||||||
await page
|
await page.locator('div').filter({ hasText: /^缩略日期$/ }).getByRole('switch').click();
|
||||||
.locator('div')
|
|
||||||
.filter({ hasText: /^缩略日期$/ })
|
|
||||||
.getByRole('switch')
|
|
||||||
.click();
|
|
||||||
await expect(page.getByText('日期', { exact: true })).toHaveClass('selected_btn');
|
await expect(page.getByText('日期', { exact: true })).toHaveClass('selected_btn');
|
||||||
|
const $$dateList = $currentMonthDynamic.locator('div.date_list');
|
||||||
await $currentForMonthDynamic.filter({ hasText: `${currentDay}` }).click();
|
await expect(async () => {
|
||||||
|
await $$dateList.getByText(`${currentDay}`, { exact: true }).click();
|
||||||
|
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
|
||||||
|
}).toPass();
|
||||||
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
|
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -2024,7 +2025,7 @@ test.describe('顾客分配', () => {
|
|||||||
const index = titleList.findIndex(text => text === '现金总额');
|
const index = titleList.findIndex(text => text === '现金总额');
|
||||||
|
|
||||||
// 拿取前三个顾客的现金总额
|
// 拿取前三个顾客的现金总额
|
||||||
let amountArray: number[];
|
let amountArray: number[] = new Array(3);
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
const amountStr = await amountList.nth(i).locator('td').nth(index).innerText();
|
const amountStr = await amountList.nth(i).locator('td').nth(index).innerText();
|
||||||
const amount = convertAmountText(amountStr).amount;
|
const amount = convertAmountText(amountStr).amount;
|
||||||
@ -2218,7 +2219,7 @@ test.describe('顾客分配', () => {
|
|||||||
|
|
||||||
test.describe('顾客分析', () => {
|
test.describe('顾客分析', () => {
|
||||||
test('查看顾客项目分析', async ({ page, homeNavigation, createCustomers, customerPage, numberInput }) => {
|
test('查看顾客项目分析', async ({ page, homeNavigation, createCustomers, customerPage, numberInput }) => {
|
||||||
let customers: Customer[];
|
let customers: Customer[] = new Array(2);
|
||||||
await test.step('创建两个顾客', async () => {
|
await test.step('创建两个顾客', async () => {
|
||||||
customers = await createCustomers(2);
|
customers = await createCustomers(2);
|
||||||
});
|
});
|
||||||
@ -2226,38 +2227,32 @@ test.describe('顾客分析', () => {
|
|||||||
const ca = customers[0];
|
const ca = customers[0];
|
||||||
const cb = customers[1];
|
const cb = customers[1];
|
||||||
|
|
||||||
// 获取姓名、手机号、档案号
|
const projects_a1 = { num: '100012', name: '雪肌晶纯护理', price: 300 };
|
||||||
const usernameA = ca.username;
|
const projects_a1_quantity = 2;
|
||||||
const phoneA = ca.phone;
|
const projects_a2 = { num: '100258', name: '出水芙蓉SPA水疗', price: 380 };
|
||||||
const usernameB = cb.username;
|
const projects_a2_quantity = 1;
|
||||||
const phoneB = cb.phone;
|
const projects_a3 = { num: '100013', name: '净透驻氧护理', price: 380 };
|
||||||
|
const projects_a3_quantity = 2;
|
||||||
const ProjectA1 = ProjectName.Projects.Projects_1;
|
const projects_a12_quantity = 1;
|
||||||
const ProjectA1Quantity = 2;
|
|
||||||
const ProjectA2 = ProjectName.Projects.Projects_239;
|
|
||||||
const ProjectA2Quantity = 1;
|
|
||||||
const ProjectA3 = ProjectName.Projects.Projects_2;
|
|
||||||
const ProjectA3Quantity = 2;
|
|
||||||
const ProjectA12Quantity = 1;
|
|
||||||
|
|
||||||
// 顾客A
|
// 顾客A
|
||||||
await test.step('顾客A', async () => {
|
await test.step('顾客A', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
await customerPage.searchCustomer(phoneA);
|
await customerPage.searchCustomer(ca.phone);
|
||||||
await customerPage.selectSearchCustomer(usernameA);
|
await customerPage.selectSearchCustomer(ca.username);
|
||||||
|
|
||||||
// 购买项目1-普通,2次
|
// 购买项目1-普通,2次
|
||||||
await page.getByText(ProjectA1.num).click();
|
await page.getByText(projects_a1.num).click();
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectA1Quantity);
|
await numberInput.setValue(projects_a1_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
// 点击面部
|
// 点击面部
|
||||||
await page.getByText('面部').click();
|
await page.getByText('面部').click();
|
||||||
|
|
||||||
// 购买项目2-普通,1次
|
// 购买项目2-普通,1次
|
||||||
await page.getByText(ProjectA2.num).click();
|
await page.getByText(projects_a2.num).click();
|
||||||
await page.locator('.type_btn').first().click();
|
await page.locator('.type_btn').first().click();
|
||||||
await page.locator('.type_item', { hasText: '普通' }).click();
|
await page.locator('.type_item', { hasText: '普通' }).click();
|
||||||
|
|
||||||
@ -2265,21 +2260,21 @@ test.describe('顾客分析', () => {
|
|||||||
await page.getByText('护理', { exact: true }).click();
|
await page.getByText('护理', { exact: true }).click();
|
||||||
|
|
||||||
// 购买项目3-赠送,3次
|
// 购买项目3-赠送,3次
|
||||||
await page.getByText(ProjectA3.num).click();
|
await page.getByText(projects_a3.num).click();
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectA3Quantity);
|
await numberInput.setValue(projects_a3_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
await page.locator('.type_btn').first().click();
|
await page.locator('.type_btn').first().click();
|
||||||
await page.locator('.type_item', { hasText: '赠送' }).click();
|
await page.locator('.type_item', { hasText: '赠送' }).click();
|
||||||
|
|
||||||
// 选择组合项目2-项目1,普通
|
// 选择组合项目2-项目1,普通
|
||||||
await page.getByText(ProjectA1.num).first().click();
|
await page.getByText(projects_a1.num).first().click();
|
||||||
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
||||||
await page.getByRole('textbox').fill(ProjectA2.num);
|
await page.getByRole('textbox').fill(projects_a2.num);
|
||||||
await page.getByRole('button', { name: /搜\s索/ }).click();
|
await page.getByRole('button', { name: /搜\s索/ }).click();
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await page.getByLabel(ProjectA2.name).uncheck();
|
await page.getByLabel(projects_a2.name).uncheck();
|
||||||
await page.getByLabel(ProjectA2.name).check();
|
await page.getByLabel(projects_a2.name).check();
|
||||||
await page.locator('.menu-item-dot', { hasText: '2' }).first().waitFor({ timeout: 2000 });
|
await page.locator('.menu-item-dot', { hasText: '2' }).first().waitFor({ timeout: 2000 });
|
||||||
}).toPass();
|
}).toPass();
|
||||||
await page.getByRole('button', { name: '确定选择' }).click();
|
await page.getByRole('button', { name: '确定选择' }).click();
|
||||||
@ -2299,50 +2294,52 @@ test.describe('顾客分析', () => {
|
|||||||
await page.getByRole('button', { name: /^结\s算$/ }).click();
|
await page.getByRole('button', { name: /^结\s算$/ }).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
const ProjectB3 = ProjectName.Projects.Projects_2;
|
const project_b3 = { num: '100013', name: '净透驻氧护理', price: 380 };
|
||||||
const ProjectB3Quantity = 20;
|
const project_b3_quantity = 20;
|
||||||
const ProjectB4 = ProjectName.Projects.Projects_661;
|
|
||||||
const ProjectB4Quantity = 30;
|
const project_b4 = { num: '100719', name: '艾灸', price: 0 };
|
||||||
const ProjectB5 = ProjectName.Projects.Projects_676;
|
const project_b4_quantity = 30;
|
||||||
const ProjectB5Quantity = 9;
|
|
||||||
const ProjectB1 = ProjectName.Projects.Projects_1;
|
const project_b5 = { num: '100735', name: '脱毛', price: 88 };
|
||||||
const ProjectB2 = ProjectName.Projects.Projects_239;
|
const project_b5_quantity = 9;
|
||||||
const ProjectB12Quantity = 2;
|
|
||||||
const ProjectB34Quantity = 3;
|
const project_b1 = { num: '100012', name: '雪肌晶纯护理', price: 300 };
|
||||||
|
const project_b2 = { num: '100258', name: '出水芙蓉SPA水疗', Price: 380 };
|
||||||
|
const project_b12_quantity = 2;
|
||||||
|
const project_b34_quantity = 3;
|
||||||
|
|
||||||
await test.step('顾客B', async () => {
|
await test.step('顾客B', async () => {
|
||||||
//顾客B
|
|
||||||
await page.reload();
|
await page.reload();
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
await customerPage.searchCustomer(phoneB);
|
await customerPage.searchCustomer(cb.phone);
|
||||||
await customerPage.selectSearchCustomer(usernameB);
|
await customerPage.selectSearchCustomer(cb.username);
|
||||||
|
|
||||||
// 购买项目3-普通,20次
|
// 购买项目3-普通,20次
|
||||||
await page.getByText(ProjectB3.num).click();
|
await page.getByText(project_b3.num).click();
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectB3Quantity);
|
await numberInput.setValue(project_b3_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
// 点击身体
|
// 点击身体
|
||||||
await page.locator('.type_tab_item', { hasText: '身体' }).click();
|
await page.locator('.type_tab_item', { hasText: '身体' }).click();
|
||||||
|
|
||||||
// 购买项目4-普通,30次
|
// 购买项目4-普通,30次
|
||||||
await page.getByText(ProjectB4.num).click();
|
await page.getByText(project_b4.num).click();
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectB4Quantity);
|
await numberInput.setValue(project_b4_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
// 购买项目5,9次
|
// 购买项目5,9次
|
||||||
await page.getByText(ProjectB5.num).click();
|
await page.getByText(project_b5.num).click();
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectB5Quantity);
|
await numberInput.setValue(project_b5_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
// 购买项目B1-B2混合,2次
|
// 购买项目B1-B2混合,2次
|
||||||
await page.locator('.type_tab_item', { hasText: '护理' }).click();
|
await page.locator('.type_tab_item', { hasText: '护理' }).click();
|
||||||
await page.getByText(ProjectB1.num).first().click();
|
await page.getByText(project_b1.num).first().click();
|
||||||
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
||||||
await page.getByRole('textbox').fill(ProjectB2.num);
|
await page.getByRole('textbox').fill(project_b2.num);
|
||||||
await page.getByRole('button', { name: /搜\s索/ }).click();
|
await page.getByRole('button', { name: /搜\s索/ }).click();
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await page.locator('.list_box .ant-checkbox-input').click();
|
await page.locator('.list_box .ant-checkbox-input').click();
|
||||||
@ -2351,13 +2348,13 @@ test.describe('顾客分析', () => {
|
|||||||
await page.getByRole('button', { name: '确定选择' }).click();
|
await page.getByRole('button', { name: '确定选择' }).click();
|
||||||
// 点击选择数量
|
// 点击选择数量
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectB12Quantity);
|
await numberInput.setValue(project_b12_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
// 购买项目B4-B4混合,3次
|
// 购买项目B4-B4混合,3次
|
||||||
await page.getByText(ProjectB3.num).first().click();
|
await page.getByText(project_b3.num).first().click();
|
||||||
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
await page.locator('.add_btn', { hasText: '设置' }).last().click();
|
||||||
await page.getByRole('textbox').fill(ProjectB4.num);
|
await page.getByRole('textbox').fill(project_b4.num);
|
||||||
await page.getByRole('button', { name: '搜 索' }).click();
|
await page.getByRole('button', { name: '搜 索' }).click();
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await page.locator('.list_box .ant-checkbox-input').click();
|
await page.locator('.list_box .ant-checkbox-input').click();
|
||||||
@ -2366,7 +2363,7 @@ test.describe('顾客分析', () => {
|
|||||||
await page.getByRole('button', { name: '确定选择' }).click();
|
await page.getByRole('button', { name: '确定选择' }).click();
|
||||||
// 点击选择数量
|
// 点击选择数量
|
||||||
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
await page.locator('.edit_txt div:nth-child(2)').first().click();
|
||||||
await numberInput.setValue(ProjectB34Quantity);
|
await numberInput.setValue(project_b34_quantity);
|
||||||
await numberInput.confirmValue();
|
await numberInput.confirmValue();
|
||||||
|
|
||||||
await page.locator('.commodity_item').last().click();
|
await page.locator('.commodity_item').last().click();
|
||||||
@ -2384,15 +2381,13 @@ test.describe('顾客分析', () => {
|
|||||||
await page.reload();
|
await page.reload();
|
||||||
await homeNavigation.gotoModule('顾客');
|
await homeNavigation.gotoModule('顾客');
|
||||||
await customerPage.gotoSubPage('顾客分析');
|
await customerPage.gotoSubPage('顾客分析');
|
||||||
await page
|
await page.getByText('排序', { exact: true }).click();
|
||||||
.locator('div')
|
await Promise.all([
|
||||||
.filter({ hasText: /^排序$/ })
|
page.waitForResponse(res => res.url().includes('analysis') && res.ok()),
|
||||||
.nth(1)
|
page.getByRole('menuitem', { name: '上次到店时间从近到远' }).click(),
|
||||||
.click();
|
]);
|
||||||
await page.getByRole('menuitem', { name: '上次到店时间从近到远' }).click();
|
const Customer1A = page.locator('.m-table__body-wrapper tbody tr', { hasText: ca.phone });
|
||||||
await page.locator('.loading_container').waitFor({ state: 'hidden' });
|
const Customer1B = page.locator('.m-table__body-wrapper tbody tr', { hasText: cb.phone });
|
||||||
const Customer1A = page.locator('.m-table__body-wrapper tbody tr', { hasText: phoneA });
|
|
||||||
const Customer1B = page.locator('.m-table__body-wrapper tbody tr', { hasText: phoneB });
|
|
||||||
// 1 查找到顾客A 顾客B
|
// 1 查找到顾客A 顾客B
|
||||||
await expect(Customer1A).toBeVisible();
|
await expect(Customer1A).toBeVisible();
|
||||||
await expect(Customer1B).toBeVisible();
|
await expect(Customer1B).toBeVisible();
|
||||||
@ -2405,19 +2400,19 @@ test.describe('顾客分析', () => {
|
|||||||
.locator('.m-table__body-wrapper tbody tr')
|
.locator('.m-table__body-wrapper tbody tr')
|
||||||
.allInnerTexts()
|
.allInnerTexts()
|
||||||
.then(async text => {
|
.then(async text => {
|
||||||
return text.findIndex(item => item.includes(phoneB));
|
return text.findIndex(item => item.includes(cb.phone));
|
||||||
});
|
});
|
||||||
|
|
||||||
// 查看各单元格内容
|
// 查看各单元格内容
|
||||||
// 护理内容
|
// 护理内容
|
||||||
await expect.soft(allTr.nth(nowRow).locator('td').nth(2)).toContainText(`${ProjectB3Quantity - 1}`);
|
await expect.soft(allTr.nth(nowRow).locator('td').nth(2)).toContainText(`${project_b3_quantity - 1}`);
|
||||||
// 身体内容
|
// 身体内容
|
||||||
await expect
|
await expect
|
||||||
.soft(allTr.nth(nowRow).locator('td').nth(5))
|
.soft(allTr.nth(nowRow).locator('td').nth(5))
|
||||||
.toContainText(`${ProjectB12Quantity + ProjectB34Quantity}`);
|
.toContainText(`${project_b12_quantity + project_b34_quantity}`);
|
||||||
// 组合内容
|
// 组合内容
|
||||||
await expect(allTr.nth(nowRow).locator('td').nth(5)).toContainText(
|
await expect(allTr.nth(nowRow).locator('td').nth(5)).toContainText(
|
||||||
`${ProjectB12Quantity + ProjectB34Quantity}`,
|
`${project_b12_quantity + project_b34_quantity}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const $productName = page.locator('.treat_box .treat_card:nth-child(1) .name_row .auto_desc');
|
const $productName = page.locator('.treat_box .treat_card:nth-child(1) .name_row .auto_desc');
|
||||||
@ -2429,67 +2424,67 @@ test.describe('顾客分析', () => {
|
|||||||
// 点击护理
|
// 点击护理
|
||||||
await allTr.nth(nowRow).locator('td').nth(2).click();
|
await allTr.nth(nowRow).locator('td').nth(2).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectB3.name);
|
await expect.soft($productName).toContainText(project_b3.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue).toContainText(`${ProjectB3Quantity - 1}`);
|
await expect($productResidue).toContainText(`${project_b34_quantity - 1}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
// 点击身体
|
// 点击身体
|
||||||
await allTr.nth(nowRow).locator('td').nth(4).click();
|
await allTr.nth(nowRow).locator('td').nth(4).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectB4.name);
|
await expect.soft($productName).toContainText(project_b4.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect.soft($productResidue).toContainText(`${ProjectB4Quantity}`);
|
await expect.soft($productResidue).toContainText(`${project_b4_quantity}`);
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName2).toContainText(ProjectB5.name);
|
await expect.soft($productName2).toContainText(project_b5.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect.soft($productResidue2).toContainText(`${ProjectB5Quantity}`);
|
await expect.soft($productResidue2).toContainText(`${project_b5_quantity}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
// 点击组合
|
// 点击组合
|
||||||
await allTr.nth(nowRow).locator('td').nth(5).click();
|
await allTr.nth(nowRow).locator('td').nth(5).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectB1.name + ',' + ProjectB2.name);
|
await expect.soft($productName).toContainText(project_b1.name + ',' + project_b2.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect.soft($productResidue).toContainText(`${ProjectB12Quantity}`);
|
await expect.soft($productResidue).toContainText(`${project_b12_quantity}`);
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName2).toContainText(ProjectB3.name + ',' + ProjectB4.name);
|
await expect.soft($productName2).toContainText(project_b3.name + ',' + project_b4.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue2).toContainText(`${ProjectB34Quantity}`);
|
await expect($productResidue2).toContainText(`${project_b34_quantity}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
// 查看顾客A的各单元格内容
|
// 查看顾客A的各单元格内容
|
||||||
const allTrA = page.locator('.m-table__body-wrapper tbody tr');
|
const allTrA = page.locator('.m-table__body-wrapper tbody tr');
|
||||||
const nowRowA = await allTrA.allInnerTexts().then(async text => {
|
const nowRowA = await allTrA.allInnerTexts().then(async text => {
|
||||||
return text.findIndex(item => item.includes(phoneA));
|
return text.findIndex(item => item.includes(ca.phone));
|
||||||
});
|
});
|
||||||
// 点击护理
|
// 点击护理
|
||||||
await allTrA.nth(nowRowA).locator('td').nth(2).click();
|
await allTrA.nth(nowRowA).locator('td').nth(2).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectA1.name);
|
await expect.soft($productName).toContainText(projects_a1.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue).toContainText(`${ProjectA1Quantity - 1}`);
|
await expect($productResidue).toContainText(`${projects_a1_quantity - 1}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
// 点击面部
|
// 点击面部
|
||||||
await allTrA.nth(nowRowA).locator('td').nth(3).click();
|
await allTrA.nth(nowRowA).locator('td').nth(3).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectA2.name);
|
await expect.soft($productName).toContainText(projects_a2.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue).toContainText(`${ProjectA2Quantity}`);
|
await expect($productResidue).toContainText(`${projects_a2_quantity}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
// 点击组合
|
// 点击组合
|
||||||
await allTrA.nth(nowRowA).locator('td').nth(5).click();
|
await allTrA.nth(nowRowA).locator('td').nth(5).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectA1.name + ',' + ProjectA2.name);
|
await expect.soft($productName).toContainText(projects_a1.name + ',' + projects_a2.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue).toContainText(`${ProjectA12Quantity}`);
|
await expect($productResidue).toContainText(`${projects_a12_quantity}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
@ -2505,18 +2500,18 @@ test.describe('顾客分析', () => {
|
|||||||
// 护理内容
|
// 护理内容
|
||||||
const allTrAA = page.locator('.m-table__body-wrapper tbody tr');
|
const allTrAA = page.locator('.m-table__body-wrapper tbody tr');
|
||||||
const nowRowAA = await allTrAA.allInnerTexts().then(async text => {
|
const nowRowAA = await allTrAA.allInnerTexts().then(async text => {
|
||||||
return text.findIndex(item => item.includes(phoneA));
|
return text.findIndex(item => item.includes(ca.phone));
|
||||||
});
|
});
|
||||||
// 点击护理
|
// 点击护理
|
||||||
await allTrAA.nth(nowRowAA).locator('td').nth(2).click();
|
await allTrAA.nth(nowRowAA).locator('td').nth(2).click();
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName).toContainText(ProjectA1.name);
|
await expect.soft($productName).toContainText(projects_a1.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect.soft($productResidue).toContainText(`${ProjectA1Quantity - 1}`);
|
await expect.soft($productResidue).toContainText(`${projects_a1_quantity - 1}`);
|
||||||
// 项目名称
|
// 项目名称
|
||||||
await expect.soft($productName2).toContainText(ProjectA3.name);
|
await expect.soft($productName2).toContainText(projects_a3.name);
|
||||||
// 剩余次数
|
// 剩余次数
|
||||||
await expect($productResidue2).toContainText(`${ProjectA3Quantity}`);
|
await expect($productResidue2).toContainText(`${projects_a3_quantity}`);
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
await page.locator('.close_icon').last().click();
|
await page.locator('.close_icon').last().click();
|
||||||
|
|
||||||
|
|||||||
@ -280,7 +280,7 @@ test.describe('业绩明细表', () => {
|
|||||||
|
|
||||||
test.describe('项目销耗存表', () => {
|
test.describe('项目销耗存表', () => {
|
||||||
test('数据校验', async ({ page, createCustomers, homeNavigation, reportPage, customerPage, numberInput }) => {
|
test('数据校验', async ({ page, createCustomers, homeNavigation, reportPage, customerPage, numberInput }) => {
|
||||||
let customers: Customer[];
|
let customers: Customer[] = new Array(2);
|
||||||
await test.step('创建两个顾客', async () => {
|
await test.step('创建两个顾客', async () => {
|
||||||
customers = await createCustomers(2);
|
customers = await createCustomers(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { Page } from "playwright";
|
||||||
|
|
||||||
// 解析二维码
|
// 解析二维码
|
||||||
const decodeImage = require('jimp').read;
|
const decodeImage = require('jimp').read;
|
||||||
const { readFile, unlinkSync } = require('fs');
|
const { readFile, unlinkSync } = require('fs');
|
||||||
@ -95,17 +97,31 @@ export function CleanPunctuation(str) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 等待指定接口加载完成
|
* 等待指定接口加载完成
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {Page} page - Playwright Page 对象
|
||||||
* @param {string[]} apiArray 接口名称数组
|
* @param {string[]} apiArray - 接口名称数组
|
||||||
* @returns Promise<Response[]>
|
* @returns Promise<Response[]>
|
||||||
*/
|
*/
|
||||||
export const waitSpecifyApiLoad = (page, apiArray) => {
|
export const waitSpecifyApiLoad = async (page: Page, apiArray: string[]): Promise<Response[]> => {
|
||||||
if (apiArray === undefined || apiArray.length === 0) {
|
// 输入参数检查
|
||||||
return Promise.resolve([]);
|
if (!page || !Array.isArray(apiArray) || apiArray.length === 0 || !apiArray.every(item => typeof item === 'string')) {
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
return Promise.all(
|
|
||||||
apiArray.map(api => page.waitForResponse(res => res.url().includes(api) && res.status() === 200)),
|
// 去重
|
||||||
|
const uniqueApiArray = Array.from(new Set(apiArray));
|
||||||
|
|
||||||
|
// 精确匹配 URL
|
||||||
|
const urlMatchers = uniqueApiArray.map(api => new RegExp(`^.*${api}$`));
|
||||||
|
|
||||||
|
// 等待所有接口加载完成
|
||||||
|
const responses = await Promise.allSettled(
|
||||||
|
urlMatchers.map(matcher => page.waitForResponse(res => matcher.test(res.url()) && res.status() === 200))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 处理结果
|
||||||
|
return responses
|
||||||
|
.filter(response => response.status === 'fulfilled')
|
||||||
|
.map(response => (response as unknown as PromiseFulfilledResult<Response>).value);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reference in New Issue
Block a user