This repository has been archived on 2025-04-22. You can view files and clone it, but cannot push or open issues or pull requests.
hlk_autotest/tests/touch/boss_customer.spec.ts
2024-12-22 21:12:43 +08:00

3599 lines
178 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-check
import { test, expect } from '@/fixtures/boss_common.js';
import { faker } from '@faker-js/faker/locale/zh_CN';
import { Customer } from '@/utils/customer';
import { waitSpecifyApiLoad, convertAmountText, waitStable } from '@/utils/utils.js';
import { Employees, ProjectName } from '@/fixtures/userconfig.js';
import path from 'path';
import fs from 'fs';
import { HomeNavigation } from '@/pages/homeNavigationPage.js';
import { CustomerPage } from '@/pages/customer/customerPage.js';
test.describe('顾客通用', () => {
test.describe('快捷查询', () => {
const customer = new Customer(1, 1, {
archive: 'ABC' + faker.string.alpha(3),
employees: [
{
name: '周慧',
level: '咨询师',
},
],
});
/**@type {import('playwright').BrowserContext} */
let browserContext;
/**@type {import('playwright').Page} */
let page;
let homeNavigation;
let customerPage;
test.beforeAll(async ({ browser, baseURL }) => {
browserContext = await browser.newContext();
page = await browserContext.newPage();
if (!baseURL) throw new Error('baseURL is required');
await page.goto(baseURL);
await page.waitForLoadState('networkidle');
await page.reload();
await page.getByRole('button', { name: /开\s单/ }).waitFor();
homeNavigation = new HomeNavigation(page);
customerPage = new CustomerPage(page);
await homeNavigation.gotoModule('顾客');
await customerPage.createCustomer(customer);
});
test.afterAll(async () => {
homeNavigation = new HomeNavigation(page);
customerPage = new CustomerPage(page);
await homeNavigation.gotoModule('顾客');
await customerPage.setInvalidCustomer(customer);
await page.close();
await browserContext.close();
});
test('精准查询', async ({ page, homeNavigation, customerPage }) => {
/**@type{Set<String>} 搜索历史 */
let historySet = new Set();
// 去创建顾客
const username = customer.username;
const phone = customer.phone;
const archive = customer.archive;
await test.step('根据名字第一个字符进行搜索', async () => {
await homeNavigation.gotoModule('顾客');
const searchStr = username.substring(0, Math.ceil(username.length / 2));
await customerPage.searchCustomer(searchStr);
await page.locator('.alertBox .close').waitFor();
// 判断顾客存在
await expect(page.locator('.custom_content', { hasText: username })).toBeVisible();
// 添加到搜索历史
historySet.add(searchStr);
await page.locator('.alertBox .close .anticon-close').click();
});
await test.step('根据手机号进行搜索', async () => {
await customerPage.searchCustomer(phone);
await page.locator('.alertBox .close').waitFor();
// 判断顾客存在
await expect(page.locator('.custom_content', { hasText: username })).toBeVisible();
// 添加到搜索历史
historySet.add(phone);
await page.locator('.alertBox .close .anticon-close').click();
});
await test.step('根据档案号进行搜索', async () => {
await customerPage.searchCustomer(archive);
await page.locator('.alertBox .close').waitFor();
// 判断顾客存在
await expect(page.locator('.custom_content', { hasText: username })).toBeVisible();
// 添加到搜索历史
historySet.add(archive);
await page.locator('.alertBox .close .anticon-close').click();
});
await test.step('查询搜索历史', async () => {
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').click();
await page.locator('.historyALertBox_title', { hasText: '搜索历史' }).waitFor();
// 判断搜索历史是否存在
await expect(page.locator('.historyMemberList_item')).toContainText([...historySet].reverse());
});
});
test('顾客概要', async ({ page, homeNavigation, customerPage, tablePage }) => {
// 第一个顾客
const $firstCustomer = tablePage.fixedLeftTable.locator('tr td:nth-child(2)').locator('.name ').first();
await test.step('选择部门一,查看顾客详情', async () => {
await homeNavigation.gotoModule('顾客');
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 点击会员
await page.locator('.sub_icon').first().click();
await page.locator('.m-table__icon__warp').waitFor({ state: 'hidden' });
// 打开顾客详情
await $firstCustomer.click();
await page.locator('.basic_box .base_info').first().waitFor();
// 判断该会员所属部门是否有美容部
await expect(page.locator('.basic_box .item_txt1', { hasText: '美容部' })).toBeVisible();
// 关闭基础资料
await customerPage.closeCustomerDetail();
await page.locator('.store_mark').click();
await page.locator('.store_mark').waitFor({ state: 'hidden' });
});
await test.step('选择员工,查看顾客详情', async () => {
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').uncheck();
await page.getByLabel('周慧').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 打开顾客详情
await $firstCustomer.click();
await expect(page.locator('.employees_txt')).toContainText('周慧');
});
});
test('顾客分配', async ({ page, homeNavigation, customerPage, tablePage }) => {
// 第一个顾客
const $firstCustomer = tablePage.fixedLeftTable.locator('tr td:nth-child(2)').locator('.name ').first();
await test.step('顾客分配', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分配');
await page.locator('.assign_info').waitFor();
// 点击左上角门店
await page.locator('.shop-picker-store').click();
await page.locator('.shopSelect_title', { hasText: '选择查询对象' }).waitFor();
// 员工不可见
await expect(page.locator('.shopSelect_small_title', { hasText: '员工' })).not.toBeVisible();
// 选择美容部
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 打开顾客详情
await $firstCustomer.click();
await page.locator('.basic_box .base_info').first().waitFor();
// 判断该会员所属部门是否有美容部
await expect(page.locator('.basic_box .item_txt1', { hasText: '美容部' })).toBeVisible();
});
});
test('顾客动态', async ({ page, homeNavigation, customerPage, tablePage }) => {
// 第一个顾客
const $firstCustomer = tablePage.fixedLeftTable.locator('tr td:nth-child(2)').locator('.name ').first();
await test.step('选择部门一,查看顾客详情', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客动态');
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').check();
await page.getByRole('button', { name: /保\s存/ }).click();
await $firstCustomer.click();
await page.locator('.basic_box .base_info').first().waitFor();
await expect(page.locator('.basic_box .item_txt1', { hasText: '美容部' })).toBeVisible();
await page.locator('.close_icons').click();
await page.locator('.basic_box .base_info').waitFor({ state: 'hidden' });
});
await test.step('选择部门一的员工,查看顾客详情', async () => {
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').uncheck();
await page.getByLabel('周慧').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 打开顾客详情
await $firstCustomer.click();
// 判断分配员工
await expect(page.locator('.employees_txt')).toContainText('周慧');
});
});
test('顾客分析', async ({ page, homeNavigation, customerPage, tablePage }) => {
// 第一个顾客
const $firstCustomer = tablePage.fixedLeftTable.locator('tr td:nth-child(2)').locator('.name ').first();
await test.step('选择部门一,查看顾客详情', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分析');
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 打开顾客详情
await $firstCustomer.click();
await page.locator('.basic_box .base_info').first().waitFor();
await expect(page.locator('.basic_box .item_txt1', { hasText: '美容部' })).toBeVisible();
await page.locator('.close_icons').click();
await expect(page.locator('.basic_box .base_info')).not.toBeVisible();
});
await test.step('选择部门一的员工,查看顾客详情', async () => {
await page.locator('.shop-picker-store').click();
await page.getByLabel('医美部').uncheck();
await page.getByLabel('美容部').uncheck();
await page.getByLabel('周慧').check();
await page.getByRole('button', { name: /保\s存/ }).click();
// 打开顾客详情
await $firstCustomer.click();
// 判断分配员工
await expect(page.locator('.employees_txt')).toContainText('周慧');
});
});
});
test.describe('高级查询', () => {
const customer = new Customer(1, 1, {
archive: 'ABC' + faker.string.alpha(3),
employees: [
{
name: '周慧',
level: '咨询师',
},
],
source: 5,
});
/**@type {import('playwright').BrowserContext} */
let browserContext;
/**@type {import('playwright').Page} */
let page;
let homeNavigation;
let customerPage;
test.beforeAll(async ({ browser, baseURL }) => {
browserContext = await browser.newContext();
page = await browserContext.newPage();
if (!baseURL) throw new Error('baseURL is required');
await page.goto(baseURL);
await page.waitForLoadState('networkidle');
await page.reload();
await page.getByRole('button', { name: /开\s单/ }).waitFor();
homeNavigation = new HomeNavigation(page);
customerPage = new CustomerPage(page);
await homeNavigation.gotoModule('顾客');
await customerPage.createCustomer(customer);
await homeNavigation.gotoModule('收银');
// 给会员开卡
await page.getByRole('button', { name: /^开\s单$/ }).click();
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await page.locator('.number_service').waitFor();
await page.getByRole('button', { name: /^开\s卡$/ }).click();
// 选择会员卡A
await page.locator('.memberCard_box > .needsclick').getByText('会员卡A').click();
// 结算,选择现金支付
await page.getByRole('button', { name: '去结算' }).click();
await page.getByText('现金').click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.getByRole('button', { name: /^结\s算$/ }).click();
await page.getByRole('button', { name: /跳\s过/ }).click();
await page.getByRole('button', { name: '转寄存' }).click();
await page.getByRole('button', { name: /^确\s认$/ }).click();
// 关闭收银界面
await page.locator('use').first().click();
});
test.afterAll(async () => {
homeNavigation = new HomeNavigation(page);
customerPage = new CustomerPage(page);
await homeNavigation.gotoModule('顾客');
await customerPage.setInvalidCustomer(customer);
await page.close();
await browserContext.close();
});
test('组合查询', async ({ page, homeNavigation }) => {
await test.step('搜索关键字-姓', async () => {
// 点击顾客
await homeNavigation.gotoModule('顾客');
await page.locator('.ant-btn-default', { hasText: /^高\s级$/ }).click();
await page.locator('.shopSelect_title', { hasText: '顾客高级查询' }).waitFor();
// 根据所属门店点击右边搜索框
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '所属门店' }) })
.locator('.item_val')
.click();
// 通过点击两次全选达到所有门店不在选中状态
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
await expect(
page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' }),
).not.toBeVisible();
// 选择门店一店
await page.locator('.label_checkbox', { hasText: 'AT测试一店' }).click();
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).first().click();
// 搜索关键字'王'
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.username[0]);
// 选择拥有会员卡A
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '拥有的会员卡' }) })
.locator('.item_val')
.click();
await page.locator('.check_box_container', { hasText: '会员卡A' }).click();
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: '会员卡A' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).nth(5).click();
// 点击搜索
await page.locator('.ant-btn-block').click();
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: customer.phone })).toBeVisible();
});
});
test('保存查询', async ({ page, homeNavigation }) => {
await test.step('搜索关键字-姓', async () => {
// 点击顾客
await homeNavigation.gotoModule('顾客');
await page.locator('.ant-btn-default', { hasText: /^高\s级$/ }).click();
await page.locator('.shopSelect_title', { hasText: '顾客高级查询' }).waitFor();
// 点击两次全选确保所有门店默认未选
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '所属门店' }) })
.locator('.item_val')
.click();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断某个门店被选中
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断门店未被选中
await expect(
page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' }),
).not.toBeVisible();
await page.locator('.label_checkbox', { hasText: 'AT测试一店' }).click();
// 确认选中一店
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).first().click();
// 搜索关键字 王
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.username[0]);
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '拥有的会员卡' }) })
.locator('.item_val')
.click();
await page.locator('.check_box_container', { hasText: '会员卡A' }).click();
// 拥有会员卡A
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: '会员卡A' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).nth(5).click();
// 点击搜索
await page.locator('.ant-btn-block').click();
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: customer.phone })).toBeVisible();
});
await test.step('保存查询', async () => {
const identificationA = faker.person.fullName();
const identificationB = faker.person.fullName();
await page.locator('.item-btns', { hasText: '保存查询' }).waitFor();
await page.locator('.item-btns', { hasText: '保存查询' }).click();
await page.locator('.modal_header').waitFor();
await page.getByPlaceholder('请输入名称').fill(identificationA);
await expect(async () => {
await page.locator('.ant-btn-primary').last().click();
await expect(page.locator('.ant-modal-content')).not.toBeVisible({
timeout: 5000,
});
}).toPass();
// 操作成功
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
await page.locator('.item-btns', { hasText: '保存查询' }).waitFor();
await page.locator('.item-btns', { hasText: '保存查询' }).click();
await page.locator('.modal_header').waitFor();
await page.getByPlaceholder('请输入名称').fill(identificationB);
await page.locator('.search_tip').click();
await expect(async () => {
await page.locator('.ant-btn-primary').last().click();
await expect(page.locator('.ant-modal-content')).not.toBeVisible({
timeout: 5000,
});
}).toPass();
// 操作成功
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
// 点击高级搜索旁边三个点
await page.locator('.ant-btn-default .anticon').click();
await page.locator('.ant-tabs-tab').first().waitFor();
await page.locator('.ant-tabs-tab', { hasText: '保存的搜索器' }).click();
await page.locator('.tools_items .item').first().waitFor();
await page.locator('.tools_items .item', { hasText: identificationA }).click();
// 判断点击该搜索器是否能搜到该会员
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: customer.phone })).toBeVisible();
// 点击高级搜索旁边三个点
await page.locator('.ant-btn-default .anticon').click();
await page.locator('.tools_items .item').first().waitFor();
// 判断该搜索器有没有手机标识
const phoneLogo = page
.locator('.tools_items .item')
.filter({ has: page.locator('.tool_name', { hasText: identificationB }) })
.locator('.item_icon');
await expect(phoneLogo).toBeVisible();
});
await test.step('删除保存的搜索器', async () => {
// 点击高级搜索旁边三个点 上一步停留在了这里面不需要点
await page.locator('.ant-tabs-tab', { hasText: '保存的搜索器' }).click();
await page.locator('.tools_items .item').first().waitFor();
// 点击右上角设置齿轮
await page.locator('.edit_btn').click();
// 等待保存搜索的右上角叉叉按钮出现
await page.locator('.del_btn').first().click();
// 点击完成
await page.locator('.btn_ok').click();
// 操作成功
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
});
});
test('使用历史查询', async ({ page, homeNavigation, createCustomCustomer, customerPage }) => {
await test.step('搜索关键字-姓', async () => {
// 点击顾客
await homeNavigation.gotoModule('顾客');
await page.locator('.ant-btn-default', { hasText: /^高\s级$/ }).click();
await page.locator('.shopSelect_title', { hasText: '顾客高级查询' }).waitFor();
// 点击两次全选确保所有门店默认未选
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '所属门店' }) })
.locator('.item_val')
.click();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断某个门店被选中
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断门店未被选中
await expect(
page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' }),
).not.toBeVisible();
await page.locator('.label_checkbox', { hasText: 'AT测试一店' }).click();
// 确认选中一店
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).first().click();
// 搜索关键字 A
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.username[0]);
// 拥有会员卡A
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '拥有的会员卡' }) })
.locator('.item_val')
.click();
await page.locator('.check_box_container', { hasText: '会员卡A' }).click();
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: '会员卡A' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).nth(5).click();
// 点击搜索
await page.locator('.ant-btn-block').click();
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: customer.phone })).toBeVisible();
});
await test.step('历史查询', async () => {
// 点击高级搜索旁边三个点
await page.locator('.ant-btn-default .anticon').click();
await page.locator('.ant-tabs-tab').first().waitFor();
await page.locator('.ant-tabs-tab', { hasText: '历史搜索' }).click();
await page.locator('.ant-tabs-tab-active', { hasText: '历史搜索' }).first().waitFor();
const $history = page
.locator('.search_list_ul .text', { hasText: `门店AT测试一店关键字${customer.username[0]};` })
.first();
await $history.click();
// 判断点击该搜索器是否能搜到该会员
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: customer.phone })).toBeVisible();
});
});
test('快捷搜索', async ({ page, homeNavigation }) => {
// 进入顾客列表
await homeNavigation.gotoModule('顾客');
// 点击高级搜索旁边三个点
await page.locator('.ant-btn-default .anticon').click();
await page.locator('.ant-tabs-tab').first().waitFor();
await page.locator('.ant-tabs-tab', { hasText: '快捷搜索' }).click();
await page.locator('.ant-tabs-tab-active', { hasText: '快捷搜索' }).first().waitFor();
await page
.locator('.class_tag')
.first()
.locator('.class_list', { hasText: /^会员$/ })
.click();
await expect(page.locator('.selected', { hasText: /^会员$/ }).first()).toBeVisible();
await page
.locator('.ant-btn-lg', { hasText: /^搜\s索$/ })
.last()
.click();
// 判断是否有会员标识
const identification = page
.locator('.m-table__fixed-left .m-table__body tbody tr')
.first()
.locator('td .icon_style', { hasText: '会' });
await expect(identification).toBeVisible();
});
});
test('顾客分页', async ({ page, homeNavigation }) => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 获取第一页会员信息
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
const pagePhone1 = await member.locator('td .user_info_body').first().innerText();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取第二页会员信息
await page.locator('.m-table-pagination .dec').waitFor();
const pagePhone2 = await member.locator('td .user_info_body').first().innerText();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取第三页会员信息
await page.locator('.m-table-pagination .dec').waitFor();
const pagePhone3 = await member.locator('td .user_info_body').first().innerText();
expect(pagePhone1).not.toBe(pagePhone2);
expect(pagePhone1).not.toBe(pagePhone3);
expect(pagePhone2).not.toBe(pagePhone3);
});
});
test.describe('顾客动态', () => {
test('新增事项', async ({ page, homeNavigation, createCustomer, customerPage }) => {
const customer = createCustomer;
const today = new Date().getDate(); // 获取今日的天数
const customerTr = page.locator('.m-table__body-wrapper tbody tr', {
hasText: customer.phone,
});
const customerTd = customerTr.locator('td .cell');
await test.step('搜索顾客存在', async () => {
// 进入顾客页面
await homeNavigation.gotoModule('顾客');
// 跳转到顾客动态
await customerPage.gotoSubPage('顾客动态');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await expect(page.locator('.m-table__fixed-left').getByText(customer.username)).toBeVisible();
});
await test.step('切换时间为上月,新增事项', async () => {
await page.locator('.ant_date').getByPlaceholder('开始日期').click();
await page.getByRole('button', { name: /^上\s月$/ }).click();
// 选择上月第一天
await customerTd.first().click();
// 过去时间不可新增事项!
await expect(page.locator('.ant-message', { hasText: '过去时间不可新增事项!' })).toBeVisible();
});
await test.step('切换时间为本月,新增事项', async () => {
await page.locator('.ant_date').getByPlaceholder('开始日期').click();
await page.getByRole('button', { name: /^本\s月$/ }).click();
// 选择本月第today天当天
await customerTd.nth(today - 1).click();
await page.locator('.action .shopSelect_title', { hasText: '新增事项' }).waitFor();
await page.locator('label', { hasText: '电话回访' }).click();
await page.getByPlaceholder('请输入1-100个字符的备注内容').fill('今日新增待办事项');
await page.getByRole('button', { name: '确认添加' }).click();
await expect(customerTd.nth(today - 1).locator('.cell-warp—td')).toBeVisible();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
});
await test.step('查看今日事项,删除事项', async () => {
// 打开今日事项
await customerTd.nth(today - 1).click();
await expect(page.locator('.remark_area span')).toContainText('今日新增待办事项');
await expect(
page
.locator('.item')
.filter({ has: page.locator('.name', { hasText: '事项状态' }) })
.locator('.status'),
).toContainText('已完成');
// 删除事项
await page.locator('.action').getByRole('button', { name: '删除' }).click();
await page
.locator('.popup_content')
.getByRole('button', { name: /^确\s认$/ })
.click();
await expect(customerTd.nth(today - 1).locator('.cell-warp—td')).not.toBeVisible();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
await customerTd.nth(today - 1).click();
await expect(page.locator('.action .shopSelect_title')).toContainText('新增事项');
// 关闭弹窗
await page.locator('.action > div > div > .shopSelect_box > .shopSelect_heard > .close > svg').click();
});
await test.step('新增明日事项,查看事项', async () => {
// 选择本月第today天的明天明天
await customerTd.nth(today).click();
await page.locator('.action .shopSelect_title', { hasText: '新增事项' }).waitFor();
await page.locator('label', { hasText: '电话回访' }).click();
await page.getByPlaceholder('请输入1-100个字符的备注内容').fill('新增明日待办事项');
await page.getByRole('button', { name: '确认添加' }).click();
await expect(customerTd.nth(today).locator('.cell-warp—td')).toBeVisible();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
// 打开明日事项
await customerTd.nth(today).click();
await page.locator('.action .shopSelect_title', { hasText: '电话回访' }).waitFor();
await expect(page.locator('.remark_area span')).toContainText('新增明日待办事项');
await expect(
page
.locator('.item')
.filter({ has: page.locator('.name', { hasText: '事项状态' }) })
.locator('.status'),
).toContainText('待完成');
});
});
test('完成事项', async ({ page, homeNavigation, createCustomer }) => {
const customer = createCustomer;
// 事项状态
let statusText;
// 当前顾客处于第几行,默认第一行
let nowRow = 0;
// 获取当前月份
const nowMonth = new Date().getMonth();
// 获取今日的天数
const today = new Date().getDate();
// 进入顾客动态
await homeNavigation.gotoModule('顾客');
await page.locator('.top_tab').getByText('顾客动态').click();
await page.getByText('图标注释').waitFor();
// 根据手机号进行搜索
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.phone);
await page.locator('.ant-input-suffix .search_btn').getByText('搜索', { exact: true }).click();
await page.locator('.alertBox .close').waitFor();
await page.locator('.custom_content', { hasText: customer.username }).click();
// 设置生日
await page.locator('.m-table__fixed-left').getByText(customer.username).click();
await page.locator('.person_info .user_name .edit_icon').click();
await page.locator('.birth_content', { hasText: '日期' }).click();
// 选择日
await page
.getByRole('listbox')
.first()
.getByRole('option')
.nth(today - 1)
.click();
// 选择月
await page.getByRole('listbox').last().getByRole('option').nth(nowMonth).click();
await page.getByRole('button', { name: /^确\s认$/ }).click();
await page.getByRole('button', { name: /^保\s存$/ }).click();
await expect(page.locator('.ant-message', { hasText: '修改成功' })).toBeVisible();
await page.locator('.close_icons svg').click();
// 切换时间为本月
await page.locator('.ant_date').getByPlaceholder('开始日期').click();
await page.getByRole('button', { name: /^本\s月$/ }).click();
// 选择本月第today天当天
const allTr = page.locator('.m-table__body-wrapper tbody tr');
await allTr
.nth(nowRow)
.locator('td .cell')
.nth(today - 1)
.click();
await page.getByRole('button', { name: '完成该事项' }).click();
await page.getByPlaceholder('这里显示的回访完成后的反馈内容').fill('测试完成该事项');
await page.getByRole('button', { name: /^提\s交$/ }).click();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
const $statusText = page
.locator('.item')
.filter({ has: page.locator('.name', { hasText: '事项状态' }) })
.locator('.status');
await expect($statusText).toContainText('已完成');
});
test('排序', async ({ page, homeNavigation, customerPage }) => {
const customerTrList = page.locator('.m-table-fixed-body tbody > tr');
const consumeTotalList = page.locator('.consume_total');
const amountTotalLocator = consumeTotalList.locator('.total_').filter({ hasText: '现金总额' });
const lastTimeArrivalLocator = consumeTotalList.locator('.consume_list').filter({ hasText: '上次到店' });
const closeMemberBoxLocator = page.locator('.close_icons');
const sortToolLocator = page.locator('.table_tools').getByText('排序');
let amountTotal, previousAmountTotal;
let lastTimeArrival, previousLastTimeArrival;
let tmp;
await test.step('上次到店时间', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客动态');
await sortToolLocator.click();
await page.getByRole('menuitem', { name: '上次到店时间从远到近' }).click();
await customerTrList.nth(0).waitFor();
await customerTrList.nth(0).locator('.name').click();
tmp = await lastTimeArrivalLocator.locator('.detail_txt').innerText();
lastTimeArrival = tmp.includes('--') ? 0 : Number(tmp);
previousLastTimeArrival = lastTimeArrival;
await closeMemberBoxLocator.click();
await sortToolLocator.click();
await page.getByRole('menuitem', { name: '上次到店时间从近到远' }).click();
await customerTrList.nth(0).waitFor();
await customerTrList.nth(0).locator('.name').click();
tmp = await lastTimeArrivalLocator.locator('.detail_txt').innerText();
lastTimeArrival = tmp.includes('--') ? 0 : Number(tmp);
previousLastTimeArrival = lastTimeArrival;
await closeMemberBoxLocator.click();
expect(lastTimeArrival).toBeGreaterThanOrEqual(previousLastTimeArrival);
});
await test.step('现金总额', async () => {
await sortToolLocator.click();
await page.getByRole('menuitem', { name: '现金总额从多到少' }).click();
await customerTrList.nth(0).waitFor();
await customerTrList.nth(0).locator('.name').click();
tmp = await amountTotalLocator.locator('.total_num').innerText();
amountTotal = Number(tmp);
previousAmountTotal = amountTotal;
await closeMemberBoxLocator.click();
await sortToolLocator.click();
await page.getByRole('menuitem', { name: '现金总额从多到少' }).click();
await customerTrList.nth(0).waitFor();
await customerTrList.nth(0).locator('.name').click();
tmp = await amountTotalLocator.locator('.total_num').innerText();
amountTotal = Number(tmp);
previousAmountTotal = amountTotal;
await closeMemberBoxLocator.click();
expect(amountTotal).toBeLessThanOrEqual(previousAmountTotal);
});
});
});
test.describe('顾客详情', () => {
test('修改顾客资料(标签、档案、到店周期、备注)', async ({
page,
homeNavigation,
customerPage,
createCustomer,
}) => {
const customer = createCustomer;
const infoBox = page.locator('.info_box');
await test.step('设置顾客标签', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
const noSignLocator = infoBox.getByText('暂未添加标签');
await expect(noSignLocator).toBeVisible();
await infoBox.locator('.sign i').click();
await expect(page.getByRole('button', { name: '移除所有选中' })).toBeVisible();
const signSelectLocator = page.getByRole('treeitem', { name: '顾客六期管理' });
await signSelectLocator.getByText('问题期').click();
await signSelectLocator.getByText('铺垫期').click();
await page.getByRole('button', { name: /确\s认/ }).click();
await expect(page.locator('.ant-message', { hasText: '修改成功' })).toBeVisible();
await expect(noSignLocator).not.toBeVisible();
await expect(page.locator('.sign_txt')).toContainText(['问题期', '铺垫期']);
});
await test.step('设置档案', async () => {
const infoBox = page.locator('.info_box');
const popupLocator = page.locator('.popup_content');
const titlePopup = popupLocator.locator('.title_box');
const rightPopup = popupLocator.locator('.right_item_box');
const archiveContent = faker.string.fromCharacters('编辑档案', 8);
const editArchive = page.locator('.box', { hasText: '编辑顾客档案' });
const archivesLocator = infoBox.getByText('档案完成度');
await expect(archivesLocator).toBeVisible();
await infoBox.locator('.file_box .edit_icon').click();
await expect(titlePopup.getByText('定制顾客档案', { exact: true })).toBeVisible();
await rightPopup.locator('.edit_icon').click();
await editArchive
.locator('.item', { hasText: '基本描述信息' })
.getByPlaceholder('请输入1-500个字符备注内容')
.fill(archiveContent);
await editArchive.getByRole('button', { name: /保\s存/ }).click();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
// 打开档案编辑页面
await expect(archivesLocator).toBeVisible();
await infoBox.locator('.file_box .edit_icon').click();
await expect(rightPopup).toContainText(archiveContent);
await page.locator('.title > .close_icon > svg > use').click();
});
await test.step('修改到店周期', async () => {
const storeCycleDay = '0'; // 到店周期实际值
const expectStoreCycleDay = '3'; // 到店周期期望值
const consumeList = infoBox.locator('.consume_list');
const storeCycle = consumeList.filter({
has: page.getByText('到店周期', { exact: true }),
});
await storeCycle.waitFor();
const storeCycleText = storeCycle.locator('.detail_txt');
await expect(storeCycleText).toHaveText('0');
await storeCycle.locator('.edit_icon').click();
await page.getByPlaceholder('请输入天数').fill(expectStoreCycleDay);
await page.locator('.number_box').getByRole('button').nth(11).click();
await expect(page.locator('.ant-message', { hasText: '修改成功' })).toBeVisible();
// 原来的值消失
await expect(storeCycleText.filter({ hasText: storeCycleDay })).not.toBeVisible();
// 更改为期望值显示
await expect(storeCycleText.filter({ hasText: expectStoreCycleDay })).toBeVisible();
});
await test.step('修改备注', async () => {
const popupLocator = page.locator('.popup_content');
const remark = faker.string.fromCharacters('修改备注', 8);
const baseInfo = page.locator('.base_info .base_info_list');
const remarkLocator = baseInfo.filter({ has: page.getByText('备注', { exact: true }) });
await expect(async () => {
await remarkLocator.locator('.edit_icon').click();
await popupLocator.getByPlaceholder('请输入1-100个字符备注内容').fill(remark);
await page.getByRole('button', { name: /保\s存/ }).click();
await expect(page.locator('.ant-message', { hasText: '修改成功' })).toBeVisible();
await expect(remarkLocator).toContainText(remark, { timeout: 3_000 });
}).toPass();
});
});
test('在顾客详情页面开卡', async ({ page, homeNavigation, customerPage, createCustomer }) => {
const customer = createCustomer;
const card = page.locator('.has_card .membercard_box', { hasText: '原价卡' });
await test.step('开卡', async () => {
// 进入顾客详情页面
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
// 去开卡
await page
.locator('.info_package')
.getByRole('button', { name: /开\s卡/ })
.click();
await page.locator('.openCard_box', { hasText: '会员卡购买' }).waitFor();
await page.locator('.openCard_box .memberCard_box', { hasText: '原价卡' }).click();
await page.locator('.remark', { hasText: '可输入卡备注' }).click();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试顾客详情页面开卡');
await page.getByRole('button', { name: /确\s认/ }).click();
await page.getByRole('button', { name: '去结算' }).click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.locator('.paytype .paymentInfoItem', { hasText: '现金' }).click();
await page.getByRole('button', { name: /结\s算/ }).click();
await page.locator('.popup_content', { hasText: '会员协议签署确认' }).waitFor();
await page.getByRole('button', { name: /跳\s过/ }).click();
// 判断会员卡存在
await expect(card.locator('.other_row .comment_item')).toHaveText('测试顾客详情页面开卡');
});
});
test('操作会员卡', async ({ page, homeNavigation, customerPage, createCustomer }) => {
const cardInfo = { name: '原价卡', gold: 5000, bonus: 3000 };
const card = page.locator('.has_card .membercard_box', { hasText: cardInfo.name });
const customer = createCustomer;
await test.step('开卡', async () => {
await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /开\s单/ }).click();
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await page.getByRole('button', { name: /开\s卡/ }).click();
// 会员卡定位器
const $card = page.locator('.openCard_box .memberCard_box', { hasText: cardInfo.name });
await $card.click();
// 判断卡金、赠金符合预期值
await expect($card.locator('.balance.needsclick')).toContainText(`${cardInfo.gold}`);
await expect($card.locator('.bonus.needsclick')).toContainText(`${cardInfo.bonus}`);
// 备注会员卡,进行结算
await page.locator('.remark', { hasText: '可输入卡备注' }).click();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试操作会员卡');
await page.getByRole('button', { name: /确\s认/ }).click();
await page.getByRole('button', { name: '去结算' }).click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.locator('.paytype .paymentInfoItem', { hasText: '现金' }).click();
await page.getByRole('button', { name: /结\s算/ }).click();
await page.getByRole('button', { name: /跳\s过/ }).click();
await expect(page.locator('.ant-message', { hasText: '结算成功' })).toBeVisible();
// 返回首页
await page.locator('.anticon > svg').first().click();
// 进入顾客详情页面,判断会员卡存在
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
// 判断会员卡存在
await expect(card.locator('.other_row .comment_item')).toHaveText('测试操作会员卡');
});
const modifiedCardGold = cardInfo.gold + 1000;
await test.step('修改卡金', async () => {
await page.locator('.card_control_btn .more').click();
await page.getByRole('menuitem', { name: '修改卡金' }).click();
await page.getByPlaceholder('请输入内容@.').fill(`${modifiedCardGold}`);
// 点击确认按钮
await page.locator('.number_tr').nth(2).getByRole('button').nth(3).click();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试修改卡金');
await page.getByRole('button', { name: /确\s认/ }).click();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
await expect(card.locator('.balances')).toContainText(`${modifiedCardGold}`);
});
const modifiedCardBonus = cardInfo.bonus + 1000;
await test.step('修改赠送金', async () => {
await page.locator('.card_control_btn .more').click();
await page.getByRole('menuitem', { name: '修改赠送金' }).click();
await page.getByPlaceholder('请输入内容@.').fill(`${modifiedCardBonus}`);
// 点击确认按钮
await page.locator('.number_tr').nth(2).getByRole('button').nth(3).click();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试修改赠金');
await page.getByRole('button', { name: /确\s认/ }).click();
await expect(card.locator('.bonuses')).toContainText(`${modifiedCardBonus}`);
});
// 随机卡号card****
const modifiedCardNo = faker.helpers.fromRegExp(/card[0-9]{4}/);
await test.step('修改卡号', async () => {
await page.locator('.card_control_btn .more').click();
await page.getByRole('menuitem', { name: '修改卡号' }).click();
await page.getByPlaceholder('请输入新卡号').fill(modifiedCardNo);
await page.getByRole('button', { name: /确\s认/ }).click();
// 判断卡号修改成功
await expect(card.locator('.number_row .numebr')).toContainText(modifiedCardNo);
});
await test.step('修改有效期会员卡左上角展示有效期提示“剩1天过期”', async () => {
await page.locator('.card_control_btn .more').click();
await page.getByRole('menuitem', { name: '修改有效期' }).click();
await page.getByPlaceholder('选择日期').click();
await page
.locator('span')
.filter({ hasText: /^今天$/ })
.click();
await page.getByRole('button', { name: /确\s认/ }).click();
// 剩1天过期
await expect(card.locator('.expireDay_box')).toContainText('剩1天');
});
await test.step('删除会员卡', async () => {
await page.locator('.card_control_btn .more').click();
await page.getByRole('menuitem', { name: '删除卡' }).click();
await page.getByRole('button', { name: /确\s认/ }).click();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill('测试删除会员卡');
await page.getByRole('button', { name: /确\s认/ }).click();
await expect(card).not.toBeVisible();
await page.getByText('未使用').click();
await page.locator('.ant-select-dropdown').getByRole('option', { name: '已删除' }).click();
await expect(card.locator('.card_name .overTime_tag').last()).toContainText('已删');
});
});
test('操作套餐', async ({ page, homeNavigation, customerPage, createCustomer }) => {
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 $$treatCard = page.locator('.treat_card').filter({ has: $setMeal });
const customer = createCustomer;
await test.step('开单买[护理修护全套]', async () => {
await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /开\s单/ }).click();
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.phone);
await page.getByText('搜索', { exact: true }).click();
await page.locator('.member_list_li').filter({ hasText: customer.phone }).click();
await page.getByText('套餐').click();
await page.getByText('护理修护全套').last().click();
await page.getByText(/结\s算/).click();
await page.locator('.paymentInfoItem').first().click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.locator('.paytype .paymentInfoItem', { hasText: '现金' }).click();
await page.getByRole('button', { name: /结\s算/ }).click();
await page.locator('.popup_content', { hasText: '会员协议签署确认' }).waitFor();
// 结算
const [response] = await Promise.all([
page.waitForResponse(async res => {
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
}),
page.getByRole('button', { name: /跳\s过/ }).click(),
]);
const responseBody = await response.json();
billNo = responseBody?.content?.billNo;
expect(billNo).not.toBeNull();
await page.getByRole('button', { name: '不寄存' }).click();
});
await test.step('打开顾客详情页面', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
});
await test.step('查看套餐消耗记录', async () => {
await page.locator('label').filter({ hasText: '套餐' }).click();
await expect($setMeal).toBeVisible();
await $$treatCard.first().locator('svg').last().click();
await page.getByText('消耗记录').click();
await expect(page.getByText(billNo).last()).toBeVisible();
await page
.locator('div')
.filter({ hasText: /^消耗记录$/ })
.locator('use')
.click();
});
await test.step('冻结有效期-解冻有效期', async () => {
// 冻结日期
const freezeStr = `${currentYear}-${currentMonth}-${dayStr}冻结`;
// 冻结有效期
await $$treatCard.first().locator('svg').last().click();
await page.getByText('冻结有效期').click();
await Promise.all([page.getByRole('button', { name: /确\s认/ }).click(), page.waitForLoadState()]);
await expect(page.locator('.ant-message')).toContainText('修改成功');
await expect($$treatCard.first().locator('.deadline_row span')).toContainText(freezeStr);
// 解冻有效期
await expect(async () => {
await $$treatCard.first().locator('svg').last().click();
await page.getByText('解冻有效期').click({ timeout: 2000 });
await expect($$treatCard.first().locator('.deadline_row span')).not.toContainText(freezeStr, {
timeout: 2000,
});
}).toPass();
});
});
test('查看流水', async ({ page, homeNavigation, createCustomer, customerPage, numberInput }) => {
const remark = '测试查看流水' + faker.string.numeric(3); // 当前备注
const project = { no: '100018', name: '苹果精萃护理', shortName: '精萃护理', price: 980 };
const goods = { no: 'aa100001', name: '家居搭配护理套', shortName: '', price: 3980 };
const cardInfo = { name: '原价卡', gold: 5000, bonus: 3000 };
// 预期的支付明细
const paymentDetail = [
{ method: '卡金', amount: 1000 },
{ method: '赠金', amount: 1000 },
{ method: '积分', amount: 1000 },
{ method: '欠款', amount: 1000 },
{ method: '优惠券', amount: 10 },
{ method: '现金', amount: 950 },
];
const customer = createCustomer;
await test.step('开卡', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
await page.getByRole('button', { name: /开\s卡/ }).click();
// 会员卡定位器
const $card = page.locator('.openCard_box .memberCard_box', { hasText: cardInfo.name });
await $card.click();
// 判断卡金、赠金符合预期值
await expect($card.locator('.balance.needsclick')).toContainText(`${cardInfo.gold}`);
await expect($card.locator('.bonus.needsclick')).toContainText(`${cardInfo.bonus}`);
await page.getByRole('button', { name: '去结算' }).click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.locator('.paytype .paymentInfoItem', { hasText: '现金' }).click();
await page.getByRole('button', { name: /结\s算/ }).click();
await page.getByRole('button', { name: /跳\s过/ }).click();
// 判断会员卡存在
const card = page.locator('.has_card .membercard_box', { hasText: cardInfo.name });
await expect(card).toBeVisible();
});
await test.step('赠送1000积分1积分兑换1元', async () => {
await page.getByRole('tab', { name: '流水' }).click();
await page.locator('.label_text', { hasText: '积分记录' }).click();
await page.getByRole('button', { name: /^赠\s送$/ }).click();
const point = paymentDetail.find(e => e.method === '积分')?.amount ?? 0;
await numberInput.setPointValue(point);
await numberInput.confirmValue();
await page.locator('.popup_content', { hasText: '赠送积分备注' }).waitFor();
await page.getByPlaceholder('请输入1-100个字符备注内容').fill(remark);
await page.locator('.popup_content input[type=radio]').click();
await page.getByRole('button', { name: /确\s认/ }).click();
});
let billNo: string;
await test.step('购买项目并消耗,购买卖品并结算,结算使用优惠券、卡金、赠金、欠款、积分,拿取单号', async () => {
// 左右两侧的支付方式定位器
const rightPaymentInfoItem = page.locator('.right .paymentmain .paymentInfoItem');
const leftPaymentInfoItem = page.locator('.left .paymentmain .paymentInfoItem');
await page.locator('.right_util .goto_pay_cash', { hasText: '去开单' }).click();
// 购买项目并消耗价格980
await page.locator('.project_list .number', { hasText: project.no }).click();
await page.locator('#shoppingCart .commodity_list li').first().click();
// 购买卖品并结算价格3980
await page.locator('.float_tab .item', { hasText: '卖品' }).click();
await page.locator('.project_list .number', { hasText: goods.no }).click();
await page.locator('.pay_btn', { hasText: /结\s算/ }).click();
// 赠送优惠券价格10
await page.locator('.payMain .left .body .row', { hasText: '优惠券抵扣' }).click();
await page.getByRole('button', { name: '赠送优惠券' }).click();
await page.locator('.popup_content', { hasText: '选择优惠券' }).waitFor();
await page
.locator('.popup_content .list .item', { hasText: '定额10元券' })
.locator('input[type="checkbox"]')
.click();
await page
.locator('.popup_content')
.getByRole('button', { name: /^确\s定$/ })
.click();
// 使用优惠券
await page.locator('.m_sliding_menu .body .box').first().locator('input[type="checkbox"]').check();
await page.getByRole('button', { name: '确认选择' }).click();
await leftPaymentInfoItem.filter({ hasText: '混合支付' }).click();
await rightPaymentInfoItem.filter({ hasText: '卡金' }).click();
await page.getByRole('button', { name: '增加收款' }).click();
await numberInput.setCommonValue(paymentDetail.find(e => e.method === '卡金')?.amount ?? 0);
await numberInput.confirmValue();
await rightPaymentInfoItem.filter({ hasText: '赠金' }).click();
await page.getByRole('button', { name: '增加收款' }).click();
await numberInput.setCommonValue(paymentDetail.find(e => e.method === '赠金')?.amount ?? 0);
await numberInput.confirmValue();
await rightPaymentInfoItem.filter({ hasText: '欠款' }).click();
await page.getByRole('button', { name: '增加收款' }).click();
await numberInput.setCommonValue(paymentDetail.find(e => e.method === '欠款')?.amount ?? 0);
await numberInput.confirmValue();
await rightPaymentInfoItem.filter({ hasText: '积分' }).click();
await page.getByRole('button', { name: '增加收款' }).click();
await numberInput.setCommonValue(paymentDetail.find(e => e.method === '积分')?.amount ?? 0);
await numberInput.confirmValue();
await rightPaymentInfoItem.filter({ hasText: '现金' }).first().click();
await page.getByRole('button', { name: '增加收款' }).click();
await numberInput.confirmValue();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
// 结算
const [response] = await Promise.all([
page.waitForResponse(async res => {
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
}),
page.getByRole('button', { name: /^结\s算$/ }).click(),
]);
const responseBody = await response.json();
billNo = responseBody?.content?.billNo;
expect(billNo).not.toBeNull();
await page.getByRole('button', { name: '不寄存' }).click();
});
const consumeTrLocator = page.locator('.consume_table .m-table__body tr');
const billNoLocator = consumeTrLocator.locator('.bill_no', { hasText: billNo });
const billTrLocator = consumeTrLocator.filter({
has: page.locator('.bill_no', { hasText: billNo }),
});
await test.step('进入顾客的详情页面的流水', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
await page.getByRole('tab', { name: '流水' }).click();
});
// 消费记录区域
const consume = page.locator('.m-detailComponent_warp');
// 购买区
const consumeBuy = consume.locator('.m-detailComponent_item').nth(0);
// 支付明细
const consumeDetail = consume.locator('.m-detailComponent_consume');
await test.step('查看购买记录和单据明细', async () => {
// 购买记录
await page.locator('.label_text', { hasText: '购买记录' }).click();
await expect(billNoLocator).toBeVisible();
await billNoLocator.click();
await consumeBuy.locator('.main-table-body_tr').last().waitFor();
// 项目简称、卖品名称
await expect(consumeBuy.locator('.main-table-body_tr')).toContainText([project.name, goods.name]);
// 总金额
await expect(consumeDetail.locator('.amount')).toContainText(`${project.price + goods.price}`);
// 欠款金额
await expect(consumeDetail.locator('.overdraft')).toContainText(
`${paymentDetail.find(e => e.method === '欠款')?.amount}`,
);
await expect(consumeDetail.locator('.m-detailComponent_consume_detail > div')).toContainText([
`优惠券¥${paymentDetail.find(e => e.method === '优惠券')?.amount}`,
`卡金¥${paymentDetail.find(e => e.method === '卡金')?.amount}`,
`赠金¥${paymentDetail.find(e => e.method === '赠金')?.amount}`,
`积分¥${paymentDetail.find(e => e.method === '积分')?.amount}`,
`现金¥${paymentDetail.find(e => e.method === '现金')?.amount}`,
]);
await page
.locator('div')
.filter({ hasText: /^单据明细$/ })
.locator('i')
.click();
});
await test.step('查看赠送记录', async () => {
await page.locator('.label_text', { hasText: '赠送记录' }).click();
await expect(billNoLocator).not.toBeVisible();
});
await test.step('查看消耗记录', async () => {
// 消耗记录
await page.locator('.label_text', { hasText: '消耗记录' }).click();
// 单据明细
await expect.soft(billNoLocator).toBeVisible();
// 项目简称
await expect.soft(billTrLocator.first().locator('.consume_shortname')).toContainText(project.shortName);
await expect.soft(billTrLocator.first().locator('.num')).toContainText('1');
await expect(billTrLocator.first().locator('.price')).toContainText(`${project.price}`);
});
await test.step('查看退换记录', async () => {
// 退换记录
await page.locator('.label_text', { hasText: '退换记录' }).click();
await expect(billNoLocator).not.toBeVisible();
});
await test.step('查看会员卡记录', async () => {
await page.locator('.label_text', { hasText: '会员卡记录' }).click();
await page.getByRole('cell', { name: '单号' }).waitFor();
const row = consumeTrLocator
.filter({
has: page.locator('td', { hasText: '消费' }),
})
.filter({
has: page.locator('td', { hasText: billNo }),
});
// 卡金
await expect(row.locator('td').nth(4)).toContainText(
`${paymentDetail.find(e => e.method === '卡金')?.amount}`,
);
// 赠金
await expect(row.locator('td').nth(5)).toContainText(
`${paymentDetail.find(e => e.method === '赠金')?.amount}`,
);
});
await test.step('查看积分记录', async () => {
await page.locator('.label_text', { hasText: '积分记录' }).click();
await expect(
consumeTrLocator
.filter({ has: page.locator('td', { hasText: '线下抵扣' }) })
.locator('td')
.nth(1),
).toContainText(`${paymentDetail.find(e => e.method === '积分')?.amount}`);
});
await test.step('查看优惠券记录', async () => {
await page.locator('.label_text', { hasText: '优惠券记录' }).click();
const pointLocator = consumeTrLocator
.filter({ has: page.locator('td', { hasText: '定额10元券' }) })
.filter({ has: page.locator('td', { hasText: '已使用' }) })
.filter({ has: page.locator('td', { hasText: /¥\s4960/ }) });
await expect(pointLocator).toBeVisible();
});
await test.step('查看卖品记录', async () => {
await page.locator('.label_text', { hasText: '卖品记录' }).click();
const productLocator = consumeTrLocator
.filter({ has: page.locator('td', { hasText: billNo }) })
.filter({ has: page.locator('td', { hasText: '购买' }) })
.filter({ has: page.locator('td', { hasText: goods.name }) });
await expect(productLocator).toBeVisible();
});
await test.step('查看欠还款记录,并且还款', async () => {
await page.locator('.label_text', { hasText: '欠还款记录' }).click();
const paybackLocator = page
.locator('.reimbursement_list')
.filter({
has: page.locator('.reimbursement_order', { hasText: billNo }),
})
.first();
// 还款存在
await expect(paybackLocator).toBeVisible();
// 进行还款
await paybackLocator.getByRole('button', { name: /^还\s款$/ }).click();
await page.getByText('现金', { exact: true }).click();
// 结算
await page.getByRole('button', { name: /^结\s算$/ }).click();
await expect(paybackLocator.filter({ hasText: '已清' })).toBeVisible();
});
});
test('查看动态', async ({ page, homeNavigation, createCustomer, customerPage, customerDetailsPage }) => {
const customer = createCustomer;
const date = new Date();
const currentYear = date.getFullYear();
const currentMonth = date.getMonth() + 1;
const currentDay = date.getDate();
/**@type {string} */
let billNo = '';
await test.step('开单拿取单号', async () => {
await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /开\s单/ }).click();
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(customer.phone);
await page.getByText('搜索', { exact: true }).click();
await page.locator('.member_list_li').filter({ hasText: customer.phone }).click();
await page.locator('.list_box .project_list').first().click();
await page
.locator('.pay_btn')
.filter({ hasText: /^结\s算$/ })
.click();
//取消推送消息提醒
await page.getByLabel('推送消费提醒').uncheck();
//取消结算签字
await page.getByLabel('结算签字').uncheck();
await page.locator('.paymentInfoItem').first().click();
// 结算
const [response] = await Promise.all([
page.waitForResponse(async res => {
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
}),
page.getByRole('button', { name: /^结\s算$/ }).click(),
]);
billNo = (await response.json())?.content?.billNo;
expect(billNo).not.toBeNull();
});
await test.step('进入顾客详情页面', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
});
await test.step('查看日动态', async () => {
// 日历列表
const $$calendarList = page.locator('.calendar_list').filter({
has: page.getByText(`${currentYear}${currentMonth.toString().padStart(2, '0')}`, {
exact: true,
}),
});
// 当前日期的动态
const $$dayForDynamics = $$calendarList
.getByTitle(`${currentMonth}${currentDay}`)
.getByRole('listitem')
.locator('div');
// 进入顾客详情动态页面
await customerDetailsPage.gotoSubPage('动态');
await expect($$dayForDynamics.first()).toBeInViewport();
await $$dayForDynamics.first().click();
await page.getByRole('button', { name: '查看消费详情' }).click();
await expect(page.getByText(billNo)).toBeVisible();
await page
.locator('div')
.filter({ hasText: /^单据明细$/ })
.locator('svg')
.click();
await page.locator('.shopSelect_heard > .close > svg').first().click();
});
// 今年所有月份的动态
const $$dynamic = page.locator('.calendar_year_list', { hasText: `${currentYear}` }).locator('.dynamic_list');
// 当前月份的动态
const $currentForMonthDynamic = $$dynamic.filter({
has: page.locator('.month_box', { hasText: `${currentMonth}` }),
});
await test.step('查看月动态-缩略', async () => {
await page
.locator('div')
.filter({ hasText: /^日月$/ })
.getByRole('switch')
.click();
await expect(page.getByText('月', { exact: true })).toHaveClass('selected_btn');
await expect(async () => {
await $currentForMonthDynamic.click();
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
}).toPass();
await page.locator('.action_detail > .container > .m_sliding_menu > .box > .top > .anticon').click();
});
await test.step('查看月动态-日期', async () => {
await page
.locator('div')
.filter({ hasText: /^缩略日期$/ })
.getByRole('switch')
.click();
await expect(page.getByText('日期', { exact: true })).toHaveClass('selected_btn');
await $currentForMonthDynamic.filter({ hasText: `${currentDay}` }).click();
await expect(page.getByRole('tabpanel').getByText(billNo)).toBeVisible();
});
});
test('日志-添加-修改-删除', async ({ page, homeNavigation, customerPage, createCustomer }) => {
const customer = createCustomer;
let logContent = '测试添加日志成功';
let lastLogContent = '';
// 日志列表
const $$journal = page.locator('.journal_list');
// 日志填写框
const $input = page.getByPlaceholder('请输入1-500个字符护理内容');
await test.step('进入顾客详情页面', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
});
await test.step('添加日志', async () => {
await page.getByRole('tab', { name: '日志' }).click();
await page.getByRole('button', { name: '添加日志' }).click();
await $input.fill(logContent);
await page.getByRole('button', { name: /确\s认/ }).click();
// 在顾客A的顾客详情页面 -》日志查看刚才添加的日志
await expect($$journal.first()).toContainText(logContent);
});
lastLogContent = logContent;
logContent = '修改日志';
await test.step('修改日志', async () => {
await $$journal.first().locator('.title a').click();
await page.getByRole('menuitem', { name: '编辑' }).click();
await $input.waitFor();
const currentLogContent = await $input.inputValue();
expect(currentLogContent).toBe(lastLogContent);
await $input.fill(logContent);
await page.getByRole('button', { name: /确\s认/ }).click();
await expect($$journal.first()).toContainText(logContent);
});
await test.step('删除日志', async () => {
await expect($$journal.first()).toContainText(logContent);
await $$journal.first().locator('.title a').click();
await page.getByRole('menuitem', { name: '删除' }).click();
await page.getByRole('button', { name: /确\s认/ }).click();
await expect($$journal.first()).not.toBeVisible();
});
});
});
test.describe('顾客概要', () => {
test('顾客列表展示', async ({ page, homeNavigation }) => {
// 定义会员数据
let TotalCash2;
let TotalCash3;
let ConsumptionFrequency2;
let ConsumptionFrequency3;
let LastArrivalTime2;
let LastArrivalTime3;
let LastConsumptionTime2;
let LastConsumptionTime3;
let FirstConsumptionTime2;
let FirstConsumptionTime3;
let RegistrationTime2;
let RegistrationTime3;
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击会员列表下拉框
await page.locator('.sub_icon').first().click();
// 现金总额
await page.locator('.m-table-cell-sort').filter({ hasText: '现金总额' }).click();
// 点击最后一页
const endPage = await page.locator('.m-table-pagination li').count();
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
// 顾客数量
const memberquantity = await page.locator('.main-table-body_tr').count();
console.log('最后一页' + memberquantity);
await test.step('倒数三个对比正数三个的现金总额', async () => {
const $$cash = page.locator('.main-table-body_tr .is-right:nth-child(12)');
const TotalCash1 = await $$cash.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
TotalCash2 = await $$cash.nth(-1).innerText();
TotalCash3 = await $$cash.nth(-2).innerText();
}
if (memberquantity === 2) {
TotalCash2 = await $$cash.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
TotalCash3 = await $$cash.nth(-1).innerText();
}
if (memberquantity > 2) {
TotalCash2 = await $$cash.nth(-2).innerText();
TotalCash3 = await $$cash.nth(-3).innerText();
}
// 点击现金总额排序
await page.locator('.m-table-cell-sort').filter({ hasText: '现金总额' }).click();
await expect($$cash.nth(0)).toContainText(TotalCash1);
await expect($$cash.nth(1)).toContainText(TotalCash2);
await expect($$cash.nth(2)).toContainText(TotalCash3);
});
await test.step('倒数三个对比正数三个的消费次数', async () => {
await page.locator('.m-table-cell-sort').filter({ hasText: '消费次数' }).click();
const $consumptionFrequency = page.locator('.main-table-body_tr .is-right:nth-child(13)');
// 点击最后一页
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
const ConsumptionFrequency1 = await $consumptionFrequency.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
ConsumptionFrequency2 = await $consumptionFrequency.nth(-1).innerText();
ConsumptionFrequency3 = await $consumptionFrequency.nth(-2).innerText();
}
if (memberquantity === 2) {
ConsumptionFrequency2 = await $consumptionFrequency.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
ConsumptionFrequency3 = await $consumptionFrequency.nth(-1).innerText();
}
if (memberquantity > 2) {
ConsumptionFrequency2 = await page
.locator('.main-table-body_tr .is-right:nth-child(13)')
.nth(-2)
.innerText();
ConsumptionFrequency3 = await page
.locator('.main-table-body_tr .is-right:nth-child(13)')
.nth(-3)
.innerText();
}
await page.locator('.m-table-cell-sort').filter({ hasText: '消费次数' }).click();
await expect(page.locator('.main-table-body_tr .is-right:nth-child(13)').nth(0)).toBeVisible();
await expect($consumptionFrequency.nth(0)).toContainText(ConsumptionFrequency1);
await expect($consumptionFrequency.nth(1)).toContainText(ConsumptionFrequency2);
await expect($consumptionFrequency.nth(2)).toContainText(ConsumptionFrequency3);
});
await test.step('倒数三个对比正数三个的上次到店时间', async () => {
await page.locator('.m-table-cell-sort').filter({ hasText: '上次到店时间' }).click();
// 点击最后一页
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
const $$lastArrivalTime = page.locator('.main-table-body_tr .is-center:nth-child(15)');
const LastArrivalTime1 = await $$lastArrivalTime.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
LastArrivalTime2 = await $$lastArrivalTime.nth(-1).innerText();
LastArrivalTime3 = await $$lastArrivalTime.nth(-2).innerText();
}
if (memberquantity === 2) {
LastArrivalTime2 = await $$lastArrivalTime.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
LastArrivalTime3 = await $$lastArrivalTime.nth(-1).innerText();
}
if (memberquantity > 2) {
LastArrivalTime2 = await $$lastArrivalTime.nth(-2).innerText();
LastArrivalTime3 = await $$lastArrivalTime.nth(-3).innerText();
}
await page.locator('.m-table-cell-sort').filter({ hasText: '上次到店时间' }).click();
await expect($$lastArrivalTime.nth(0)).toContainText(LastArrivalTime1);
await expect($$lastArrivalTime.nth(1)).toContainText(LastArrivalTime2);
await expect($$lastArrivalTime.nth(2)).toContainText(LastArrivalTime3);
});
await test.step('倒数三个对比正数三个的上次消费时间', async () => {
await page.locator('.m-table-cell-sort').filter({ hasText: '上次消费时间' }).click();
// 点击最后一页
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
// 上次消费时间定位器
const $$lastConsumptionTime = page.locator('.main-table-body_tr .is-center:nth-child(16)');
const LastConsumptionTime1 = await $$lastConsumptionTime.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
LastConsumptionTime2 = await $$lastConsumptionTime.nth(-1).innerText();
LastConsumptionTime3 = await $$lastConsumptionTime.nth(-2).innerText();
}
if (memberquantity === 2) {
LastConsumptionTime2 = await $$lastConsumptionTime.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
LastConsumptionTime3 = await $$lastConsumptionTime.nth(-1).innerText();
}
if (memberquantity > 2) {
LastConsumptionTime2 = await $$lastConsumptionTime.nth(-2).innerText();
LastConsumptionTime3 = await $$lastConsumptionTime.nth(-3).innerText();
}
await page.locator('.m-table-cell-sort').filter({ hasText: '上次消费时间' }).click();
await expect($$lastConsumptionTime.nth(0)).toContainText(LastConsumptionTime1);
await expect($$lastConsumptionTime.nth(1)).toContainText(LastConsumptionTime2);
await expect($$lastConsumptionTime.nth(2)).toContainText(LastConsumptionTime3);
});
await test.step('倒数三个对比正数三个的首次消费时间', async () => {
await page.locator('.m-table-cell-sort').filter({ hasText: '首次消费时间' }).click();
// 点击最后一页
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
// 首次消费时间定位器
const $$firstConsumptionTime = page.locator('.main-table-body_tr .is-center:nth-child(17)');
const FirstConsumptionTime1 = await $$firstConsumptionTime.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
FirstConsumptionTime2 = await $$firstConsumptionTime.nth(-1).innerText();
FirstConsumptionTime3 = await $$firstConsumptionTime.nth(-2).innerText();
}
if (memberquantity === 2) {
FirstConsumptionTime2 = await $$firstConsumptionTime.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
FirstConsumptionTime3 = await $$firstConsumptionTime.nth(-1).innerText();
}
if (memberquantity > 2) {
FirstConsumptionTime2 = await $$firstConsumptionTime.nth(-2).innerText();
FirstConsumptionTime3 = await $$firstConsumptionTime.nth(-3).innerText();
}
await page.locator('.m-table-cell-sort').filter({ hasText: '首次消费时间' }).click();
await expect($$firstConsumptionTime.nth(0)).toContainText(FirstConsumptionTime1);
await expect($$firstConsumptionTime.nth(1)).toContainText(FirstConsumptionTime2);
await expect($$firstConsumptionTime.nth(2)).toContainText(FirstConsumptionTime3);
});
await test.step('倒数三个对比正数三个的注册时间', async () => {
// 注册时间
await page.locator('.m-table-cell-sort').filter({ hasText: '注册时间' }).click();
// 点击最后一页
await page
.locator('.m-table-pagination li')
.nth(endPage - 3)
.click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
// 注册时间定位器
const $$registrationTime = page.locator('.main-table-body_tr .is-center:nth-child(18)');
const RegistrationTime1 = await $$registrationTime.nth(-1).innerText();
if (memberquantity === 1) {
await page.locator('.ant-pagination-item-link').first().click();
RegistrationTime2 = await $$registrationTime.nth(-1).innerText();
RegistrationTime3 = await $$registrationTime.nth(-2).innerText();
}
if (memberquantity === 2) {
RegistrationTime2 = await $$registrationTime.nth(-2).innerText();
await page.locator('.ant-pagination-item-link').first().click();
RegistrationTime3 = await $$registrationTime.nth(-1).innerText();
}
if (memberquantity > 2) {
RegistrationTime2 = await $$registrationTime.nth(-2).innerText();
RegistrationTime3 = await $$registrationTime.nth(-3).innerText();
}
await page.locator('.m-table-cell-sort').filter({ hasText: '注册时间' }).click();
await expect($$registrationTime.nth(0)).toContainText(RegistrationTime1);
await expect($$registrationTime.nth(1)).toContainText(RegistrationTime2);
await expect($$registrationTime.nth(2)).toContainText(RegistrationTime3);
});
});
test('待办展示', async ({ page, homeNavigation, createCustomCustomer }) => {
const date = new Date();
const currentYear = date.getFullYear();
const currentMonth = date.getMonth() + 1;
const currentDay = date.getDate();
const customer = new Customer(1, 1, {
birthday: { year: currentYear, month: currentMonth, day: currentDay },
});
const todoLocator = page.locator('.member-side', { hasText: '待办事项' });
const todoListLocator = todoLocator.locator('.action_item');
const customerTodo = todoListLocator.filter({ has: page.getByText(customer.username) });
const showTodoLocator = page.locator('.shopSelect_box', { hasText: '事项状态' });
// 创建顾客,并且设置了顾客生日为今日
await createCustomCustomer(customer);
// 进入顾客模块
await homeNavigation.gotoModule('顾客');
// 待办列表存在
await expect(todoLocator).toBeVisible();
// 打开顾客的生日待办事项
await customerTodo.getByText('生日提醒', { exact: true }).click();
// 判断待办事项正确展示
await expect(showTodoLocator).toContainText('生日提醒');
await expect(showTodoLocator).toContainText(customer.username);
});
test.skip('表显示配置', async ({ page, homeNavigation }) => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 点击更多
await page.locator('.more', { hasText: '更多' }).waitFor();
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
// 关闭档案号、项目的显示开关
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^档案号$/ }) })
.locator('.ant-switch')
.click();
const SwitchA = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^档案号$/ }) })
.locator('.ant-switch-checked');
// 判断开关已关闭
await expect(SwitchA).not.toBeVisible();
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^项目$/ }) })
.locator('.ant-switch')
.click();
const SwitchB = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^项目$/ }) })
.locator('.ant-switch-checked');
// 判断开关已关闭
await expect(SwitchB).not.toBeVisible();
// 确认
await page.locator('.ant-btn-primary', { hasText: /^确\s认$/ }).click();
// 遍历标题 项目 档案号不存在
const allTrB = page.locator('.m-table__header-wrapper thead th');
const archivesB = allTrB.locator('.m-table-cell', { hasText: /^档案号$/ });
const ProjectB = allTrB.locator('.m-table-cell', { hasText: /^项目$/ });
await expect(archivesB).not.toBeVisible();
await expect(ProjectB).not.toBeVisible();
// 点击更多
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
// 关闭档案号、项目的显示开关
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^档案号$/ }) })
.locator('.ant-switch')
.click();
const SwitchC = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^档案号$/ }) })
.locator('.ant-switch-checked');
// 判断开关已打开
await expect(SwitchC).toBeVisible();
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^项目$/ }) })
.locator('.ant-switch')
.click();
const SwitchD = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^项目$/ }) })
.locator('.ant-switch-checked');
// 判断开关已打开
await expect(SwitchD).toBeVisible();
// 确认
await page.locator('.ant-btn-primary', { hasText: /^确\s认$/ }).click();
// 遍历标题 项目 档案号存在
const allTrA = page.locator('.m-table__header-wrapper thead th');
const archivesA = allTrA.locator('.m-table-cell', { hasText: /^档案号$/ });
const ProjectA = allTrA.locator('.m-table-cell', { hasText: /^项目$/ });
await expect(archivesA).toBeVisible();
await expect(ProjectA).toBeVisible();
// 点击更多
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
const sortArchives = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^档案号$/ }) })
.locator('.sort');
const sortItem = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^项目$/ }) })
.locator('.sort');
// 边界框
const boundaryArchives = await sortArchives.boundingBox();
const boundaryItem = await sortItem.boundingBox();
if (!boundaryArchives || !boundaryItem) {
throw new Error('获取边界框失败');
}
const ArchivesX = boundaryArchives.x + boundaryArchives.width / 2;
const ArchivesY = boundaryArchives.y + boundaryArchives.height / 2;
const ItemX = boundaryItem.x + boundaryItem.width / 2;
const ItemY = boundaryItem.y + boundaryItem.height / 2;
await expect(async () => {
// 拖动项目到档案号的位置
await page.mouse.move(ItemX, ItemY);
await page.mouse.down();
await page.waitForTimeout(2000);
await page.mouse.move(ArchivesX, ArchivesY);
await page.mouse.up();
expect(await page.locator('.sortList .list-session .name').first().innerText()).toBe('项目');
}).toPass();
await expect(async () => {
// 拖动项目到档案号的位置
await page.mouse.move(ItemX, ItemY);
await page.mouse.down();
await page.waitForTimeout(2000);
await page.mouse.move(ArchivesX, ArchivesY);
await page.mouse.up();
expect(await page.locator('.sortList .list-session .name').first().innerText()).toBe('档案号');
}).toPass();
});
test.skip('导出表格', async ({ page, homeNavigation }) => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 点击更多
await page.locator('.more', { hasText: '更多' }).waitFor();
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
const downloadPromise = page.waitForEvent('download');
// 点击导出数据
await page.locator('.a-modal-export', { hasText: '导出数据' }).click();
// 等待报表导出
await page.locator('.m-exportModal_title', { hasText: '报表导出' }).waitFor();
// 确认
await page.locator('.m-exportModal_button', { hasText: /^确\s认$/ }).click();
const download = await downloadPromise;
// 获取下载的文件名
const fileName = download.suggestedFilename();
// 指定保存下载文件的路径
const downloadPath = path.join(__dirname, `@/imgs/${fileName}`);
// 保存下载的文件
await download.saveAs(downloadPath);
// 验证文件是否成功保存
const fileExists = fs.existsSync(downloadPath);
expect(fileExists).toBeTruthy();
});
});
test.describe('顾客分配', () => {
test('顾客列表展示', async ({ page, homeNavigation, customerPage }) => {
await test.step('查看总人数和页脚总人数一致', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分配');
const headTotalLocator = page.locator('.info_item', { hasText: '总人数' });
await waitStable(headTotalLocator);
const paginationLocator = page.locator('.m-table-pagination .dec');
await paginationLocator.waitFor();
const paginationMatch = (await paginationLocator.innerText()).match(/共计([0-9]+)/);
const paginationTotal = paginationMatch ? paginationMatch[1] : '0';
const headTotal = await headTotalLocator.locator('.info_number').innerText();
expect.soft(headTotal).toBe(paginationTotal);
});
await test.step('按照现金总额排序查看列表', async () => {
const amountTotalLocator = page.locator('.m-table__header-wrapper th', {
hasText: '现金总额',
});
// 顺序和倒序的按钮
const amountTotalOrder = amountTotalLocator.locator('.m-table-sort i').last();
const amountTotalReverseOrder = amountTotalLocator.locator('.m-table-sort i').first();
const amountList = page.locator('.m-table__body-wrapper .main-table-body_tr');
// 查看从高到底的排序
await amountTotalOrder.click();
await expect(amountTotalOrder).toHaveClass(/on/);
await amountList.first().waitFor();
// 拿取现金总额列的index
const titleListLocator = page.locator('.m-table__header-wrapper tr').first().locator('th');
const titleList = await titleListLocator.allInnerTexts();
const index = titleList.findIndex(text => text === '现金总额');
// 拿取前三个顾客的现金总额
let amountArray = [];
for (let i = 0; i < 3; i++) {
const amountStr = await amountList.nth(i).locator('td').nth(index).innerText();
const amount = convertAmountText(amountStr).amount;
amountArray.push(amount);
}
// 金额按照从高到低排列
expect(amountArray[0]).toBeGreaterThanOrEqual(amountArray[1]);
expect(amountArray[1]).toBeGreaterThanOrEqual(amountArray[2]);
// 查看从低到高的排序
await amountTotalReverseOrder.click();
await expect(amountTotalOrder).toHaveClass(/on/);
await amountList.first().waitFor();
amountArray = [];
let amountStr = await amountList.nth(0).locator('td').nth(index).innerText();
amountArray.push(convertAmountText(amountStr).amount);
// 跳转到倒数第一页,拿取最后三个顾客的现金总额
const paginationLiLocator = page.locator('.m-table-pagination ul li');
const paginationLiCount = await paginationLiLocator.count();
await paginationLiLocator.nth(paginationLiCount - 3).click();
amountStr = await amountList.nth(0).locator('td').nth(index).innerText();
amountArray.push(convertAmountText(amountStr).amount);
// 金额按照从高到低排列
expect(amountArray[0]).toBeLessThanOrEqual(amountArray[1]);
});
});
test.skip('表显示配置', async ({ page, homeNavigation }) => {
await page.reload(); // 跟分配师一样不重进不加载某些内容
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击顾客分配
await page.locator('.tab_item', { hasText: '顾客分配' }).first().click();
await page.locator('.assign_info').waitFor();
// 点击更多
await page.locator('.more', { hasText: '更多' }).waitFor();
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
// 关闭档案号、项目的显示开关
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^咨询师$/ }) })
.locator('.ant-switch')
.click();
const SwitchA = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^咨询师$/ }) })
.locator('.ant-switch-checked');
// 判断开关已关闭
await expect(SwitchA).not.toBeVisible();
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^医生$/ }) })
.locator('.ant-switch')
.click();
const SwitchB = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^医生$/ }) })
.locator('.ant-switch-checked');
// 判断开关已关闭
await expect(SwitchB).not.toBeVisible();
// 确认
await page.locator('.ant-btn-primary', { hasText: /^确\s认$/ }).click();
// 遍历标题 项目 档案号不存在
const allTrB = page.locator('.m-table__header-wrapper thead th');
const archivesB = allTrB.locator('.m-table-cell', { hasText: /^咨询师$/ });
const ProjectB = allTrB.locator('.m-table-cell', { hasText: /^医生$/ });
await expect(archivesB).not.toBeVisible();
await expect(ProjectB).not.toBeVisible();
// 点击更多
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
// 关闭档案号、项目的显示开关
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^咨询师$/ }) })
.locator('.ant-switch')
.click();
const SwitchC = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^咨询师$/ }) })
.locator('.ant-switch-checked');
// 判断开关已打开
await expect(SwitchC).toBeVisible();
await page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^医生$/ }) })
.locator('.ant-switch')
.click();
const SwitchD = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^医生$/ }) })
.locator('.ant-switch-checked');
// 判断开关已打开
await expect(SwitchD).toBeVisible();
// 确认
await page.locator('.ant-btn-primary', { hasText: /^确\s认$/ }).click();
// 遍历标题 项目 档案号存在
const allTrA = page.locator('.m-table__header-wrapper thead th');
const archivesA = allTrA.locator('.m-table-cell', { hasText: /^咨询师$/ });
const ProjectA = allTrA.locator('.m-table-cell', { hasText: /^医生$/ });
await expect(archivesA).toBeVisible();
await expect(ProjectA).toBeVisible();
// 点击更多
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
const sortArchives = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^咨询师$/ }) })
.locator('.sort');
const sortItem = page
.locator('.sortList .list-session')
.filter({ has: page.locator('.name', { hasText: /^医生$/ }) })
.locator('.sort');
// 边界框
const boundaryArchives = await sortArchives.boundingBox();
const boundaryItem = await sortItem.boundingBox();
if (!boundaryArchives || !boundaryItem) {
throw new Error('获取边界框失败');
}
const ArchivesX = boundaryArchives.x + boundaryArchives.width / 2;
const ArchivesY = boundaryArchives.y + boundaryArchives.height / 2;
const ItemX = boundaryItem.x + boundaryItem.width / 2;
const ItemY = boundaryItem.y + boundaryItem.height / 2;
await expect(async () => {
// 拖动项目到档案号的位置
await page.mouse.move(ItemX, ItemY);
await page.mouse.down();
await page.waitForTimeout(2000);
await page.mouse.move(ArchivesX, ArchivesY);
await page.mouse.up();
expect(await page.locator('.sortList .list-session .name').first().innerText()).toBe('医生');
}).toPass();
await expect(async () => {
// 拖动项目到档案号的位置
await page.mouse.move(ItemX, ItemY);
await page.mouse.down();
await page.waitForTimeout(2000);
await page.mouse.move(ArchivesX, ArchivesY);
await page.mouse.up();
expect(await page.locator('.sortList .list-session .name').first().innerText()).toBe('咨询师');
}).toPass();
});
test.skip('导出表格', async ({ page, homeNavigation }) => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击顾客分配
await page.locator('.tab_item', { hasText: '顾客分配' }).click();
await page.locator('.assign_side').waitFor();
// 点击更多
await page.locator('.more', { hasText: '更多' }).waitFor();
await page.locator('.more', { hasText: '更多' }).click();
// 等待表显示配置
await page.locator('.title', { hasText: '表显示配置' }).waitFor();
const downloadPromise = page.waitForEvent('download');
// 点击导出数据
await page.locator('.a-modal-export', { hasText: '导出数据' }).click();
// 等待报表导出
await page.locator('.m-exportModal_title', { hasText: '报表导出' }).waitFor();
// 确认
await page.locator('.m-exportModal_button', { hasText: /^确\s认$/ }).click();
const download = await downloadPromise;
// 获取下载的文件名
const fileName = download.suggestedFilename();
// 指定保存下载文件的路径
const downloadPath = path.join(__dirname, `@/imgs/${fileName}`);
// 保存下载的文件
await download.saveAs(downloadPath);
// 验证文件是否成功保存
const fileExists = fs.existsSync(downloadPath);
expect(fileExists).toBeTruthy();
});
});
test.describe('顾客分析', () => {
test('查看顾客项目分析', async ({ page, homeNavigation, createCustomers, customerPage, numberInput }) => {
/**@type {Customer[]} */
let customers = [];
await test.step('创建两个顾客', async () => {
// 创建顾客
customers = await createCustomers(2);
});
const ca = customers[0];
const cb = customers[1];
console.log(`顾客A: ${ca.username}${ca.phone}`);
console.log(`顾客B: ${cb.username}${cb.phone}`);
// 获取姓名、手机号、档案号
const usernameA = ca.username;
const phoneA = ca.phone;
const usernameB = cb.username;
const phoneB = cb.phone;
const ProjectA1 = ProjectName.Projects.Projects_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
await test.step('顾客A', async () => {
await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /开\s单/ }).click();
await customerPage.searchCustomer(phoneA);
await customerPage.selectSearchCustomer(usernameA);
// 购买项目1-普通2次
await page.getByText(ProjectA1.num).click();
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectA1Quantity);
await numberInput.confirmValue();
// 点击面部
await page.getByText('面部').click();
// 购买项目2-普通1次
await page.getByText(ProjectA2.num).click();
await page.locator('.type_btn').first().click();
await page.locator('.type_item', { hasText: '普通' }).click();
// 点击护理
await page.getByText('护理', { exact: true }).click();
// 购买项目3-赠送3次
await page.getByText(ProjectA3.num).click();
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectA3Quantity);
await numberInput.confirmValue();
await page.locator('.type_btn').first().click();
await page.locator('.type_item', { hasText: '赠送' }).click();
// 选择组合项目2-项目1普通
await page.getByText(ProjectA1.num).first().click();
await page.locator('.add_btn', { hasText: '设置' }).last().click();
await page.getByRole('textbox').fill(ProjectA2.num);
await page.getByRole('button', { name: /搜\s索/ }).click();
await expect(async () => {
await page.getByLabel(ProjectA2.name).uncheck();
await page.getByLabel(ProjectA2.name).check();
await page.locator('.menu-item-dot', { hasText: '2' }).first().waitFor({ timeout: 2000 });
}).toPass();
await page.getByRole('button', { name: '确定选择' }).click();
await page.locator('.type_btn').first().click();
await page.locator('.type_item', { hasText: '普通' }).click();
// 消耗混合项目1次
await page.locator('.commodity_item').last().click();
await page
.locator('div')
.filter({ hasText: /^结 算$/ })
.click();
// 使用银联支付
await page.getByText('银联').click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.getByRole('button', { name: /^结\s算$/ }).click();
});
const ProjectB3 = ProjectName.Projects.Projects_2;
const ProjectB3Quantity = 20;
const ProjectB4 = ProjectName.Projects.Projects_661;
const ProjectB4Quantity = 30;
const ProjectB5 = ProjectName.Projects.Projects_676;
const ProjectB5Quantity = 9;
const ProjectB1 = ProjectName.Projects.Projects_1;
const ProjectB2 = ProjectName.Projects.Projects_239;
const ProjectB12Quantity = 2;
const ProjectB34Quantity = 3;
await test.step('顾客B', async () => {
//顾客B
await page.reload();
await page.getByRole('button', { name: /开\s单/ }).click();
await customerPage.searchCustomer(phoneB);
await customerPage.selectSearchCustomer(usernameB);
// 购买项目3-普通20次
await page.getByText(ProjectB3.num).click();
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectB3Quantity);
await numberInput.confirmValue();
// 点击身体
await page.locator('.type_tab_item', { hasText: '身体' }).click();
// 购买项目4-普通30次
await page.getByText(ProjectB4.num).click();
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectB4Quantity);
await numberInput.confirmValue();
// 购买项目59次
await page.getByText(ProjectB5.num).click();
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectB5Quantity);
await numberInput.confirmValue();
// 购买项目B1-B2混合2次
await page.locator('.type_tab_item', { hasText: '护理' }).click();
await page.getByText(ProjectB1.num).first().click();
await page.locator('.add_btn', { hasText: '设置' }).last().click();
await page.getByRole('textbox').fill(ProjectB2.num);
await page.getByRole('button', { name: /搜\s索/ }).click();
await expect(async () => {
await page.locator('.list_box .ant-checkbox-input').click();
await page.locator('.menu-item-dot', { hasText: '2' }).first().waitFor({ timeout: 1000 });
}).toPass();
await page.getByRole('button', { name: '确定选择' }).click();
// 点击选择数量
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectB12Quantity);
await numberInput.confirmValue();
// 购买项目B4-B4混合3次
await page.getByText(ProjectB3.num).first().click();
await page.locator('.add_btn', { hasText: '设置' }).last().click();
await page.getByRole('textbox').fill(ProjectB4.num);
await page.getByRole('button', { name: '搜 索' }).click();
await expect(async () => {
await page.locator('.list_box .ant-checkbox-input').click();
await page.locator('.menu-item-dot', { hasText: '2' }).first().waitFor({ timeout: 1000 });
}).toPass();
await page.getByRole('button', { name: '确定选择' }).click();
// 点击选择数量
await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(ProjectB34Quantity);
await numberInput.confirmValue();
await page.locator('.commodity_item').last().click();
await page
.locator('div')
.filter({ hasText: /^结 算$/ })
.click();
await page.getByText('银联').click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.getByRole('button', { name: /^结\s算$/ }).click();
});
await test.step('查看顾客项目分析', async () => {
await page.reload();
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分析');
await page
.locator('div')
.filter({ hasText: /^排序$/ })
.nth(1)
.click();
await page.getByRole('menuitem', { name: '上次到店时间从近到远' }).click();
await page.locator('.loading_container').waitFor({ state: 'hidden' });
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
await expect(Customer1A).toBeVisible();
await expect(Customer1B).toBeVisible();
// 表格行
const allTr = page.locator('.m-table__body-wrapper tbody tr');
// 获取顾客B处于第几行
const nowRow = await page
.locator('.m-table__body-wrapper tbody tr')
.allInnerTexts()
.then(async text => {
return text.findIndex(item => item.includes(phoneB));
});
// 查看各单元格内容
// 护理内容
await expect.soft(allTr.nth(nowRow).locator('td').nth(2)).toContainText(`${ProjectB3Quantity - 1}`);
// 身体内容
await expect
.soft(allTr.nth(nowRow).locator('td').nth(5))
.toContainText(`${ProjectB12Quantity + ProjectB34Quantity}`);
// 组合内容
await expect(allTr.nth(nowRow).locator('td').nth(5)).toContainText(
`${ProjectB12Quantity + ProjectB34Quantity}`,
);
const $productName = page.locator('.treat_box .treat_card:nth-child(1) .name_row .auto_desc');
const $productResidue = page.locator('.treat_box .treat_card:nth-child(1) .name_row .residue');
const $productName2 = page.locator('.treat_box .treat_card:nth-child(2) .name_row .auto_desc');
const $productResidue2 = page.locator('.treat_box .treat_card:nth-child(2) .name_row .residue');
// 点击查看弹窗内容
// 点击护理
await allTr.nth(nowRow).locator('td').nth(2).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectB3.name);
// 剩余次数
await expect($productResidue).toContainText(`${ProjectB3Quantity - 1}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击身体
await allTr.nth(nowRow).locator('td').nth(4).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectB4.name);
// 剩余次数
await expect.soft($productResidue).toContainText(`${ProjectB4Quantity}`);
// 项目名称
await expect.soft($productName2).toContainText(ProjectB5.name);
// 剩余次数
await expect.soft($productResidue2).toContainText(`${ProjectB5Quantity}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击组合
await allTr.nth(nowRow).locator('td').nth(5).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectB1.name + '' + ProjectB2.name);
// 剩余次数
await expect.soft($productResidue).toContainText(`${ProjectB12Quantity}`);
// 项目名称
await expect.soft($productName2).toContainText(ProjectB3.name + '' + ProjectB4.name);
// 剩余次数
await expect($productResidue2).toContainText(`${ProjectB34Quantity}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 查看顾客A的各单元格内容
const allTrA = page.locator('.m-table__body-wrapper tbody tr');
const nowRowA = await allTrA.allInnerTexts().then(async text => {
return text.findIndex(item => item.includes(phoneA));
});
// 点击护理
await allTrA.nth(nowRowA).locator('td').nth(2).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectA1.name);
// 剩余次数
await expect($productResidue).toContainText(`${ProjectA1Quantity - 1}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击面部
await allTrA.nth(nowRowA).locator('td').nth(3).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectA2.name);
// 剩余次数
await expect($productResidue).toContainText(`${ProjectA2Quantity}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击组合
await allTrA.nth(nowRowA).locator('td').nth(5).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectA1.name + '' + ProjectA2.name);
// 剩余次数
await expect($productResidue).toContainText(`${ProjectA12Quantity}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击左上角设置
await page.locator('.setting_icon').click();
// 选择购买数
await page.getByText('购买数', { exact: true }).click();
// 选择显示体验/赠送项目
await page.getByText('显示体验/赠送项目').click();
// 保存
await page.getByRole('button', { name: /保\s存/ }).click();
await page.locator('.loading_container').waitFor({ state: 'hidden' });
// 护理内容
const allTrAA = page.locator('.m-table__body-wrapper tbody tr');
const nowRowAA = await allTrAA.allInnerTexts().then(async text => {
return text.findIndex(item => item.includes(phoneA));
});
// 点击护理
await allTrAA.nth(nowRowAA).locator('td').nth(2).click();
// 项目名称
await expect.soft($productName).toContainText(ProjectA1.name);
// 剩余次数
await expect.soft($productResidue).toContainText(`${ProjectA1Quantity - 1}`);
// 项目名称
await expect.soft($productName2).toContainText(ProjectA3.name);
// 剩余次数
await expect($productResidue2).toContainText(`${ProjectA3Quantity}`);
// 关闭弹窗
await page.locator('.close_icon').last().click();
// 点击排序后顾客在第一页显示
await page
.locator('div')
.filter({ hasText: /^排序$/ })
.nth(1)
.click();
await page.getByRole('menuitem', { name: '上次到店时间从近到远' }).click();
await page.locator('.loading_container').waitFor({ state: 'hidden' }); // 1 查找到顾客A 顾客B
await expect.soft(Customer1A).toBeVisible();
await expect(Customer1B).toBeVisible();
});
});
test('查看项目余量分析', async ({
page,
homeNavigation,
customerPage,
createCustomer,
customerAnalysisPage,
numberInput,
}) => {
const customer = createCustomer;
let billNo = '';
// 分类-项目选择器
const $$switch = page.locator('.coustom_switch');
const $categoryAndProject = $$switch
.filter({ hasText: '分类' })
.filter({ hasText: '项目' })
.getByRole('switch');
// 客数-余次选择器
const $passengersAndRemainder = $$switch
.filter({ hasText: '客数' })
.filter({ hasText: '余次' })
.getByRole('switch');
await test.step('进入顾客分析-》项目余量分析', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分析');
await customerAnalysisPage.gotoSubPage('项目余量分析');
});
let project = { name: '', className: '' };
await test.step('获取项目中客数最高的项目', async () => {
await page.getByRole('cell', { name: '普通' }).locator('svg').nth(1).click();
await page.getByRole('cell', { name: '类别' }).waitFor();
const $firstProjectTr = page.locator('.main-table-body_tr').first();
await $firstProjectTr.waitFor();
const $firstProjectTd = $firstProjectTr.locator('td');
// 获取项目名称和项目类型名称
project.name = (await $firstProjectTd.first().innerText()).trim();
project.className = (await $firstProjectTd.nth(1).innerText()).trim();
});
expect(project.name).not.toBe('');
expect(project.className).not.toBe('');
await test.step('进入顾客详情', async () => {
await customerPage.gotoSubPage('顾客概要');
await customerPage.searchCustomer(customer.phone);
await customerPage.selectSearchCustomer(customer.username);
await customerPage.openCustomerDetail(customer.username, customer.phone);
});
await test.step('开单购买普通、赠送、体验各三次,并且各消耗一次', async () => {
// 项目列表
const $$project = page.locator('.project_list');
await page.locator('span').filter({ hasText: '去开单' }).first().click();
await page.getByRole('main').getByText(project.className, { exact: true }).click();
// 普通三次
await $$project.getByText(project.name, { exact: true }).click();
await page.locator('#buyList').getByText('1', { exact: true }).click();
await numberInput.setValue(3);
await numberInput.confirmValue();
// 体验三次
await $$project.getByText(project.name, { exact: true }).click();
await page.locator('#buyList').getByText('1', { exact: true }).click();
await numberInput.setValue(3);
await numberInput.confirmValue();
await page.getByRole('button', { name: '普' }).click();
await page.getByText('体验', { exact: true }).click();
// 赠送三次
await $$project.getByText(project.name, { exact: true }).click();
await page.locator('#buyList').getByText('1', { exact: true }).click();
await numberInput.setValue(3);
await numberInput.confirmValue();
await page.getByRole('button', { name: '普' }).click();
await page.getByText('赠送', { exact: true }).click();
// 普通、体验、赠送各消耗三次
await page.locator('#shoppingCart').getByText('雪肌晶纯护理').first().click();
await page.locator('#shoppingCart').getByText('雪肌晶纯护理').nth(1).click();
await page.locator('#shoppingCart').getByText('雪肌晶纯护理').nth(2).click();
// 结算
await page
.locator('div')
.filter({ hasText: /^结\s算$/ })
.click();
await page.locator('.paymentInfoItem', { hasText: '现金' }).click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
// 结算
const [response] = await Promise.all([
page.waitForResponse(async res => {
return res.url().includes('/bill') && (await res.json()).code === 'SUCCESS';
}),
page.getByRole('button', { name: /^结\s算$/ }).click(),
]);
const responseBody = await response.json();
billNo = responseBody?.content?.billNo;
expect(billNo).not.toBeNull();
console.log('Bill No:' + billNo);
await expect(page.getByRole('button', { name: /开\s单/ })).toBeInViewport();
});
await test.step('进入顾客分析-》项目余量分析', async () => {
await homeNavigation.gotoModule('顾客');
await customerPage.gotoSubPage('顾客分析');
await customerAnalysisPage.gotoSubPage('项目余量分析');
});
await test.step('查看类别', async () => {
await page.getByText('选择项目类别').click();
await page.getByRole('option', { name: project.className }).click();
await Promise.all([
waitSpecifyApiLoad(page, ['/property_analysis']),
page.getByRole('cell', { name: '普通' }).locator('svg').nth(1).click(),
]);
// 判断项目存在
await expect(page.getByRole('cell', { name: project.name, exact: true })).toBeVisible();
});
// 项目所在行
const $projectTr = page
.locator('.main-table-body_tr')
.filter({ has: page.getByText(project.name) })
.filter({ has: page.getByText(project.className) });
// 弹窗内容
const $popup = page.locator('.popup_content');
// 弹窗内顾客的信息
const $customerTr = $popup
.locator('.main-table-body_tr')
.filter({ has: page.getByText(customer.username) })
.filter({ has: page.getByText(customer.phone) });
//普通
const $normalProjectTd = $projectTr.getByRole('cell').nth(2);
//体验
const $experienceProjectTd = $projectTr.getByRole('cell').nth(3);
//赠送
const $giveAwayProjectTd = $projectTr.getByRole('cell').nth(4);
await test.step('查看数据', async () => {
// 普通
await $normalProjectTd.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
// 体验
await $experienceProjectTd.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
// 赠送
await $giveAwayProjectTd.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
});
// 顾客项目分析数据
const analysisData = {
normal: -1,
experience: -1,
giveAway: -1,
};
// 项目剩余次数
const $currentItemRemaining = page
.locator('.proerty_summery .item')
.filter({ has: page.getByText('项目余次') })
.locator('.item_num');
await test.step('显示已用完的项目、余次,查看数据', async () => {
// 配置为显示已用完的项目和项目余次
await $passengersAndRemainder.click();
await page.locator('.setting_icon').click();
await page.getByLabel('显示已用完的项目').check();
await Promise.all([
waitSpecifyApiLoad(page, ['/property_analysis']),
page.getByRole('button', { name: /保\s存/ }).click(),
]);
// 获取项目余次数据
analysisData.normal = Number((await $normalProjectTd.innerText()).trim());
analysisData.experience = Number((await $experienceProjectTd.innerText()).trim());
analysisData.giveAway = Number((await $giveAwayProjectTd.innerText()).trim());
// 普通
await $normalProjectTd.click();
await expect($customerTr).toBeVisible();
const currentNormalData = Number((await $currentItemRemaining.innerText()).trim());
expect(currentNormalData).toBeGreaterThanOrEqual(analysisData.normal);
await page.locator('.title > .close_icon > svg').click();
// 体验
await $experienceProjectTd.click();
await expect($customerTr).toBeVisible();
const currentExperienceData = Number((await $currentItemRemaining.innerText()).trim());
expect(currentExperienceData).toBeGreaterThanOrEqual(analysisData.experience);
await page.locator('.title > .close_icon > svg').click();
// 赠送
await $giveAwayProjectTd.click();
await expect($customerTr).toBeVisible();
const currentGiveAwayData = Number((await $currentItemRemaining.innerText()).trim());
expect(currentGiveAwayData).toBeGreaterThanOrEqual(analysisData.giveAway);
await page.locator('.title > .close_icon > svg').click();
});
// 项目剩余次数行
const $categoryTr = page.locator('.main-table-body_tr').filter({ has: page.getByText(project.className) });
//普通
const $normalProjectTdForCategory = $categoryTr.getByRole('cell').nth(1);
//体验
const $experienceProjectTdForCategory = $categoryTr.getByRole('cell').nth(2);
//赠送
const $giveAwayProjectTdForCategory = $categoryTr.getByRole('cell').nth(3);
await test.step('分类、客数,查看数据', async () => {
// 切换为分类和客数
await $categoryAndProject.click();
await $passengersAndRemainder.click();
// 普通
await $normalProjectTdForCategory.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
// 体验
await $experienceProjectTdForCategory.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
// 赠送
await $giveAwayProjectTdForCategory.click();
await expect($customerTr).toBeVisible();
await page.locator('.title > .close_icon > svg').click();
});
});
test('查看套餐消耗升单分析', async ({ page, homeNavigation, createCustomer, customerPage, numberInput }) => {
const c = createCustomer;
// 点击顾客 拿取初始数据
await homeNavigation.gotoModule('顾客');
await page.locator('.tab_item', { hasText: '顾客分析' }).click();
await page.getByText('顾客项目分析').click();
await page.getByRole('menuitem', { name: '套餐消耗升单分析' }).click();
// 选择套餐
await page.locator('.selectpage').click();
await page.getByLabel('A套餐GK035').check();
await page.getByRole('button', { name: '确定选择' }).click();
await page.locator('span').filter({ hasText: '选择员工' }).click();
await page.getByLabel('陈刚').check();
await page.getByRole('button', { name: '确定选择' }).click();
await page.getByRole('button', { name: '查询' }).click();
// 点击查看购买消耗升单
await page.locator('.table_top_center').click();
// 初始购买
const Initialbuy = await page.locator('.propomTop .propomSize').nth(0).innerText(); //购买
// 初始消耗
const Initialexpend = await page.locator('.propomTop .propomSize').nth(1).innerText(); //消耗
// 初始升单
const Initialupbills = await page.locator('.propomTop .propomSize').nth(2).innerText(); //升单
// 关闭窗口
await page
.locator('div')
.filter({ hasText: /^A套餐GK035合计$/ })
.locator('i')
.click();
await page.reload();
await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /^开\s单$/ }).click();
await customerPage.searchCustomer(c.phone);
await customerPage.selectSearchCustomer(c.username);
// 选择套餐
await page.locator('.float_tab').getByText('套餐').click();
// 选择A套餐
await page.locator('.project_one > .item').filter({ hasText: ProjectName.SetMeal.SetMeal_6.name }).click();
// 点击添加员工
await page.locator('#buyList').getByRole('button').nth(1).click();
// 选择员工1
const employee1 = Employees.FirstShop.Employee_6.name;
await page.locator('.hand_txt .name_txt').getByText(employee1).click();
// 保存并复制到其他项目
await page.locator('button.save_and_copy').filter({ hasText: '保存并复制到其他项目/卖品' }).click();
// 结算
await page
.locator('div')
.filter({ hasText: /^结\s算$/ })
.click();
// 点击现金
await page.getByText('现金').click();
await page.getByLabel('推送消费提醒').uncheck();
await page.getByLabel('结算签字').uncheck();
await page.getByRole('button', { name: /^结\s算$/ }).click();
await page.getByRole('button', { name: /跳\s过/ }).click();
await expect.soft(page.locator('.ant-message', { hasText: '结算成功' })).toBeVisible();
await page.getByRole('button', { name: /^开\s单$/ }).click();
await customerPage.searchCustomer(c.phone);
await customerPage.selectSearchCustomer(c.username);
// 消耗该项目5次
await page.locator('.treat_card_content').first().click();
// 点击选择数量
await page.locator('.buy_number').click();
// 点击删除所有数量
await page.locator('div').filter({ hasText: /^123$/ }).getByRole('button').nth(3).click();
// 选择数量5
await numberInput.setValue(5);
await numberInput.confirmValue();
// 点击添加员工
await page.locator('.staff_btn').click();
// 选择员工1
await page.locator('.hand_txt .name_txt').getByText(employee1).click();
// 保存并复制到其他项目
await page.locator('button.save_and_copy').filter({ hasText: '保存并复制到其他项目' }).click();
// 购买项目C
await page.getByText(ProjectName.Projects.Projects_21.num).click();
// 点击选择数量
await page.locator('.edit_txt div:nth-child(2)').first().click();
// 点击删除所有数量
await page.locator('div').filter({ hasText: /^123$/ }).getByRole('button').nth(3).click();
// 选择数量2
await numberInput.setValue(2);
await numberInput.confirmValue();
await page
.locator('div')
.filter({ hasText: /^结\s算$/ })
.click();
// 点击现金
await page.getByText('现金').click();
// 取消推送消息提醒
await page.getByLabel('推送消费提醒').uncheck();
// 取消结算签字
await page.getByLabel('结算签字').uncheck();
// 点击结算
await page.getByRole('button', { name: /^结\s算$/ }).click();
await expect.soft(page.locator('.ant-message', { hasText: '结算成功' })).toBeVisible();
await homeNavigation.gotoModule('顾客');
await page.locator('.tab_item', { hasText: '顾客分析' }).click();
await page.getByText('顾客项目分析').click();
await page.getByRole('menuitem', { name: '套餐消耗升单分析' }).click();
// 选择套餐
await page.locator('.selectpage').click();
await page.getByLabel('A套餐GK035').check();
await page.getByRole('button', { name: '确定选择' }).click();
await page.locator('.search_middle .select_multiple').click();
await page.getByLabel('陈刚').check();
await page.getByRole('button', { name: '确定选择' }).click();
await page.getByRole('button', { name: '查询' }).click();
// 点击查看购买消耗升单
await page.locator('.table_top_center').click();
await expect.soft(page.locator('.propomTop .propomSize').nth(0)).toContainText(`${Number(Initialbuy) + 1}`);
await expect.soft(page.locator('.propomTop .propomSize').nth(1)).toContainText(`${Number(Initialexpend) + 1}`);
await expect(page.locator('.propomTop .propomSize').nth(2)).toContainText(`${Number(Initialupbills) + 1}`);
// 关闭窗口
await page
.locator('div')
.filter({ hasText: /^A套餐GK035合计$/ })
.locator('i')
.click();
// 顾客行数
const allTr = page.locator('.m-table__body-wrapper tbody tr');
await allTr.first().waitFor();
let nowRow = await allTr.allInnerTexts().then(async text => {
return text.findIndex(item => item.includes(c.phone));
});
const ProjectA = ProjectName.Projects.Projects_19.name;
const ProjectB = ProjectName.Projects.Projects_20.name;
const ProjectC = ProjectName.Projects.Projects_21.name;
// 员工(陈刚)
await expect(
page.locator('.m-table__body-wrapper tbody tr').nth(nowRow).locator('td:nth-child(4)'),
).toContainText(employee1);
// 套餐消耗(水娃娃x5)
await expect(
page.locator('.m-table__body-wrapper tbody tr').nth(nowRow).locator('td:nth-child(5) .projectName'),
).toContainText(ProjectA + 'x5');
// 升单(德国原装冰吻之恋x2)
await expect(
page.locator('.m-table__body-wrapper tbody tr').nth(nowRow).locator('td:nth-child(6) .projectName'),
).toContainText(ProjectC + 'x2');
// 套餐结余(水娃娃x5 德国原装水元素x5)
await expect(
page.locator('.m-table__body-wrapper tbody tr').nth(nowRow).locator('td:nth-child(7)'),
).toContainText(ProjectA + 'x5');
await expect(
page.locator('.m-table__body-wrapper tbody tr').nth(nowRow).locator('td:nth-child(7)'),
).toContainText(ProjectB + 'x5');
});
});
test.describe('批量操作', () => {
let usePhones = Array(8).fill(null); // 创建一个长度为8的数组初始值为null表示未设置
test.beforeEach(async ({ page }) => {
// 监听响应事件
await page.addLocatorHandler(
page.locator('.popup_content .ant-btn-primary', { hasText: '我知道了' }),
async () => {
await page.locator('.popup_content .ant-btn-primary').click();
await expect(page.locator('.popup_content .ant-btn-primary')).not.toBeVisible();
},
);
});
test('顾客分配', async ({ page, homeNavigation }) => {
await page.reload();
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 打开顾客列表
// await page.getByRole("menuitem", { name: "打开顾客列表" }).click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第二页
await page.locator('.ant-pagination-item-2').click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 顾客分配
await page.getByRole('menuitem', { name: '顾客分配' }).click();
await expect(async () => {
try {
await page.locator('.label_text', { hasText: '移除已分配咨询师' }).waitFor({ timeout: 2000 });
await page.locator('.label_text', { hasText: '移除已分配咨询师' }).click();
} catch {
// 关闭窗口
await page.locator('.ant-modal-close-x').click();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 顾客分配
await page.getByRole('menuitem', { name: '顾客分配' }).click();
await page.locator('.label_text', { hasText: '移除已分配咨询师' }).waitFor({ timeout: 2000 });
await page.locator('.label_text', { hasText: '移除已分配咨询师' }).click();
}
}).toPass();
// // 点击已经已分配
// await page.locator(".label_text", { hasText: "移除已分配咨询师" }).click();
// 确认分配
await page.getByRole('button', { name: '确认分配' }).click();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
// 确保清完已分配重新进入进行分配
await page.reload();
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 打开顾客列表
// await page.getByRole("menuitem", { name: "打开顾客列表" }).click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第二页
await page.locator('.ant-pagination-item-2').click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 顾客分配
await page.getByRole('menuitem', { name: '顾客分配' }).click();
// 选择员工A
let nowRowA = 0;
const employee1 = Employees.FirstShop.Employee_3.name;
const allTrA = page.locator('.ant-tree-child-tree-open').first().locator('.ant-tree-treenode-switcher-open');
const countA = await allTrA.count();
// 获取第几个
for (let i = 0; i < countA; i++) {
const trA = allTrA.nth(i);
const employee = await trA.locator('.ant-tree-title').innerText();
console.log(employee);
if (employee.includes(employee1)) {
nowRowA = i;
break;
}
}
await page
.locator('.ant-tree-child-tree-open')
.first()
.locator('.ant-tree-treenode-switcher-open')
.nth(nowRowA)
.click();
// 选择员工B
let nowRowB = 0;
const employee2 = Employees.FirstShop.Employee_4.name;
const allTrB = page.locator('.ant-tree-child-tree-open').first().locator('.ant-tree-treenode-switcher-open');
const countB = await allTrB.count();
// 获取第几个
for (let i = 0; i < countB; i++) {
const trB = allTrB.nth(i);
const employeeB = await trB.locator('.ant-tree-title').innerText();
console.log(employeeB);
if (employeeB.includes(employee2)) {
nowRowB = i;
break;
}
}
await page
.locator('.ant-tree-child-tree-open')
.first()
.locator('.ant-tree-treenode-switcher-open')
.nth(nowRowB)
.click();
// 确认分配
await page.getByRole('button', { name: '确认分配' }).click();
// 操作成功
await expect(page.locator('.ant-message-notice', { hasText: '操作成功' })).toBeVisible();
await page.reload();
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 打开顾客列表
// await page.getByRole("menuitem", { name: "打开顾客列表" }).click();
// 点击第一个会员
await page.locator('.m-table__fixed-left .user_info').first().click();
// 等待基本资料加载完成
await page.locator('.basic_box .base_info').first().waitFor();
// 判断这两员工是否分配到了
const employeeResult = await page.locator('.description .employees_txt').innerText();
expect(employeeResult).toBe(employee1 + '、' + employee2);
// 关闭详情回到顾客列表
await page.locator('.close_icons').click();
// 点击第二页
await page.locator('.ant-pagination-item-2').click();
// 点击第一个会员
await page.locator('.m-table__fixed-left .user_info').first().click();
// 等待基本资料加载完成
await page.locator('.basic_box .base_info').first().waitFor();
// 判断这两员工是否分配到了
expect(employeeResult).toBe(employee1 + '、' + employee2);
await page.reload();
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第二页
await page.locator('.ant-pagination-item-2').click();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 顾客分配
await page.getByRole('menuitem', { name: '顾客分配' }).click();
// 点击已经已分配
await page.locator('.label_text', { hasText: '移除已分配咨询师' }).click();
// 确认分配
await page.getByRole('button', { name: '确认分配' }).click();
// 操作成功
await expect(page.locator('.ant-message-notice', { hasText: '操作成功' })).toBeVisible();
});
test('新增待办', async ({ page, homeNavigation }) => {
// 随机数字备注
const remark = faker.helpers.fromRegExp(/1[3-9][0-9]{7}/);
await test.step('勾选会员并记录该会员手机', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 获取准备选中的会员手机1
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
usePhones[0] = await member.locator('td .user_info_body').first().innerText();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取准备选中的会员手机2
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
usePhones[1] = await member.locator('td .user_info_body').first().innerText();
console.log('手机1=' + usePhones[0] + '手机2=' + usePhones[1]);
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
});
await test.step('批量操作新增待办', async () => {
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击新增代办事项
await page.getByRole('menuitem', { name: '新增待办事项' }).click();
await page.locator('.a_title').waitFor();
const title = (await page.locator('.a_title').innerText()).trim();
expect.soft(title).toBe('批量新增事项');
await expect(async () => {
await page.getByPlaceholder('请选择日期').click();
await page.locator('.date_picker_today', { hasText: '今天' }).click();
await page.locator('.normal', { hasText: '今天' }).waitFor({ timeout: 2000 });
}).toPass();
// 选择类型
await page.locator('.ant-radio-button-wrapper', { hasText: '电话回访' }).click();
// 填入随机备注
await page.getByPlaceholder('请输入1-100个字符的备注内容').fill(remark);
await page.locator('.shop_btn', { hasText: '确认添加' }).click();
await page.locator('.ant-message', { hasText: '操作成功' }).waitFor();
await expect.soft(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
});
await test.step('校验数据', async () => {
// 点击第一个会员
await page.locator('.m-table__fixed-left .m-table__body tbody tr').first().locator('td').nth(1).click();
await page.locator('.consume_data').waitFor();
// 点击动态
await page.locator('.ant-tabs-nav-animated .ant-tabs-tab', { hasText: '动态' }).click();
await page.locator('.ant-fullcalendar-tbody').first().waitFor();
// 切换列表模式
if (await page.locator('.selected_btn', { hasText: '日历模式' }).isVisible()) {
await page.locator('.date_change').first().click();
} else {
console.log('无需切换');
}
await page.locator('.ant-tabs-tabpane-active .m-table__body-wrapper').waitFor();
const success = page.locator('.ant-tabs-tabpane-active .m-table__body-wrapper .m-table__body tbody tr');
const success_color = await success
.filter({ has: page.locator('td', { hasText: remark }) })
.locator('td')
.nth(2)
.innerText();
expect.soft(success_color).toBe('已完成');
await page.locator('.close_icons').click();
});
});
test('设置标签', async ({ page, homeNavigation }) => {
await test.step('勾选会员并记录该会员手机', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 获取准备选中的会员手机1
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
usePhones[2] = await member.locator('td .user_info_body').first().innerText();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取准备选中的会员手机2
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
usePhones[3] = await member.locator('td .user_info_body').first().innerText();
console.log('手机1=' + usePhones[2] + '手机2=' + usePhones[3]);
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
});
await test.step('批量操作设置标签', async () => {
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击设置标签
await page.getByRole('menuitem', { name: '设置标签' }).click();
// 等待选择标签出现
await page.locator('.ant-modal-title', { hasText: '选择标签' }).waitFor();
// 点击两次标题全选 全取消
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
const check = page.locator('.ant-tree-checkbox-checked').first();
await expect(check).toBeVisible();
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
await expect(check).not.toBeVisible();
// 选择铺垫期、销售期
await page.locator('.ant-tree-title', { hasText: '铺垫期' }).click();
await page.locator('.ant-tree-node-selected', { hasText: '铺垫期' }).waitFor();
await page.locator('.ant-tree-title', { hasText: '销售期' }).click();
await page.locator('.ant-tree-node-selected', { hasText: '销售期' }).waitFor();
// 确认
await page.locator('.ok_btn', { hasText: /^确\s认$/ }).click();
});
await test.step('校验数据', async () => {
// 根据获取的手机号码搜索该会员
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(usePhones[2]);
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
// 等待会员数据弹出
await page.locator('.alertBox .close').waitFor();
// 根据指定手机点击会员
await page.locator('.member_list_li').filter({ hasText: usePhones[2] }).click();
// 点击进入详情
await page.locator('.m-table__fixed-left .user_info_body', { hasText: usePhones[2] }).click();
// 等待基础资料特定界面出现
await page.locator('.basic_box .base_info').first().waitFor();
// 判断标签显示是否正确
const pdq = await page.locator('.sign_txt', { hasText: '铺垫期' }).innerText();
expect(pdq).toBe('铺垫期');
const xxq = await page.locator('.sign_txt', { hasText: '销售期' }).innerText();
expect(xxq).toBe('销售期');
// 顺带去掉该标签
await page.locator('.sign .edit_icon').click();
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
const checks = page.locator('.ant-tree-checkbox-checked').first();
await expect(checks).toBeVisible();
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
await expect(checks).not.toBeVisible();
await page.locator('.ok_btn', { hasText: /^确\s认$/ }).click();
await page.locator('.close_icons').click();
// 根据获取手机搜索会员
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(usePhones[3]);
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
// 等待会员数据弹出
await page.locator('.alertBox .close').waitFor();
// 根据指定手机点击会员
await page.locator('.member_list_li').filter({ hasText: usePhones[3] }).click();
// 点击进入详情
await page.locator('.m-table__fixed-left .user_info_body', { hasText: usePhones[3] }).click();
// 等待基础资料特定界面出现
await page.locator('.basic_box .base_info').first().waitFor();
// 判断标签显示是否正确
expect.soft(pdq).toBe('铺垫期');
expect(xxq).toBe('销售期');
// 顺带去掉该标签
await page.locator('.sign .edit_icon').click();
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
await expect(checks).toBeVisible();
await page.locator('.ant-tree-title', { hasText: '顾客六期管理' }).click();
await expect(checks).not.toBeVisible();
await page.locator('.ok_btn', { hasText: /^确\s认$/ }).click();
});
});
test('设置无效客', async ({ page, homeNavigation, customerPage }) => {
let usernameA;
let phoneA;
const ca = new Customer(1, 1);
await test.step('创建会员', async () => {
// 创建顾客
await customerPage.createCustomer(ca);
usernameA = ca.username;
phoneA = ca.phone;
});
await test.step('搜索创建的会员设置无效客', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(phoneA);
await expect(async () => {
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
await page.locator('.alertBox .close').waitFor();
await page.locator('.member_list_li').filter({ hasText: usernameA }).click();
const useinfo = page.locator('.member_list_li').filter({ hasText: usernameA });
await expect(useinfo).not.toBeVisible();
const member = page.locator('.m-table__fixed-left tbody tr');
await member.locator('td .user_info_body', { hasText: phoneA }).first().waitFor();
}).toPass();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击设为无效客
await page.getByRole('menuitem', { name: '设为无效客' }).click();
// 确认
await page.locator('.comfirm_btn', { hasText: /^确\s认$/ }).click();
await expect(page.locator('.ant-message', { hasText: '操作成功' })).toBeVisible();
});
await test.step('高级搜索无效客', async () => {
// 点击高级搜索
await page.locator('.ant-btn-default', { hasText: /^高\s级$/ }).click();
await page.locator('.shopSelect_title', { hasText: '顾客高级查询' }).waitFor();
// 点击两次全选确保所有门店默认未选
await page
.locator('.item_sub')
.filter({ has: page.locator('.item_name', { hasText: '所属门店' }) })
.locator('.item_val')
.click();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断某个门店被选中
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page
.locator('.comPicker_btn', { hasText: /^全\s选$/ })
.first()
.click();
// 判断门店未被选中
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).not.toBeVisible();
await page.locator('.label_checkbox', { hasText: 'AT测试一店' }).click();
// 确认选中一店
await expect(page.locator('.ant-checkbox-wrapper-checked', { hasText: 'AT测试一店' })).toBeVisible();
await page.locator('.ant-btn-primary', { hasText: '确定选择' }).nth(1).click();
// 搜索关键字手机
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(phoneA);
await page
.locator('.ant-checkbox-wrapper')
.filter({ has: page.locator('.needsclick', { hasText: '无效客' }) })
.locator('.ant-checkbox')
.click();
const Invalid = page.locator('.ant-checkbox-wrapper-checked', { hasText: '无效客' });
// 判断无效客选中
await expect(Invalid).toBeVisible();
// 点击搜索
await page.locator('.ant-btn-block').click();
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
const $use = page.locator('.m-table__fixed-left tbody tr').first();
await expect(async () => {
if (await $use.isVisible()) {
await expect(page.locator('.m-table__fixed-left tbody tr', { hasText: phoneA })).toBeVisible();
} else {
// 点击高级搜索
await page.locator('.ant-btn-default', { hasText: /^高\s级$/ }).click();
await page.locator('.shopSelect_title', { hasText: '顾客高级查询' }).waitFor();
// 点击搜索
await page.locator('.ant-btn-block').click();
}
}).toPass();
});
});
test('设置会员分类', async ({ page, homeNavigation }) => {
await test.step('勾选会员并记录该会员手机', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 获取准备选中的会员手机1
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
usePhones[4] = await member.locator('td .user_info_body').first().innerText();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取准备选中的会员手机2
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
usePhones[5] = await member.locator('td .user_info_body').first().innerText();
console.log('手机1=' + usePhones[4] + '手机2=' + usePhones[5]);
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
});
await test.step('批量操作设置会员分类', async () => {
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击设置会员分类
await page.getByRole('menuitem', { name: '设置会员分类' }).click();
// 等待设置会员分类出现
await page.locator('.ant-model-title', { hasText: '设置会员分类' }).waitFor();
await expect(async () => {
// 选择铺(铺垫期)
await page.locator('.class_tag .tag', { hasText: '铺' }).click();
const check = page.locator('.select_style');
await expect(check).toBeVisible({ timeout: 2000 });
// 确认
await page.locator('.comfirm_btn', { hasText: /^确\s认$/ }).click();
await page.locator('.ant-message', { hasText: '操作成功' }).waitFor({ timeout: 5000 });
}).toPass();
});
await test.step('校验数据', async () => {
// 根据获取的手机号码搜索该会员
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(usePhones[4]);
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
// 等待会员数据弹出
await page.locator('.alertBox .close').waitFor();
// 根据指定手机点击会员
await page.locator('.member_list_li').filter({ hasText: usePhones[4] }).click();
// 点击进入详情
await page.locator('.m-table__fixed-left .user_info_body', { hasText: usePhones[4] }).click();
// 等待基础资料特定界面出现
await page.locator('.basic_box .base_info').first().waitFor();
// 判断分类显示是否正确
const sort = page.locator('.tag_list .class_icon .icon_style', { hasText: '铺' });
await expect(sort).toBeVisible();
// 去掉该分类判断一下是否消失
// 点击三点
await page.locator('.more_icon svg').click();
// 选择会员分类设置
await page.locator('.ant-dropdown-menu-item', { hasText: '设置会员分类' }).click();
// 等待设置会员分类出现
await page.locator('.ant-model-title', { hasText: '设置会员分类' }).waitFor();
// 点击被选中的分类
await page.locator('.select_style').click();
// 判断选中分类已取消
await expect(page.locator('.select_style')).not.toBeVisible();
// 确认
await page.locator('.comfirm_btn', { hasText: /^确\s认$/ }).click();
// 关闭详情
await page.locator('.close_icons').click();
// 根据获取的手机号码搜索该会员
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(usePhones[5]);
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
// 等待会员数据弹出
await page.locator('.alertBox .close').waitFor();
// 根据指定手机点击会员
await page.locator('.member_list_li').filter({ hasText: usePhones[5] }).click();
// 点击进入详情
await page.locator('.m-table__fixed-left .user_info_body', { hasText: usePhones[5] }).click();
// 等待基础资料特定界面出现
await page.locator('.basic_box .base_info').first().waitFor();
// 判断分类显示是否正确
await expect.soft(sort).toBeVisible();
// 去掉该分类判断一下是否消失
// 点击三点
await page.locator('.more_icon svg').click();
// 选择会员分类设置
await page.locator('.ant-dropdown-menu-item', { hasText: '设置会员分类' }).click();
// 等待设置会员分类出现
await page.locator('.ant-model-title', { hasText: '设置会员分类' }).waitFor();
// 点击被选中的分类
await page.locator('.select_style').click();
// 判断选中分类已取消
await expect(page.locator('.select_style')).not.toBeVisible();
// 确认
await page.locator('.comfirm_btn', { hasText: /^确\s认$/ }).click();
// 关闭详情
await page.locator('.close_icons').click();
});
});
test('赠送积分', async ({ page, homeNavigation, numberInput }) => {
//输入积分
const points = 8;
await test.step('勾选会员并记录该会员手机', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 获取准备选中的会员手机1
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
usePhones[6] = await member.locator('td .user_info_body').first().innerText();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取准备选中的会员手机2
await expect(page.locator('.m-table__icon__warp')).toBeHidden();
usePhones[7] = await member.locator('td .user_info_body').first().innerText();
console.log('手机1=' + usePhones[6] + '手机2=' + usePhones[7]);
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
});
await test.step('批量操作赠送积分', async () => {
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击赠送积分
await page.getByRole('menuitem', { name: '赠送积分' }).click();
// 等待赠送积分出现
await page.locator('.popup_content .title', { hasText: '赠送积分' }).waitFor();
// 输入积分
await numberInput.setValue(points);
await numberInput.confirmValue();
await page.locator('.ant-message-custom-content', { hasText: '赠送成功预计10分钟内到账' }).waitFor();
await expect(
page.locator('.ant-message-custom-content', {
hasText: '赠送成功预计10分钟内到账',
}),
).toBeVisible();
});
await test.step('校验核对', async () => {
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').fill(usePhones[6]);
await page.locator('.ant-input-suffix', { hasText: '搜索' }).click();
// 等待会员数据弹出
await page.locator('.alertBox .close').waitFor();
// 根据指定手机点击会员
await page.locator('.member_list_li').filter({ hasText: usePhones[6] }).click();
// 点击进入详情
await page.locator('.m-table__fixed-left .user_info_body', { hasText: usePhones[6] }).click();
// 等待基础资料特定界面出现
await page.locator('.basic_box .base_info').first().waitFor();
// 详情页点击流水
await page.locator('.ant-tabs-tab', { hasText: '流水' }).click();
// 等待页面加载
await page.locator('.tab_btn .ant-radio-button-wrapper').first().waitFor();
// 点击积分记录
await page.locator('.tab_btn .ant-radio-button-wrapper', { hasText: '积分记录' }).click();
// 获取积分变动
await expect(page.locator('.positive').first()).toContainText(`${points}`);
});
});
test('群发优惠券', async ({ page, homeNavigation }) => {
// 用于存储会员名称
const useNames = [];
await test.step('勾选会员并记录该会员手机', async () => {
// 进入顾客界面
await homeNavigation.gotoModule('顾客');
// 点击潜客
await page.locator('.sub_icon').nth(3).click();
// 打开顾客列表
// 获取准备选中的会员手机1
await page.locator('.m-table-pagination .dec').waitFor();
const member = page.locator('.m-table__fixed-left tbody tr');
useNames[0] = await member.locator('td .user_name').first().innerText();
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
// 点击第下一页
await page.locator('.ant-pagination-next').click();
// 获取准备选中的会员手机2
await expect.soft(page.locator('.m-table__icon__warp')).toBeHidden();
useNames[1] = await member.locator('td .user_name').first().innerText();
console.log('姓名1=' + useNames[0] + '姓名2=' + useNames[1]);
// 选中第一个顾客
await page.locator('.m-table__fixed-left .is-center').nth(1).click();
});
await test.step('批量操作赠送积分', async () => {
// 判断批量操作出现
const Batch = page.locator('.item-btns', { hasText: '批量操作' });
await expect(Batch).toBeVisible();
// 批量操作
await page.locator('.item-btns', { hasText: /^批量操作$/ }).click();
// 点击群发优惠券
await page.getByRole('menuitem', { name: '群发优惠券' }).click();
// 等待群发优惠券出现
await page.locator('.m_sliding_menu .header', { hasText: '群发优惠券' }).waitFor();
// 点击添加优惠券
await page.locator('.add_txt', { hasText: '添加优惠券' }).click();
await page.locator('.popup_content .title', { hasText: '选择优惠券' }).waitFor();
// 选择优惠券
await page.locator('.check_item').click();
// 判断是否选中
const coupon = page.locator('.ant-checkbox-checked').first();
await expect(coupon).toBeVisible();
// 保存
await page.locator('.confirm_btn', { hasText: /^保\s存$/ }).click();
const coupons = page.locator('.coupon_list').first();
await expect(coupons).toBeVisible();
// 确认发送
await page.locator('.sure_btn span', { hasText: '确认发送' }).click();
await page.locator('.handle_task_content').waitFor();
// 点击顾客列表
await page.locator('.m-table__fixed-right tbody .gustom_list_btn').first().click();
// 等待发送顾客列表
await page.locator('.custom_list_content .header').first().waitFor();
await expect.soft(page.locator('.custom_name').first()).toContainText(useNames[0]);
await expect(page.locator('.custom_name').last()).toContainText(useNames[1]);
});
});
});