优化代码
This commit is contained in:
parent
cf67a1c95c
commit
8c910d9086
@ -2,6 +2,7 @@
|
|||||||
const { defineConfig, devices } = require('@playwright/test');
|
const { defineConfig, devices } = require('@playwright/test');
|
||||||
// import dotenv from "dotenv";
|
// import dotenv from "dotenv";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read environment variables from file.
|
* Read environment variables from file.
|
||||||
* https://github.com/motdotla/dotenv
|
* https://github.com/motdotla/dotenv
|
||||||
@ -41,7 +42,8 @@ module.exports = defineConfig({
|
|||||||
/* Opt out of parallel tests on CI. */
|
/* Opt out of parallel tests on CI. */
|
||||||
workers: process.env.CI ? 1 : 2,
|
workers: process.env.CI ? 1 : 2,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: [['html'], ['list'], ['./my-awesome-reporter.ts']],
|
// reporter: [['html'], ['list'], ['./my-awesome-reporter.ts']],
|
||||||
|
reporter: [['html'], ['list']],
|
||||||
|
|
||||||
// reporter: './my-awesome-reporter.ts',
|
// reporter: './my-awesome-reporter.ts',
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
@ -71,12 +73,12 @@ module.exports = defineConfig({
|
|||||||
projects: [
|
projects: [
|
||||||
{
|
{
|
||||||
name: '总部管理员鉴权',
|
name: '总部管理员鉴权',
|
||||||
testMatch: /.*boss_auth\.setup\.js/,
|
testMatch: /.*boss_auth\.setup\.ts/,
|
||||||
use: { baseURL: process.env.BASE_URL },
|
use: { baseURL: process.env.BASE_URL },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '门店员工鉴权',
|
name: '门店员工鉴权',
|
||||||
testMatch: /.*staff_auth\.setup\.js/,
|
testMatch: /.*staff_auth\.setup\.ts/,
|
||||||
use: { baseURL: process.env.BASE_URL },
|
use: { baseURL: process.env.BASE_URL },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -88,7 +90,7 @@ module.exports = defineConfig({
|
|||||||
viewport: { width: 1280, height: 720 },
|
viewport: { width: 1280, height: 720 },
|
||||||
isMobile: true,
|
isMobile: true,
|
||||||
},
|
},
|
||||||
testMatch: /.*boss_.*\.spec\.js/,
|
testMatch: /.*boss_.*\.spec\.ts/,
|
||||||
dependencies: ['总部管理员鉴权'],
|
dependencies: ['总部管理员鉴权'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -100,7 +102,7 @@ module.exports = defineConfig({
|
|||||||
viewport: { width: 1280, height: 720 },
|
viewport: { width: 1280, height: 720 },
|
||||||
isMobile: true,
|
isMobile: true,
|
||||||
},
|
},
|
||||||
testMatch: /.*boss_.*\.spec\.js/,
|
testMatch: /.*boss_.*\.spec\.ts/,
|
||||||
dependencies: ['总部管理员鉴权'],
|
dependencies: ['总部管理员鉴权'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -111,7 +113,7 @@ module.exports = defineConfig({
|
|||||||
viewport: { width: 1280, height: 720 },
|
viewport: { width: 1280, height: 720 },
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
},
|
},
|
||||||
testMatch: /.*staff_.*\.spec\.js/,
|
testMatch: /.*staff_.*\.spec\.ts/,
|
||||||
dependencies: ['门店员工鉴权'],
|
dependencies: ['门店员工鉴权'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -122,7 +124,7 @@ module.exports = defineConfig({
|
|||||||
viewport: { width: 1280, height: 720 },
|
viewport: { width: 1280, height: 720 },
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
},
|
},
|
||||||
testMatch: /.*staff_.*\.spec\.js/,
|
testMatch: /.*staff_.*\.spec\.ts/,
|
||||||
dependencies: ['门店员工鉴权'],
|
dependencies: ['门店员工鉴权'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
100
tests/fixtures/customerFixture.ts
vendored
100
tests/fixtures/customerFixture.ts
vendored
@ -1,16 +1,8 @@
|
|||||||
import { test as base } from '@playwright/test';
|
import { test as base, Page } from '@playwright/test';
|
||||||
import { CustomerPage, CustomerDetailsPage, CustomerAnalysisPage } from '@/pages/customer';
|
import { CustomerPage, CustomerDetailsPage, CustomerAnalysisPage } from '@/pages/customer';
|
||||||
import { Customer } from '@/utils/customer';
|
import { Customer } from '@/utils/customer';
|
||||||
|
|
||||||
type MyFixture = {
|
type MyFixture = {
|
||||||
singleCustomerPage: {
|
|
||||||
createCustomer: (customer: Customer) => Promise<void>;
|
|
||||||
setInvalidCustomer: (customer: Customer) => Promise<void>;
|
|
||||||
};
|
|
||||||
moreCustomerPage: {
|
|
||||||
createMoreCustomer: (customer: Customer[]) => Promise<void>;
|
|
||||||
setMoreInvalidCustomer: (customer: Customer[]) => Promise<void>;
|
|
||||||
};
|
|
||||||
customerPage: CustomerPage;
|
customerPage: CustomerPage;
|
||||||
customerDetailsPage: CustomerDetailsPage;
|
customerDetailsPage: CustomerDetailsPage;
|
||||||
customerAnalysisPage: CustomerAnalysisPage;
|
customerAnalysisPage: CustomerAnalysisPage;
|
||||||
@ -20,34 +12,50 @@ type MyFixture = {
|
|||||||
createCustomCustomers: (customers: Customer[]) => Promise<void>;
|
createCustomCustomers: (customers: Customer[]) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到顾客管理页面
|
||||||
|
*/
|
||||||
|
const navigateToCustomerSchema = async (page: Page, baseURL: string) => {
|
||||||
|
await page.goto(baseURL);
|
||||||
|
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
||||||
|
await page.goto('/#/member/member-schame');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置为无效顾客
|
||||||
|
* @param customerPage { CustomerPage } 顾客页面
|
||||||
|
* @param customers { Customer | Customer[] } 顾客列表
|
||||||
|
*/
|
||||||
|
const setInvalidCustomers = async (customerPage: CustomerPage, customers: Customer[] | Customer) => {
|
||||||
|
try {
|
||||||
|
if (Array.isArray(customers)) {
|
||||||
|
await customerPage.setMoreInvalidCustomer(customers);
|
||||||
|
} else {
|
||||||
|
await customerPage.setInvalidCustomer(customers);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set invalid customers:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const test = base.extend<MyFixture>({
|
export const test = base.extend<MyFixture>({
|
||||||
/**
|
/**
|
||||||
* 创建一个顾客
|
* 创建一个顾客
|
||||||
*/
|
*/
|
||||||
createCustomer: async ({ page, baseURL }, use) => {
|
createCustomer: async ({ page, baseURL }, use) => {
|
||||||
if (!baseURL) {
|
|
||||||
throw new Error('baseUrl is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const customerPage = new CustomerPage(page);
|
const customerPage = new CustomerPage(page);
|
||||||
const customer = new Customer(1, 1);
|
const customer = new Customer(1, 1);
|
||||||
await customerPage.createCustomer(customer);
|
await customerPage.createCustomer(customer);
|
||||||
await page.goto(baseURL);
|
|
||||||
await use(customer);
|
await use(customer);
|
||||||
await page.goto(baseURL);
|
await navigateToCustomerSchema(page, baseURL!);
|
||||||
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
await setInvalidCustomers(customerPage, customer);
|
||||||
await page.goto('/#/member/member-schame');
|
|
||||||
await customerPage.setInvalidCustomer(customer);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建多个顾客
|
* 创建多个顾客
|
||||||
*/
|
*/
|
||||||
createCustomers: async ({ page, baseURL }, use): Promise<void> => {
|
createCustomers: async ({ page, baseURL }, use): Promise<void> => {
|
||||||
if (!baseURL) {
|
|
||||||
throw new Error('baseUrl is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const customerPage = new CustomerPage(page);
|
const customerPage = new CustomerPage(page);
|
||||||
let createdCustomers: Customer[] = [];
|
let createdCustomers: Customer[] = [];
|
||||||
|
|
||||||
@ -70,56 +78,44 @@ export const test = base.extend<MyFixture>({
|
|||||||
|
|
||||||
if (createdCustomers.length === 0) return;
|
if (createdCustomers.length === 0) return;
|
||||||
|
|
||||||
// 测试结束后将客户设置为无效
|
await navigateToCustomerSchema(page, baseURL!);
|
||||||
await page.goto(baseURL);
|
await setInvalidCustomers(customerPage, createdCustomers);
|
||||||
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
|
||||||
await page.goto('/#/member/member-schame');
|
|
||||||
await customerPage.setMoreInvalidCustomer(createdCustomers);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个自定义顾客
|
* 创建一个自定义顾客
|
||||||
*/
|
*/
|
||||||
createCustomCustomer: async ({ page, baseURL }, use) => {
|
createCustomCustomer: async ({ page, baseURL }, use) => {
|
||||||
if (!baseURL) {
|
|
||||||
throw new Error('baseUrl is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const customerPage = new CustomerPage(page);
|
const customerPage = new CustomerPage(page);
|
||||||
let tmp: Customer | undefined;
|
let customizeCustomer: Customer | undefined;
|
||||||
const setCustomer = async (customer: Customer) => {
|
|
||||||
await customerPage.createCustomer(customer);
|
|
||||||
tmp = customer;
|
|
||||||
};
|
|
||||||
await use(setCustomer);
|
|
||||||
|
|
||||||
if (!tmp) return;
|
const createCustomizeCustomer = async (customer: Customer) => {
|
||||||
await page.goto(baseURL);
|
await customerPage.createCustomer(customer);
|
||||||
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
customizeCustomer = customer;
|
||||||
await page.goto('/#/member/member-schame');
|
};
|
||||||
await customerPage.setInvalidCustomer(tmp);
|
|
||||||
|
await use(createCustomizeCustomer);
|
||||||
|
|
||||||
|
if (!customizeCustomer) return;
|
||||||
|
await navigateToCustomerSchema(page, baseURL!);
|
||||||
|
await setInvalidCustomers(customerPage, customizeCustomer);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建多个自定义顾客
|
* 创建多个自定义顾客
|
||||||
*/
|
*/
|
||||||
createCustomCustomers: async ({ page, baseURL }, use) => {
|
createCustomCustomers: async ({ page, baseURL }, use) => {
|
||||||
if (!baseURL) {
|
|
||||||
throw new Error('baseUrl is required');
|
|
||||||
}
|
|
||||||
const customerPage = new CustomerPage(page);
|
const customerPage = new CustomerPage(page);
|
||||||
let tmp: Customer[] | undefined;
|
let createCustomizeCustomerArray: Customer[] | undefined;
|
||||||
const setCustomers = async (customers: Customer[]) => {
|
const setCustomers = async (customers: Customer[]) => {
|
||||||
await customerPage.createMoreCustomer(customers);
|
await customerPage.createMoreCustomer(customers);
|
||||||
tmp = customers;
|
createCustomizeCustomerArray = customers;
|
||||||
};
|
};
|
||||||
await use(setCustomers);
|
await use(setCustomers);
|
||||||
|
|
||||||
if (!tmp) return;
|
if (!createCustomizeCustomerArray) return;
|
||||||
await page.goto(baseURL);
|
await navigateToCustomerSchema(page, baseURL!);
|
||||||
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
await setInvalidCustomers(customerPage, createCustomizeCustomerArray);
|
||||||
await page.goto('/#/member/member-schame');
|
|
||||||
await customerPage.setMoreInvalidCustomer(tmp);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -34,7 +34,6 @@ export class NumberInput {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置值
|
* 设置值
|
||||||
* @param value
|
|
||||||
*/
|
*/
|
||||||
async setValue(value: number): Promise<void> {
|
async setValue(value: number): Promise<void> {
|
||||||
await this.inputLocator.fill(value.toString());
|
await this.inputLocator.fill(value.toString());
|
||||||
|
|||||||
@ -6,7 +6,6 @@ export class CustomerAnalysisPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 顾客分析页面
|
* 顾客分析页面
|
||||||
* @param {import("@playwright/test").Page} page
|
|
||||||
*/
|
*/
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { expect, type Locator, type Page } from '@playwright/test';
|
import { expect, type Locator, type Page } from '@playwright/test';
|
||||||
import { HomeNavigation } from '../homeNavigationPage.js';
|
import { Customer, employee } from '@/utils/customer';
|
||||||
import { Customer, employee } from '../../utils/customer';
|
import { waitSpecifyApiLoad } from '@/utils/utils';
|
||||||
import { waitSpecifyApiLoad } from '../../utils/utils.js';
|
|
||||||
|
|
||||||
type SubPage = {
|
type SubPage = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -14,7 +13,6 @@ type SubPage = {
|
|||||||
*/
|
*/
|
||||||
export class CustomerPage {
|
export class CustomerPage {
|
||||||
page: Page;
|
page: Page;
|
||||||
private readonly homeNavigation: HomeNavigation;
|
|
||||||
private readonly subPages: SubPage[] = [
|
private readonly subPages: SubPage[] = [
|
||||||
{ name: '顾客概要', url: ['summary', 'todo'] },
|
{ name: '顾客概要', url: ['summary', 'todo'] },
|
||||||
{ name: '顾客分配', url: ['search_new', 'distribution'] },
|
{ name: '顾客分配', url: ['search_new', 'distribution'] },
|
||||||
@ -42,15 +40,14 @@ export class CustomerPage {
|
|||||||
$register: Locator;
|
$register: Locator;
|
||||||
$tabItem: Locator;
|
$tabItem: Locator;
|
||||||
$searchInput: Locator;
|
$searchInput: Locator;
|
||||||
$searchConfirm: Locator;
|
$searchBtn: Locator;
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.$tabItem = this.page.locator('.top_tab .tab_item');
|
this.$tabItem = this.page.locator('.top_tab .tab_item');
|
||||||
this.$register = this.page.locator('.regmeber_warp', { hasText: '创建会员' });
|
this.$register = this.page.locator('.regmeber_warp', { hasText: '创建会员' });
|
||||||
this.$searchInput = this.page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索');
|
this.$searchInput = this.page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索');
|
||||||
this.$searchConfirm = this.page.getByText('搜索', { exact: true });
|
this.$searchBtn = this.page.getByText('搜索', { exact: true });
|
||||||
this.homeNavigation = new HomeNavigation(this.page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,19 +65,19 @@ export class CustomerPage {
|
|||||||
throw new Error(`子页面 ${subPageName} 不存在`);
|
throw new Error(`子页面 ${subPageName} 不存在`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const $subPage = this.$tabItem.filter({ hasText: subPageName });
|
const $subPageTab = this.$tabItem.filter({ hasText: subPageName });
|
||||||
|
|
||||||
await $subPage.waitFor();
|
await $subPageTab.waitFor();
|
||||||
|
|
||||||
const classAttribute = await $subPage.getAttribute('class', { timeout: 5000 });
|
const classAttribute = await $subPageTab.getAttribute('class', { timeout: 5000 });
|
||||||
if (classAttribute && classAttribute.includes('active')) {
|
if (classAttribute && classAttribute.includes('active')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
expect(async () => {
|
expect(async () => {
|
||||||
await $subPage.click();
|
await $subPageTab.click();
|
||||||
await expect($subPage).toHaveClass(/active/);
|
await expect($subPageTab).toHaveClass(/active/);
|
||||||
}).toPass(),
|
}).toPass(),
|
||||||
waitSpecifyApiLoad(this.page, subPage.url),
|
waitSpecifyApiLoad(this.page, subPage.url),
|
||||||
]);
|
]);
|
||||||
@ -95,7 +92,7 @@ export class CustomerPage {
|
|||||||
const $customerInfoCard = $$customerContent.filter({ hasText: text }).first();
|
const $customerInfoCard = $$customerContent.filter({ hasText: text }).first();
|
||||||
|
|
||||||
await this.$searchInput.fill(text);
|
await this.$searchInput.fill(text);
|
||||||
await this.$searchConfirm.click();
|
await this.$searchBtn.click();
|
||||||
await $customerInfoCard.waitFor();
|
await $customerInfoCard.waitFor();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -136,14 +133,13 @@ export class CustomerPage {
|
|||||||
* 关闭顾客详情页面
|
* 关闭顾客详情页面
|
||||||
*/
|
*/
|
||||||
closeCustomerDetail = async () => {
|
closeCustomerDetail = async () => {
|
||||||
const closeButton = this.page.locator('.member_info_box .close_icons > svg');
|
const $closeBtn = this.page.locator('.member_info_box .close_icons > svg');
|
||||||
await closeButton.click();
|
await $closeBtn.click();
|
||||||
await closeButton.waitFor({ state: 'detached' });
|
await $closeBtn.waitFor({ state: 'detached' });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建顾客
|
* 创建顾客
|
||||||
* @param {Customer} customer 顾客
|
|
||||||
*/
|
*/
|
||||||
createCustomer = async (customer: Customer) => {
|
createCustomer = async (customer: Customer) => {
|
||||||
const customerPage = '/#/member/member-schame';
|
const customerPage = '/#/member/member-schame';
|
||||||
@ -249,11 +245,22 @@ export class CustomerPage {
|
|||||||
* @param gender 性别
|
* @param gender 性别
|
||||||
*/
|
*/
|
||||||
private readonly selectGender = async (gender: number) => {
|
private readonly selectGender = async (gender: number) => {
|
||||||
|
// 定义性别选项的映射
|
||||||
|
const GENDER_OPTIONS = {
|
||||||
|
FEMALE: 0,
|
||||||
|
MALE: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 定义对应的文本
|
||||||
|
const GENDER_TEXTS = {
|
||||||
|
[GENDER_OPTIONS.FEMALE]: '女性',
|
||||||
|
[GENDER_OPTIONS.MALE]: '男性',
|
||||||
|
};
|
||||||
|
|
||||||
if (gender === 0) {
|
if (gender === 0) {
|
||||||
await this.$register.locator('label').filter({ hasText: '女性' }).click();
|
return;
|
||||||
} else if (gender === 1) {
|
|
||||||
await this.$register.locator('label').filter({ hasText: '男性' }).click();
|
|
||||||
}
|
}
|
||||||
|
await this.$register.locator('label').filter({ hasText: GENDER_TEXTS[gender] }).click();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,23 +271,37 @@ export class CustomerPage {
|
|||||||
* @param {number} birthday.day 日期
|
* @param {number} birthday.day 日期
|
||||||
*/
|
*/
|
||||||
private readonly selectBirthday = async (birthday: { year: number; month: number; day: number }) => {
|
private readonly selectBirthday = async (birthday: { year: number; month: number; day: number }) => {
|
||||||
if (birthday) {
|
if (!birthday) {
|
||||||
|
throw new Error('birthday参数为空');
|
||||||
|
}
|
||||||
const { year, month, day } = birthday;
|
const { year, month, day } = birthday;
|
||||||
const birthdayLocator = this.$register.locator('.ant-form-item', { hasText: '生日' });
|
|
||||||
|
if (!Number.isInteger(year) || year < 1900 || year > new Date().getFullYear()) {
|
||||||
|
throw new Error(`年份 ${year} 不合法`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(month) || month < 1 || month > 12) {
|
||||||
|
throw new Error(`月份 ${month} 不合法`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(day) || day < 1 || day > 31) {
|
||||||
|
throw new Error(`日期 ${day} 不合法`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const $birthday = this.$register.locator('.ant-form-item', { hasText: '生日' });
|
||||||
if (year) {
|
if (year) {
|
||||||
await birthdayLocator.getByText('年份').click();
|
await $birthday.getByText('年份').click();
|
||||||
await this.page.getByRole('option', { name: `${year}` }).click();
|
await this.page.getByRole('option', { name: `${year}` }).click();
|
||||||
await expect(this.page.getByRole('option', { name: `${year}` })).not.toBeVisible();
|
await expect(this.page.getByRole('option', { name: `${year}` })).not.toBeVisible();
|
||||||
}
|
}
|
||||||
if (month && day) {
|
if (month && day) {
|
||||||
await birthdayLocator.getByText('日期').click();
|
await $birthday.getByText('日期').click();
|
||||||
await this.page.getByRole('option', { name: new RegExp(`^${month}\\s月$`) }).click();
|
await this.page.getByRole('option', { name: new RegExp(`^${month}\\s月$`) }).click();
|
||||||
await this.page.getByRole('option', { name: new RegExp(`^${day}\\s日$`) }).click();
|
await this.page.getByRole('option', { name: new RegExp(`^${day}\\s日$`) }).click();
|
||||||
await this.page.getByRole('button', { name: /确\s认/ }).click();
|
await this.page.getByRole('button', { name: /确\s认/ }).click();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`month:${month}, day:${day}其中一个为空`);
|
throw new Error(`month:${month}, day:${day}其中一个为空`);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,9 +317,8 @@ export class CustomerPage {
|
|||||||
* @param {string} remark 备注
|
* @param {string} remark 备注
|
||||||
*/
|
*/
|
||||||
private readonly fillRemark = async (remark: string) => {
|
private readonly fillRemark = async (remark: string) => {
|
||||||
if (remark) {
|
if (!remark) return;
|
||||||
await this.$register.getByPlaceholder('请输入1-100个字符备注内容').fill(remark);
|
await this.$register.getByPlaceholder('请输入1-100个字符备注内容').fill(remark);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -315,7 +335,7 @@ export class CustomerPage {
|
|||||||
const responseBody = await response.json();
|
const responseBody = await response.json();
|
||||||
|
|
||||||
const phoneStatus = responseBody?.content?.status;
|
const phoneStatus = responseBody?.content?.status;
|
||||||
if (!phoneStatus) {
|
if (phoneStatus === undefined || phoneStatus === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.page.getByText('系统查询到当前手机号被建档后转为无效客,是否要恢复无效客?').waitFor();
|
await this.page.getByText('系统查询到当前手机号被建档后转为无效客,是否要恢复无效客?').waitFor();
|
||||||
@ -341,7 +361,6 @@ export class CustomerPage {
|
|||||||
await this.page.locator('.m-table__fixed-left').getByText(customer.username).first().click();
|
await this.page.locator('.m-table__fixed-left').getByText(customer.username).first().click();
|
||||||
|
|
||||||
// 设置无效客
|
// 设置无效客
|
||||||
await this.page.locator('.person_content').waitFor();
|
|
||||||
await this.page.locator('.person_content .tag_box .more_icon svg').click();
|
await this.page.locator('.person_content .tag_box .more_icon svg').click();
|
||||||
await this.page.getByRole('menuitem', { name: '设为无效客' }).click();
|
await this.page.getByRole('menuitem', { name: '设为无效客' }).click();
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
@ -372,7 +391,7 @@ export class CustomerPage {
|
|||||||
*/
|
*/
|
||||||
setMoreInvalidCustomer = async (customerArray: Customer[]) => {
|
setMoreInvalidCustomer = async (customerArray: Customer[]) => {
|
||||||
for (const customer of customerArray) {
|
for (const customer of customerArray) {
|
||||||
this.page.reload();
|
await this.page.reload();
|
||||||
await this.setInvalidCustomer(customer);
|
await this.setInvalidCustomer(customer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { waitSpecifyApiLoad } from '@/utils/utils';
|
|||||||
export class InventoryManagementPage {
|
export class InventoryManagementPage {
|
||||||
page: Page;
|
page: Page;
|
||||||
subPages: { name: string; url?: string[] }[];
|
subPages: { name: string; url?: string[] }[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 库存管理页
|
* 库存管理页
|
||||||
* @param page
|
* @param page
|
||||||
|
|||||||
@ -4,9 +4,10 @@ import { waitSpecifyApiLoad } from '@/utils/utils';
|
|||||||
export class TransferManagementPage {
|
export class TransferManagementPage {
|
||||||
page: Page;
|
page: Page;
|
||||||
subPages: { name: string; url?: string[] }[];
|
subPages: { name: string; url?: string[] }[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 库存-调货管理页面
|
* 库存-调货管理页面
|
||||||
* @param {import("@playwright/test").Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
*/
|
*/
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
|
|||||||
@ -11,20 +11,20 @@ const regex = /^https?:\/\/(www\.)?hlk\.meiguanjia\.net\/?(#\s)?$/;
|
|||||||
const personalizedPages = '/#/marketing/brand/personalized';
|
const personalizedPages = '/#/marketing/brand/personalized';
|
||||||
|
|
||||||
class testAccount {
|
class testAccount {
|
||||||
constructor(account, password, path) {
|
constructor(account: string, password: string, path: string) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
account;
|
account: string;
|
||||||
password;
|
password: string;
|
||||||
path;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const allAccounts = [
|
const allAccounts = [
|
||||||
new testAccount(process.env.boss_account, process.env.boss_password, firstAuthFile),
|
new testAccount(process.env.boss_account!, process.env.boss_password!, firstAuthFile),
|
||||||
new testAccount(process.env.boss_account_2, process.env.boss_password_2, secondAuthFile),
|
new testAccount(process.env.boss_account_2!, process.env.boss_password_2!, secondAuthFile),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let a of allAccounts) {
|
for (let a of allAccounts) {
|
||||||
@ -37,7 +37,7 @@ for (let a of allAccounts) {
|
|||||||
.locator('div', { has: page.getByRole('textbox', { name: '请输入您的手机号码' }) })
|
.locator('div', { has: page.getByRole('textbox', { name: '请输入您的手机号码' }) })
|
||||||
.locator('.pass_svg');
|
.locator('.pass_svg');
|
||||||
|
|
||||||
await page.goto(baseURL);
|
await page.goto(baseURL!);
|
||||||
await page.getByRole('textbox', { name: '请输入您的手机号码' }).fill(account);
|
await page.getByRole('textbox', { name: '请输入您的手机号码' }).fill(account);
|
||||||
await page.getByRole('textbox', { name: '请输入登录密码' }).fill(password);
|
await page.getByRole('textbox', { name: '请输入登录密码' }).fill(password);
|
||||||
await page.getByLabel('请同意慧来客隐私政策和用户协议').check();
|
await page.getByLabel('请同意慧来客隐私政策和用户协议').check();
|
||||||
@ -45,7 +45,7 @@ for (let a of allAccounts) {
|
|||||||
await page.getByRole('button', { name: /登\s录/ }).click();
|
await page.getByRole('button', { name: /登\s录/ }).click();
|
||||||
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
await page.getByRole('button', { name: /开\s单/ }).waitFor();
|
||||||
|
|
||||||
if (regex.test(baseURL)) {
|
if (regex.test(baseURL!)) {
|
||||||
await page.goto(personalizedPages);
|
await page.goto(personalizedPages);
|
||||||
await page.getByRole('button', { name: '新增模块' }).waitFor();
|
await page.getByRole('button', { name: '新增模块' }).waitFor();
|
||||||
const $sideIframe = page.locator('.side iframe').contentFrame();
|
const $sideIframe = page.locator('.side iframe').contentFrame();
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import { faker } from '@faker-js/faker/locale/zh_CN';
|
import { faker } from '@faker-js/faker/locale/zh_CN';
|
||||||
import { test, expect } from '@/fixtures/boss_common.js';
|
import { test, expect } from '@/fixtures/boss_common.js';
|
||||||
import path from 'path';
|
|
||||||
import fs from 'fs';
|
|
||||||
import { staffData } from '@/fixtures/staff.js';
|
import { staffData } from '@/fixtures/staff.js';
|
||||||
import { HomeNavigation } from '@/pages/homeNavigationPage.js';
|
import { HomeNavigation } from '@/pages/homeNavigationPage.js';
|
||||||
import { AppointmentPage } from '@/pages/appointmentPage.js';
|
import { AppointmentPage } from '@/pages/appointmentPage.js';
|
||||||
import { AppointmentOperation } from '@/pages/appointmentPage.js';
|
import { AppointmentOperation } from '@/pages/appointmentPage.js';
|
||||||
|
|
||||||
test('使用预约单元格', async ({ page, homeNavigation, createCustomer, appointmentPage, customerPage }) => {
|
test('使用预约单元格', async ({ page, homeNavigation, createCustomer, appointmentPage, customerPage }) => {
|
||||||
const setAppointmentTime = appointmentPage.getAppointmentTimesAvailable();
|
|
||||||
const customer = createCustomer;
|
|
||||||
const employee = staffData.firstStore.firstSector.employee_1;
|
const employee = staffData.firstStore.firstSector.employee_1;
|
||||||
// 当前可预约时间定位器
|
const setAppointmentTime = appointmentPage.getAppointmentTimesAvailable();
|
||||||
|
|
||||||
|
const customer = createCustomer;
|
||||||
|
|
||||||
|
/** 当前可预约时间定位器 */
|
||||||
const $time = page.locator('.times_table td').filter({ hasText: setAppointmentTime });
|
const $time = page.locator('.times_table td').filter({ hasText: setAppointmentTime });
|
||||||
// 顾客预约定位器
|
/** 顾客预约定位器 */
|
||||||
const $customerAppointment = page
|
const $customerAppointment = page
|
||||||
.locator('.a_userInfo')
|
.locator('.a_userInfo')
|
||||||
.filter({ hasText: customer.phone })
|
.filter({ hasText: customer.phone })
|
||||||
@ -309,36 +309,6 @@ test.describe('预约状态', () => {
|
|||||||
expect(customerStatus).toEqual(appointmentStatusSetting.SETTLED.name);
|
expect(customerStatus).toEqual(appointmentStatusSetting.SETTLED.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip('预约-过期', async ({ page, createCustomer, appointmentPage, customerPage }) => {
|
|
||||||
// 获取预约时间
|
|
||||||
let setAppointmentTime = appointmentPage.getAppointmentTimesAvailable();
|
|
||||||
|
|
||||||
// 创建顾客
|
|
||||||
const customer = createCustomer;
|
|
||||||
// 员工赵军
|
|
||||||
const employee = staffData.firstStore.firstSector.employee_5;
|
|
||||||
// 预约时间定位器
|
|
||||||
const $time = page.locator('.times_table td').filter({ hasText: setAppointmentTime });
|
|
||||||
// 员工定位器
|
|
||||||
const $employee = page.locator('.room_table .tr .name_th').filter({ hasText: employee.name });
|
|
||||||
|
|
||||||
await test.step('选择顾客进行预约', async () => {
|
|
||||||
await $employee.scrollIntoViewIfNeeded();
|
|
||||||
await $time.scrollIntoViewIfNeeded();
|
|
||||||
await appointmentPage.openAppointmentCell(employee.name);
|
|
||||||
await expect(async () => {
|
|
||||||
await appointmentPage.operationAppointment(AppointmentOperation.ADD_APPOINT);
|
|
||||||
await expect(page.getByText('选择会员')).toBeVisible();
|
|
||||||
}).toPass();
|
|
||||||
await customerPage.searchCustomer(customer.phone);
|
|
||||||
await customerPage.selectSearchCustomer(customer.phone);
|
|
||||||
await expect(page.locator('.newAppointmentContent .header_title')).toContainText('新建预约');
|
|
||||||
await expect(page.locator('.newAppointmentContent .content .phone')).toContainText(customer.phone);
|
|
||||||
await page.getByRole('button', { name: '确认新建' }).click();
|
|
||||||
await expect(page.locator('.ant-message', { hasText: '预约成功' })).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test.afterEach(async ({ homeNavigation, wasteBookBusinessRecordPage, billSet }) => {
|
test.afterEach(async ({ homeNavigation, wasteBookBusinessRecordPage, billSet }) => {
|
||||||
|
|||||||
@ -5,11 +5,12 @@ import { decodeQR, KeepOnlyNumbers } from '@/utils/utils.js';
|
|||||||
import { faker } from '@faker-js/faker/locale/zh_CN';
|
import { faker } from '@faker-js/faker/locale/zh_CN';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { AppointmentOperation } from '@/pages/appointmentPage.js';
|
import { AppointmentOperation } from '@/pages/appointmentPage.js';
|
||||||
|
import { Customer } from '@/utils/customer';
|
||||||
|
|
||||||
test.describe('挂单', () => {
|
test.describe('挂单', () => {
|
||||||
let c;
|
let c: Customer;
|
||||||
let username;
|
let username: string;
|
||||||
let phone;
|
let phone: string;
|
||||||
test.beforeEach('测试前新建会员', async ({ page, homeNavigation, createCustomer, customerPage }) => {
|
test.beforeEach('测试前新建会员', async ({ page, homeNavigation, createCustomer, customerPage }) => {
|
||||||
// 创建顾客
|
// 创建顾客
|
||||||
c = createCustomer;
|
c = createCustomer;
|
||||||
@ -423,8 +424,7 @@ test.describe('挂单', () => {
|
|||||||
await page.locator('.qrcode').screenshot({ path: filePath });
|
await page.locator('.qrcode').screenshot({ path: filePath });
|
||||||
}).toPass();
|
}).toPass();
|
||||||
|
|
||||||
/**@type {string} 解析后的网址 */
|
let result: string = await decodeQR(filePath);
|
||||||
let result = await decodeQR(filePath);
|
|
||||||
console.log(result);
|
console.log(result);
|
||||||
|
|
||||||
let url_1 = new URL(result);
|
let url_1 = new URL(result);
|
||||||
@ -760,8 +760,7 @@ test.describe('收银-房态', () => {
|
|||||||
const setAppointment = appointmentPage.getAppointmentTimesAvailable(); // 获取当前时间
|
const setAppointment = appointmentPage.getAppointmentTimesAvailable(); // 获取当前时间
|
||||||
const cede = page.locator('.left_table td');
|
const cede = page.locator('.left_table td');
|
||||||
// 找到当前时间的行数
|
// 找到当前时间的行数
|
||||||
/**@type {number} 找到当前时间的行数 */
|
const nowRowTime: number = await cede.allInnerTexts().then(text => {
|
||||||
const nowRowTime = await cede.allInnerTexts().then(text => {
|
|
||||||
return text.findIndex(item => item === setAppointment) + 2;
|
return text.findIndex(item => item === setAppointment) + 2;
|
||||||
});
|
});
|
||||||
// 获取第几列没被占用
|
// 获取第几列没被占用
|
||||||
@ -822,9 +821,7 @@ test.describe('收银-房态', () => {
|
|||||||
const setAppointment = appointmentPage.getAppointmentTimesAvailable(); // 获取当前时间
|
const setAppointment = appointmentPage.getAppointmentTimesAvailable(); // 获取当前时间
|
||||||
const cede = page.locator('.left_table td');
|
const cede = page.locator('.left_table td');
|
||||||
// 找到当前时间的行数
|
// 找到当前时间的行数
|
||||||
// const nowRowTime = await cede.allInnerTexts().then(text => text.indexOf(setAppointment) + 3);
|
const nowRowTime: number = await cede.allInnerTexts().then(text => {
|
||||||
/**@type{number} 找到当前时间的行数 */
|
|
||||||
const nowRowTime = await cede.allInnerTexts().then(text => {
|
|
||||||
return text.findIndex(item => item === setAppointment) + 2;
|
return text.findIndex(item => item === setAppointment) + 2;
|
||||||
});
|
});
|
||||||
// 获取第几列没被占用
|
// 获取第几列没被占用
|
||||||
|
|||||||
@ -97,7 +97,7 @@ test.describe('顾客通用', () => {
|
|||||||
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').click();
|
await page.getByPlaceholder('姓名(拼音首字)、手机号、档案号搜索').click();
|
||||||
await page.locator('.historyALertBox_title', { hasText: '搜索历史' }).waitFor();
|
await page.locator('.historyALertBox_title', { hasText: '搜索历史' }).waitFor();
|
||||||
// 判断搜索历史是否存在
|
// 判断搜索历史是否存在
|
||||||
await expect(page.locator('.historyMemberList_item')).toContainText([@.historySet].reverse());
|
await expect(page.locator('.historyMemberList_item')).toContainText([...historySet].reverse());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1026,8 +1026,7 @@ test.describe('顾客详情', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('操作套餐', async ({ page, homeNavigation, customerPage, createCustomer }) => {
|
test('操作套餐', async ({ page, homeNavigation, customerPage, createCustomer }) => {
|
||||||
/**@type {string} */
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const currentYear = date.getFullYear();
|
const currentYear = date.getFullYear();
|
||||||
const currentMonth = date.getMonth() + 1;
|
const currentMonth = date.getMonth() + 1;
|
||||||
@ -1166,8 +1165,7 @@ test.describe('顾客详情', () => {
|
|||||||
await page.getByRole('button', { name: /确\s认/ }).click();
|
await page.getByRole('button', { name: /确\s认/ }).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**@type {string} 当前单号 */
|
let billNo: string;
|
||||||
let billNo = '';
|
|
||||||
|
|
||||||
await test.step('购买项目并消耗,购买卖品并结算,结算使用优惠券、卡金、赠金、欠款、积分,拿取单号', async () => {
|
await test.step('购买项目并消耗,购买卖品并结算,结算使用优惠券、卡金、赠金、欠款、积分,拿取单号', async () => {
|
||||||
// 左右两侧的支付方式定位器
|
// 左右两侧的支付方式定位器
|
||||||
|
|||||||
@ -361,8 +361,7 @@ test.describe('门店看板', () => {
|
|||||||
// 收银结算button
|
// 收银结算button
|
||||||
const leftPaymentInfoItem = page.locator('.left .paymentmain .paymentInfoItem');
|
const leftPaymentInfoItem = page.locator('.left .paymentmain .paymentInfoItem');
|
||||||
|
|
||||||
/**@type {Customer[]} */
|
let customers: Customer[] = [];
|
||||||
let customers = [];
|
|
||||||
await test.step('创建3个顾客', async () => {
|
await test.step('创建3个顾客', async () => {
|
||||||
customers = await createCustomers(3);
|
customers = await createCustomers(3);
|
||||||
});
|
});
|
||||||
@ -1261,8 +1260,7 @@ test.describe('精细目标', () => {
|
|||||||
let firstStoreFirstSector = staffData.firstStore.firstSector;
|
let firstStoreFirstSector = staffData.firstStore.firstSector;
|
||||||
let firstStoreSecondSector = staffData.firstStore.secondSector;
|
let firstStoreSecondSector = staffData.firstStore.secondSector;
|
||||||
|
|
||||||
/**@type {Customer[]} */
|
let customers: Customer[] = [];
|
||||||
let customers = [];
|
|
||||||
await test.step('创建两个顾客', async () => {
|
await test.step('创建两个顾客', async () => {
|
||||||
customers = await createCustomers(2);
|
customers = await createCustomers(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import { faker } from '@faker-js/faker/locale/zh_CN';
|
|||||||
import { expect, test } from '@/fixtures/boss_common.js';
|
import { expect, test } from '@/fixtures/boss_common.js';
|
||||||
import { CleanPunctuation, getListIndexForTargetElement, KeepOnlyNumbers } from '@/utils/utils.js';
|
import { CleanPunctuation, getListIndexForTargetElement, KeepOnlyNumbers } from '@/utils/utils.js';
|
||||||
import { ProjectName } from '@/fixtures/userconfig.js';
|
import { ProjectName } from '@/fixtures/userconfig.js';
|
||||||
import { Customer } from '@/utils/customer';
|
|
||||||
|
|
||||||
test.describe('出入库管理', () => {
|
test.describe('出入库管理', () => {
|
||||||
test.describe('入库单', () => {
|
test.describe('入库单', () => {
|
||||||
@ -11,8 +10,8 @@ test.describe('出入库管理', () => {
|
|||||||
const remark = '入库' + faker.helpers.fromRegExp(/1[0-9]{4}/);
|
const remark = '入库' + faker.helpers.fromRegExp(/1[0-9]{4}/);
|
||||||
const productA = ProjectName.Product.Product_3;
|
const productA = ProjectName.Product.Product_3;
|
||||||
|
|
||||||
/**@type {number} 产品A余量 */
|
/** 产品A余量 */
|
||||||
let productASurplus;
|
let productASurplus: number;
|
||||||
const quantity1 = 100;
|
const quantity1 = 100;
|
||||||
const quantity2 = 5;
|
const quantity2 = 5;
|
||||||
await test.step('获取入库前数据', async () => {
|
await test.step('获取入库前数据', async () => {
|
||||||
@ -63,8 +62,8 @@ test.describe('出入库管理', () => {
|
|||||||
await expect(page.getByRole('button', { name: '确认入库' })).not.toBeVisible();
|
await expect(page.getByRole('button', { name: '确认入库' })).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**@type {number} 入库单的索引 */
|
/** 入库单的索引 */
|
||||||
let billEntryIndex;
|
let billEntryIndex: number;
|
||||||
await test.step('校验入库单', async () => {
|
await test.step('校验入库单', async () => {
|
||||||
// 根据备注找出入库单在第几行
|
// 根据备注找出入库单在第几行
|
||||||
const codes = page.locator('.table-warp .m-table__body-wrapper .m-table__body tbody tr');
|
const codes = page.locator('.table-warp .m-table__body-wrapper .m-table__body tbody tr');
|
||||||
@ -898,8 +897,7 @@ test.describe('库存管理', () => {
|
|||||||
const productA = ProjectName.Product.Product_2.name;
|
const productA = ProjectName.Product.Product_2.name;
|
||||||
const productNum = ProjectName.Product.Product_2.num;
|
const productNum = ProjectName.Product.Product_2.num;
|
||||||
|
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
await test.step('出库', async () => {
|
await test.step('出库', async () => {
|
||||||
// 点击库存
|
// 点击库存
|
||||||
await homeNavigation.gotoModule('库存');
|
await homeNavigation.gotoModule('库存');
|
||||||
@ -1261,8 +1259,7 @@ test.describe('库存管理', () => {
|
|||||||
|
|
||||||
const customer = createCustomer;
|
const customer = createCustomer;
|
||||||
|
|
||||||
/**@type {string} */
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
await test.step('进行开单购买卖品并寄存', async () => {
|
await test.step('进行开单购买卖品并寄存', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
@ -1338,8 +1335,7 @@ test.describe('统计', async () => {
|
|||||||
|
|
||||||
const quantity1 = 20; //数量
|
const quantity1 = 20; //数量
|
||||||
const UnitPrice = 10; //单价
|
const UnitPrice = 10; //单价
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
let totality;
|
let totality;
|
||||||
let GrossAmount;
|
let GrossAmount;
|
||||||
|
|
||||||
@ -1839,8 +1835,7 @@ test.describe('统计', async () => {
|
|||||||
|
|
||||||
const quantity1 = 20; //数量
|
const quantity1 = 20; //数量
|
||||||
const UnitPrice = 10; //单价
|
const UnitPrice = 10; //单价
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
let totality = 0;
|
let totality = 0;
|
||||||
|
|
||||||
await test.step('获取出库前总数', async () => {
|
await test.step('获取出库前总数', async () => {
|
||||||
@ -1990,7 +1985,7 @@ test.describe('统计', async () => {
|
|||||||
}).toPass({ timeout: 60000 });
|
}).toPass({ timeout: 60000 });
|
||||||
|
|
||||||
// 获取出库后总数
|
// 获取出库后总数
|
||||||
await expect(page.locator('.main-table-body_tr td').nth(5)).toBe(Number(totality) + Number(quantity1));
|
expect(page.locator('.main-table-body_tr td').nth(5)).toBe(Number(totality) + Number(quantity1));
|
||||||
|
|
||||||
// 点击总数进入流水
|
// 点击总数进入流水
|
||||||
await page.locator('.main-table-body_tr td').nth(5).click();
|
await page.locator('.main-table-body_tr td').nth(5).click();
|
||||||
@ -2683,8 +2678,7 @@ test.describe('统计', async () => {
|
|||||||
.then(Number);
|
.then(Number);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
await test.step('顾客开单购买3次项目,并消耗3次项目,选择产品配方3次5ml', async () => {
|
await test.step('顾客开单购买3次项目,并消耗3次项目,选择产品配方3次5ml', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
@ -2806,7 +2800,7 @@ test.describe('调货管理', () => {
|
|||||||
};
|
};
|
||||||
const remarkA = '调货管理' + faker.helpers.fromRegExp(/[a-d]{2}[0-9]{2}/);
|
const remarkA = '调货管理' + faker.helpers.fromRegExp(/[a-d]{2}[0-9]{2}/);
|
||||||
const remarkB = '调货管理' + faker.helpers.fromRegExp(/[a-d]{2}[0-9]{2}/);
|
const remarkB = '调货管理' + faker.helpers.fromRegExp(/[a-d]{2}[0-9]{2}/);
|
||||||
let billA, billB;
|
let billA:string, billB:string;
|
||||||
|
|
||||||
let quantity = 0; // 数量
|
let quantity = 0; // 数量
|
||||||
let outQuantity = 0; // 调出数量
|
let outQuantity = 0; // 调出数量
|
||||||
@ -3310,8 +3304,7 @@ test.describe.serial('盘点', () => {
|
|||||||
let ProductMargin;
|
let ProductMargin;
|
||||||
// 获取单号的ID
|
// 获取单号的ID
|
||||||
let billId;
|
let billId;
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
|
|
||||||
await test.step('记录各自批次数量', async () => {
|
await test.step('记录各自批次数量', async () => {
|
||||||
// 点击库存
|
// 点击库存
|
||||||
@ -3537,8 +3530,7 @@ test.describe.serial('盘点', () => {
|
|||||||
|
|
||||||
// 获取单号的ID
|
// 获取单号的ID
|
||||||
let billId;
|
let billId;
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
|
|
||||||
await test.step('记录各自批次数量', async () => {
|
await test.step('记录各自批次数量', async () => {
|
||||||
// 点击库存
|
// 点击库存
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { Customer } from '@/utils/customer';
|
|||||||
import { staffData } from '@/fixtures/staff.js';
|
import { staffData } from '@/fixtures/staff.js';
|
||||||
import { HomeNavigation } from '@/pages/homeNavigationPage.js';
|
import { HomeNavigation } from '@/pages/homeNavigationPage.js';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
test.describe('商城', () => {
|
test.describe('商城', () => {
|
||||||
test.describe('上架好物', () => {
|
test.describe('上架好物', () => {
|
||||||
@ -1117,8 +1118,8 @@ test.describe('品牌', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('门店排序', async ({ page, homeNavigation }) => {
|
test('门店排序', async ({ page, homeNavigation }) => {
|
||||||
let firstTrStoreName;
|
let firstTrStoreName: string;
|
||||||
let secondTrStoreName;
|
let secondTrStoreName: string;
|
||||||
|
|
||||||
await test.step('进入门店信息', async () => {
|
await test.step('进入门店信息', async () => {
|
||||||
await homeNavigation.gotoModule('营销');
|
await homeNavigation.gotoModule('营销');
|
||||||
@ -1285,8 +1286,7 @@ test.describe('品牌', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/**@type { import("@playwright/test").Page } 初始化页面*/
|
let initPage: Page;
|
||||||
let initPage;
|
|
||||||
test.beforeAll(async ({ browser, baseURL }) => {
|
test.beforeAll(async ({ browser, baseURL }) => {
|
||||||
initPage = await browser.newPage();
|
initPage = await browser.newPage();
|
||||||
const homeNavigation = new HomeNavigation(initPage);
|
const homeNavigation = new HomeNavigation(initPage);
|
||||||
@ -1336,7 +1336,7 @@ test.describe('品牌', () => {
|
|||||||
|
|
||||||
test.describe('个性化', () => {
|
test.describe('个性化', () => {
|
||||||
test('配色', async ({ page, homeNavigation }) => {
|
test('配色', async ({ page, homeNavigation }) => {
|
||||||
let colorArray;
|
let colorArray: string[];
|
||||||
|
|
||||||
await test.step('进入个性化装扮', async () => {
|
await test.step('进入个性化装扮', async () => {
|
||||||
await homeNavigation.gotoModule('营销');
|
await homeNavigation.gotoModule('营销');
|
||||||
@ -1701,8 +1701,7 @@ test.describe('邀客系统', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('邀客管理', async ({ page, homeNavigation, tablePage, customerPage, createCustomers, marketingPage }) => {
|
test('邀客管理', async ({ page, homeNavigation, tablePage, customerPage, createCustomers, marketingPage }) => {
|
||||||
/**@type {Customer[]} */
|
let customers: Customer[] = [];
|
||||||
let customers = [];
|
|
||||||
await test.step('创建顾客', async () => {
|
await test.step('创建顾客', async () => {
|
||||||
customers = await createCustomers(2);
|
customers = await createCustomers(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -817,8 +817,7 @@ test.describe('对账流水', () => {
|
|||||||
test('根据条件搜索对账流水', async ({ page, homeNavigation, createCustomer, wasteBookBusinessRecordPage }) => {
|
test('根据条件搜索对账流水', async ({ page, homeNavigation, createCustomer, wasteBookBusinessRecordPage }) => {
|
||||||
const customer = createCustomer;
|
const customer = createCustomer;
|
||||||
const project = { no: '100018', name: '苹果精萃护理', shortName: '精萃护理', price: '980' };
|
const project = { no: '100018', name: '苹果精萃护理', shortName: '精萃护理', price: '980' };
|
||||||
/**@type {string} 单号*/
|
let billNo: string;
|
||||||
let billNo;
|
|
||||||
await test.step('选择顾客开单,结算使用银联、支付宝、微信、欠款、现金', async () => {
|
await test.step('选择顾客开单,结算使用银联、支付宝、微信、欠款、现金', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
await page.getByRole('button', { name: /开\s单/ }).click();
|
await page.getByRole('button', { name: /开\s单/ }).click();
|
||||||
@ -930,8 +929,7 @@ test.describe('对账流水', () => {
|
|||||||
|
|
||||||
const customer = createCustomer;
|
const customer = createCustomer;
|
||||||
|
|
||||||
/**@type {string} 单号*/
|
let billNo:string;
|
||||||
let billNo;
|
|
||||||
|
|
||||||
await test.step('选择顾客开单,结算使用银联、支付宝、微信、欠款、现金', async () => {
|
await test.step('选择顾客开单,结算使用银联、支付宝、微信、欠款、现金', async () => {
|
||||||
await homeNavigation.gotoModule('收银');
|
await homeNavigation.gotoModule('收银');
|
||||||
@ -1000,7 +998,7 @@ test.describe('对账流水', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// 拿取现金列的列数
|
// 拿取现金列的列数
|
||||||
let index;
|
let index: number;
|
||||||
const thLocator = page.locator('.m-table__header tr').last().locator('th');
|
const thLocator = page.locator('.m-table__header tr').last().locator('th');
|
||||||
const headers = await thLocator.allInnerTexts();
|
const headers = await thLocator.allInnerTexts();
|
||||||
index = headers.findIndex(headerText => headerText.includes('支付方式'));
|
index = headers.findIndex(headerText => headerText.includes('支付方式'));
|
||||||
|
|||||||
@ -1,56 +1,50 @@
|
|||||||
export async function readIndexedDB() {
|
export async function readIndexedDB() {
|
||||||
const databases = await indexedDB.databases();
|
const databases = await indexedDB.databases();
|
||||||
const allData: Array<{ databaseName: string; data: { key: IDBValidKey; value: any }[] }> = [];
|
const allData = [];
|
||||||
|
|
||||||
for (const db of databases) {
|
for (const db of databases) {
|
||||||
const databaseName = db.name!;
|
const databaseName = db.name;
|
||||||
|
|
||||||
try {
|
// 打开数据库
|
||||||
const dbInstance = await openDatabase(databaseName);
|
|
||||||
const transaction = dbInstance.transaction(dbInstance.objectStoreNames, 'readonly');
|
|
||||||
const objectStore = transaction.objectStore(dbInstance.objectStoreNames[0]);
|
|
||||||
const storeData = await getAllDataFromObjectStore(objectStore);
|
|
||||||
|
|
||||||
allData.push({
|
|
||||||
databaseName,
|
|
||||||
data: storeData,
|
|
||||||
});
|
|
||||||
|
|
||||||
dbInstance.close();
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error reading database ${databaseName}:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allData;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openDatabase(databaseName: string): Promise<IDBDatabase> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const request = indexedDB.open(databaseName);
|
const request = indexedDB.open(databaseName);
|
||||||
|
|
||||||
request.onsuccess = event => resolve(event.target.result);
|
const databaseData = await new Promise((resolve, reject) => {
|
||||||
request.onerror = event => reject(event.target.error);
|
request.onsuccess = (event) => {
|
||||||
});
|
const db = event.target.result;
|
||||||
}
|
const transaction = db.transaction(db.objectStoreNames, 'readonly');
|
||||||
|
const objectStore = transaction.objectStore(db.objectStoreNames[0]);
|
||||||
function getAllDataFromObjectStore(objectStore: IDBObjectStore): Promise<Array<{ key: IDBValidKey; value: any }>> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const storeData: Array<{ key: IDBValidKey; value: any }> = [];
|
|
||||||
const cursorRequest = objectStore.openCursor();
|
const cursorRequest = objectStore.openCursor();
|
||||||
|
|
||||||
cursorRequest.onsuccess = event => {
|
const storeData = [];
|
||||||
|
|
||||||
|
cursorRequest.onsuccess = (event) => {
|
||||||
const cursor = event.target.result;
|
const cursor = event.target.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
storeData.push({ key: cursor.key, value: cursor.value });
|
storeData.push({ key: cursor.key, value: cursor.value });
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else {
|
} else {
|
||||||
resolve(storeData);
|
resolve(storeData); // 执行 resolve,返回数据
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cursorRequest.onerror = event => reject(event.target.error);
|
cursorRequest.onerror = (event) => {
|
||||||
|
reject(event.target.error); // 发生错误时 reject
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = (event) => {
|
||||||
|
reject(event.target.error); // 发生错误时 reject
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 将数据库数据存入 allData
|
||||||
|
allData.push({
|
||||||
|
databaseName,
|
||||||
|
data: databaseData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return allData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function writeIndexedDB(jsonData) {
|
export async function writeIndexedDB(jsonData) {
|
||||||
|
|||||||
Reference in New Issue
Block a user