Some checks are pending
Playwright Tests / test (push) Waiting to run
init test test test 划分美管加、慧来客、智荟宝项目 新增美管加demo 新增npm命令 测试智荟宝 test test ii csv test init test test init init
327 lines
11 KiB
JavaScript
327 lines
11 KiB
JavaScript
//@ts-check
|
|
const { expect } = require('@playwright/test');
|
|
const { Customer } = require('./customer');
|
|
|
|
class CustomerPage {
|
|
/**
|
|
* @param {import("@playwright/test").Page} page
|
|
*/
|
|
constructor(page) {
|
|
this.page = page;
|
|
this.$module = this.page.locator('.left_box .link_item').filter({ hasText: /顾客/ });
|
|
this.$tabItem = this.page.locator('.top_tab .tab_item');
|
|
this.$summary = this.$tabItem.filter({ hasText: '顾客概要' });
|
|
this.$distribution = this.$tabItem.filter({ hasText: '顾客分配' });
|
|
this.$dynamic = this.$tabItem.filter({ hasText: '顾客动态' });
|
|
this.$analysis = this.$tabItem.filter({ hasText: '顾客分析' });
|
|
this.$serviceLog = this.$tabItem.filter({ hasText: '服务日志' });
|
|
this.$register = this.page.locator('.regmeber_warp', { hasText: '创建会员' });
|
|
this.firstStore = {
|
|
firstDepartment: { no: 1, name: '美容部' },
|
|
secondDepartment: { no: 2, name: '医美部' },
|
|
};
|
|
this.secondStore = {
|
|
firstDepartment: { no: 1, name: '美容部' },
|
|
};
|
|
this.source = [
|
|
'邀客',
|
|
'员工带客',
|
|
'美团',
|
|
'大众点评',
|
|
'客带客',
|
|
'上门客人',
|
|
'百度糯米',
|
|
'支付宝',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 跳转子页面,并且等待页面接口加载完成
|
|
* @param {import("@playwright/test").Locator} locator
|
|
* @param {string[]} apiList
|
|
*/
|
|
gotoSubPage = async (locator, apiList) => {
|
|
await expect(async () => {
|
|
if (!(await locator.getAttribute('class'))?.includes('active')) {
|
|
await locator.click();
|
|
}
|
|
await expect(locator).toHaveClass(/active/);
|
|
}).toPass({ timeout: 30000 });
|
|
|
|
await Promise.all(
|
|
apiList.map((api) =>
|
|
this.page.waitForResponse((res) => res.url().includes(api) && res.status() === 200)
|
|
)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* 跳转到顾客概要
|
|
*/
|
|
gotoSummary = async () => {
|
|
await this.gotoSubPage(this.$summary, ['summary', 'todo']);
|
|
};
|
|
|
|
/**
|
|
* 跳转到顾客分配
|
|
*/
|
|
gotoDistribution = async () => {
|
|
await this.gotoSubPage(this.$distribution, ['search_new', 'distribution']);
|
|
};
|
|
|
|
/**
|
|
* 跳转到顾客动态
|
|
*/
|
|
gotoDynamic = async () => {
|
|
await this.gotoSubPage(this.$dynamic, ['daily_action']);
|
|
};
|
|
|
|
/**
|
|
* 跳转到顾客分析
|
|
*/
|
|
gotoAnalysis = async () => {
|
|
await this.gotoSubPage(this.$analysis, ['analysis']);
|
|
};
|
|
|
|
/**
|
|
* 跳转到服务日志
|
|
*/
|
|
gotoServiceLog = async () => {
|
|
await this.gotoSubPage(this.$serviceLog, ['service_log']);
|
|
};
|
|
|
|
/**
|
|
* 搜索顾客
|
|
* @param {Customer} customer
|
|
*/
|
|
searchCustomer = async (customer) => {
|
|
const searchLocator = this.page.locator('.search_normal');
|
|
const searchInput = this.page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索');
|
|
await searchInput.fill(customer.phone);
|
|
await searchLocator.filter({ has: searchInput }).getByText('搜索', { exact: true }).click();
|
|
const customerLocator = this.page
|
|
.locator('.member_list .member_list_li')
|
|
.filter({ hasText: customer.username });
|
|
await customerLocator.click();
|
|
await expect(customerLocator).not.toBeVisible();
|
|
};
|
|
|
|
/**
|
|
* 打开顾客详情页面
|
|
* @param {Customer} customer
|
|
*/
|
|
openCustomerDetails = async (customer) => {
|
|
const $username = this.page.getByText(customer.username).last();
|
|
await $username.click();
|
|
const infoBox = this.page.locator('.member_info_box');
|
|
|
|
await Promise.all([
|
|
expect(infoBox.getByText(customer.username)).toBeVisible(),
|
|
this.page.waitForFunction(() => {
|
|
return document.readyState === 'complete';
|
|
}),
|
|
]);
|
|
};
|
|
|
|
/**
|
|
* 关闭顾客详情页面
|
|
*/
|
|
closeCustomerDetails = async () => {
|
|
const closeButton = this.page.locator('.member_info_box .close_icons > svg');
|
|
await closeButton.click();
|
|
await expect(closeButton).not.toBeVisible();
|
|
};
|
|
|
|
/**
|
|
* 创建顾客
|
|
* @param {Customer} customer 顾客
|
|
* @returns {Promise<void>}
|
|
*/
|
|
createCustomer = async (customer) => {
|
|
await expect(async () => {
|
|
await this.$module.click({ clickCount: 1 });
|
|
await expect(this.$module).toHaveClass(/active/, { timeout: 2000 });
|
|
}).toPass({ timeout: 30000 });
|
|
|
|
// 选择门店
|
|
await this.page.locator('.search_store > div').click();
|
|
await this.page.getByText('部门', { exact: true }).waitFor();
|
|
await this.page.locator('.shopSelect_box .shopSelect_shop_content').click();
|
|
await this.page
|
|
.locator('.com_picker .label')
|
|
.nth(customer.store - 1)
|
|
.click();
|
|
await this.page.getByRole('button', { name: /保.*存/ }).click();
|
|
|
|
await this.page.getByRole('button', { name: '新增顾客' }).click();
|
|
await this.$register.getByPlaceholder('请输入姓名').fill(customer.username);
|
|
await this.$register.getByPlaceholder('请输入会员手机号').fill(customer.phone);
|
|
await this.$register.getByPlaceholder('请输入会员手机号').click();
|
|
|
|
const checkPhoneLocator = this.$register
|
|
.locator('.ant-form-item', { hasText: '手机号' })
|
|
.locator('.ant-form-explain');
|
|
if (await checkPhoneLocator.isVisible()) {
|
|
const phoneStr = await checkPhoneLocator.innerText();
|
|
if (phoneStr.includes('非法手机号码') || phoneStr.includes('请输入会员手机号')) {
|
|
throw new Error(`手机号码:${customer.phone}不正确`);
|
|
}
|
|
}
|
|
|
|
// 输入档案号
|
|
if (customer.archive) {
|
|
await this.$register.getByPlaceholder('请输入12位以内的数字或字母').fill(customer.archive);
|
|
}
|
|
|
|
// 选择部门
|
|
await this.$register.locator('#register_departmentNo').getByRole('combobox').click();
|
|
if (customer.store === 1) {
|
|
if (customer.department === 1) {
|
|
await this.page.getByRole('option', { name: this.firstStore.firstDepartment.name }).click();
|
|
} else if (customer.department === 2) {
|
|
await this.page
|
|
.getByRole('option', { name: this.firstStore.secondDepartment.name })
|
|
.click();
|
|
}
|
|
} else if (customer.store === 2) {
|
|
if (customer.department === 1) {
|
|
await this.page
|
|
.getByRole('option', { name: this.secondStore.firstDepartment.name })
|
|
.click();
|
|
} else {
|
|
throw new Error(`部门:${customer.department}不存在`);
|
|
}
|
|
} else {
|
|
throw new Error(`门店:${customer.store}不存在`);
|
|
}
|
|
|
|
// 选择员工
|
|
|
|
// 选择性别
|
|
if (customer.gender) {
|
|
if (customer.gender === 0) {
|
|
await this.$register.locator('label').filter({ hasText: '女性' }).click();
|
|
} else if (customer.gender === 1) {
|
|
await this.$register.locator('label').filter({ hasText: '男性' }).click();
|
|
}
|
|
}
|
|
|
|
// 选择生日
|
|
const birthday = customer.birthday;
|
|
const birthdayLocator = this.$register.locator('.ant-form-item', { hasText: '生日' });
|
|
if (birthday) {
|
|
const { year, month, day } = birthday;
|
|
if (year) {
|
|
await birthdayLocator.getByText('年份').click();
|
|
await this.page.getByRole('option', { name: `${year}` }).click();
|
|
await expect(this.page.getByRole('option', { name: `${year}` })).not.toBeVisible();
|
|
}
|
|
if (month && day) {
|
|
await birthdayLocator.getByText('日期').click();
|
|
await this.page.getByRole('option', { name: new RegExp(`^${month}\\s月$`) }).click();
|
|
await this.page.getByRole('option', { name: new RegExp(`^${day}\\s日$`) }).click();
|
|
await this.page.getByRole('button', { name: /确\s认/ }).click();
|
|
} else {
|
|
throw new Error(`month:${month}, day:${day}其中一个为空`);
|
|
}
|
|
}
|
|
|
|
// 选择顾客来源
|
|
// await this.$register.getByLabel(this.source[customer.source]).click();
|
|
|
|
await this.$register.getByText('请选择顾客来源').click();
|
|
await this.page.getByRole('option', { name: this.source[customer.source] }).first().click();
|
|
|
|
// 选择备注
|
|
if (customer.remark) {
|
|
await this.$register.getByPlaceholder('请输入1-100个字符备注内容').fill(customer.remark);
|
|
}
|
|
|
|
const [response] = await Promise.all([
|
|
this.page.waitForResponse(
|
|
async (res) => res.url().includes('/invalid_check') && (await res.json()).code === 'SUCCESS'
|
|
),
|
|
this.page.getByRole('button', { name: '确认创建' }).click(),
|
|
]);
|
|
const responseBody = await response.json();
|
|
|
|
const phoneStatus = responseBody?.content?.status;
|
|
if (phoneStatus) {
|
|
await this.page
|
|
.getByText('系统查询到当前手机号被建档后转为无效客,是否要恢复无效客?')
|
|
.waitFor();
|
|
await this.page.getByRole('button', { name: '重新建档' }).click();
|
|
// 检查弹窗信息
|
|
const popupWindow = this.page.locator('.ant-message');
|
|
await popupWindow.waitFor();
|
|
const popupContent = (await popupWindow.innerText()).trim();
|
|
if (popupContent.includes('该手机号码已经被使用')) {
|
|
throw new Error(`该手机号码:${customer.phone}已经被使用`);
|
|
}
|
|
}
|
|
|
|
await this.page.locator('.person_content').waitFor();
|
|
};
|
|
|
|
/**
|
|
* 设置顾客为无效客
|
|
* @param {Customer} customer 顾客
|
|
* @returns {Promise<void>}
|
|
*/
|
|
setInvalidCustomer = async (customer) => {
|
|
await this.page.goto(process.env.BASE_URL || '', { waitUntil: 'load' });
|
|
const moduleLocator = this.$module;
|
|
const activeLocator = moduleLocator.locator('.active_arrow');
|
|
await expect(async () => {
|
|
if (!(await activeLocator.isVisible())) {
|
|
await moduleLocator.click({ clickCount: 1 });
|
|
}
|
|
await expect(activeLocator).toBeVisible({ timeout: 2_000 });
|
|
}).toPass({ timeout: 30_000 });
|
|
|
|
// 根据手机号进行搜索,进入顾客详情页面
|
|
await this.page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.phone);
|
|
await this.page.locator('.ant-input-suffix .search_btn', { hasText: '搜索' }).click();
|
|
await this.page.locator('.custom_content', { hasText: customer.phone }).click();
|
|
await this.page.locator('.m-table__fixed-left').getByText(customer.username).first().click();
|
|
|
|
// 设置无效客
|
|
await this.page.locator('.person_content').waitFor();
|
|
await this.page.locator('.person_content .tag_box .more_icon svg').click();
|
|
await this.page.getByRole('menuitem', { name: '设为无效客' }).click();
|
|
const [response] = await Promise.all([
|
|
this.page.waitForResponse(
|
|
(response) =>
|
|
response.url().includes('/customer') && response.request().method() === 'PATCH'
|
|
),
|
|
this.page.getByRole('button', { name: /确\s认/ }).click(),
|
|
]);
|
|
|
|
const responseBody = await response.json();
|
|
const code = responseBody?.code;
|
|
expect(code).toBe('SUCCESS');
|
|
};
|
|
|
|
/**
|
|
* 批量创建顾客
|
|
* @param {Array<Customer>} customerArray
|
|
*/
|
|
createMoreCustomer = async (customerArray) => {
|
|
for (const customer of customerArray) {
|
|
await this.createCustomer(customer);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 批量设置无效客
|
|
* @param {Array<Customer>} customerArray
|
|
*/
|
|
setMoreInvalidCustomer = async (customerArray) => {
|
|
for (const customer of customerArray) {
|
|
await this.setInvalidCustomer(customer);
|
|
}
|
|
};
|
|
}
|
|
|
|
module.exports = { CustomerPage };
|