划分美管加、慧来客、智荟宝项目
This commit is contained in:
parent
228c806846
commit
4bca759adb
File diff suppressed because one or more lines are too long
@ -1,111 +0,0 @@
|
||||
{
|
||||
"cookies": [
|
||||
{
|
||||
"name": "realParentShopId",
|
||||
"value": "1063590",
|
||||
"domain": "vip1.meiguanjia.net",
|
||||
"path": "/shair/",
|
||||
"expires": 1763607851.35647,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"value": "mgj",
|
||||
"domain": "vip1.meiguanjia.net",
|
||||
"path": "/shair/",
|
||||
"expires": 1763607851.356543,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "JSESSIONID",
|
||||
"value": "6F73A614C651DB7F8F1F9EC08A03658D",
|
||||
"domain": "vip1.meiguanjia.net",
|
||||
"path": "/shair",
|
||||
"expires": -1,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "shopId",
|
||||
"value": "1063590",
|
||||
"domain": ".meiguanjia.net",
|
||||
"path": "/shair",
|
||||
"expires": -1,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "userId",
|
||||
"value": "1424506",
|
||||
"domain": ".meiguanjia.net",
|
||||
"path": "/shair",
|
||||
"expires": -1,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"value": "%E5%B0%8F%E7%BE%8E%E7%BE%8E%E4%B8%9A",
|
||||
"domain": "vip1.meiguanjia.net",
|
||||
"path": "/shair",
|
||||
"expires": 1729652651,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"value": "de064679-b32a-4617-9135-ca1289f568ae",
|
||||
"domain": ".meiguanjia.net",
|
||||
"path": "/shair",
|
||||
"expires": -1,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "io",
|
||||
"value": "x4_ZagMh7LMUnzzFGbNQ",
|
||||
"domain": "socketlogin.meiguanjia.net",
|
||||
"path": "/",
|
||||
"expires": -1,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"sameSite": "Lax"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "https://vip1.meiguanjia.net",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "CLUSTER",
|
||||
"value": "{\"cluster\":\"vip\",\"existence\":true,\"shopName\":\"小美美业3\",\"list\":[{\"id\":1424506,\"parentShopId\":1063590,\"shopId\":1063590,\"barberId\":null,\"barberName\":null,\"cardTypeId\":null,\"schemeIds\":null,\"cardtypeid\":null,\"softgenre\":null,\"token\":null,\"period\":null,\"startDatetime\":null,\"endDatetime\":null,\"fromHis\":0,\"lastUpdateTime\":null,\"operateStr\":null,\"powerStr\":null,\"descriptionFlag\":0,\"itemIdStr\":null,\"username\":null,\"openid\":null,\"role\":\"3\",\"name\":\"11\",\"roleStr\":null,\"type\":null,\"shopName\":\" \",\"shopIds\":null,\"qyWechatUserid\":null,\"status\":null,\"auditStatus\":null,\"mobile\":\"18900000001\",\"hqName\":\"小美美业3\",\"invaliddate\":1819512000000,\"shopStatus\":\"1\",\"mobileFlag\":false}],\"url\":\"https://vip1.meiguanjia.net/\"}"
|
||||
},
|
||||
{
|
||||
"name": "SHAIR_NEW_MODE",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"name": "renewalLastQueryTime",
|
||||
"value": "1729047852587"
|
||||
},
|
||||
{
|
||||
"name": "themeConfig",
|
||||
"value": "1063590"
|
||||
},
|
||||
{
|
||||
"name": "mgjversion",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
4
.env
4
.env
@ -6,7 +6,9 @@ SMSCODE=1660
|
||||
|
||||
ZHB_ACCOUNT=18571458300
|
||||
ZHB_PASSWORD=1
|
||||
ZHB_BASE_URL="https://shengyibao.meiguanjia.net/shair/components/shair-web/base-system/index.html#"
|
||||
# ZHB_BASE_URL="https://shengyibao.meiguanjia.net/shair/components/shair-web/base-system/index.html#"
|
||||
ZHB_BASE_URL="https://shengyibao.meiguanjia.net/young/"
|
||||
|
||||
|
||||
MGJ_ACCOUNT=小美美业
|
||||
MGJ_PASSWORD=1
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@ node_modules/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
.auth/
|
||||
|
||||
|
||||
24
package-lock.json
generated
24
package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.0.3",
|
||||
"@playwright/test": "^1.48.0",
|
||||
"@playwright/test": "^1.48.1",
|
||||
"@types/node": "^22.7.5",
|
||||
"dotenv": "^16.4.5"
|
||||
}
|
||||
@ -33,13 +33,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.48.0",
|
||||
"resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.48.0.tgz",
|
||||
"integrity": "sha512-W5lhqPUVPqhtc/ySvZI5Q8X2ztBOUgZ8LbAFy0JQgrXZs2xaILrUcNO3rQjwbLPfGK13+rZsDa1FpG+tqYkT5w==",
|
||||
"version": "1.48.1",
|
||||
"resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.48.1.tgz",
|
||||
"integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.48.0"
|
||||
"playwright": "1.48.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -87,13 +87,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.48.0",
|
||||
"resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.48.0.tgz",
|
||||
"integrity": "sha512-qPqFaMEHuY/ug8o0uteYJSRfMGFikhUysk8ZvAtfKmUK3kc/6oNl/y3EczF8OFGYIi/Ex2HspMfzYArk6+XQSA==",
|
||||
"version": "1.48.1",
|
||||
"resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.48.1.tgz",
|
||||
"integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.48.0"
|
||||
"playwright-core": "1.48.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -106,9 +106,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.48.0",
|
||||
"resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.48.0.tgz",
|
||||
"integrity": "sha512-RBvzjM9rdpP7UUFrQzRwR8L/xR4HyC1QXMzGYTbf1vjw25/ya9NRAVnXi/0fvFopjebvyPzsmoK58xxeEOaVvA==",
|
||||
"version": "1.48.1",
|
||||
"resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.48.1.tgz",
|
||||
"integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
||||
34
package.json
34
package.json
@ -1,19 +1,21 @@
|
||||
{
|
||||
"name": "playwright-demo",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"codegen": "npx playwright codegen",
|
||||
"name": "playwright-demo",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"hlk_codegen": "npx playwright codegen https://hlk.meiguanjia.net/#/",
|
||||
"mgj_codegen": "npx playwright codegen https://vip1.meiguanjia.net/shair/?v=mgj",
|
||||
"zhb_codegen": "npx playwright codegen https://shengyibao.meiguanjia.net/young/",
|
||||
"ui": "npx playwright test --ui"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.0.3",
|
||||
"@playwright/test": "^1.48.0",
|
||||
"@types/node": "^22.7.5",
|
||||
"dotenv": "^16.4.5"
|
||||
}
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.0.3",
|
||||
"@playwright/test": "^1.48.1",
|
||||
"@types/node": "^22.7.5",
|
||||
"dotenv": "^16.4.5"
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,9 @@ const path = require('path');
|
||||
|
||||
// Read from ".env" file.
|
||||
dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
const adminAuthFile = path.join(__dirname, '../.auth/admin.json');
|
||||
const zhbAuthFile = path.join(__dirname, '../.auth/zhb_admin.json');
|
||||
const hlkAuthFile = path.join(__dirname, '.auth/hlk_admin.json');
|
||||
const zhbAuthFile = path.join(__dirname, '.auth/zhb_admin.json');
|
||||
const mgjAuthFile = path.join(__dirname, '.auth/mgj_admin.json');
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
@ -18,79 +19,74 @@ const zhbAuthFile = path.join(__dirname, '../.auth/zhb_admin.json');
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
module.exports = defineConfig({
|
||||
testDir: './tests',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.BASE_URL,
|
||||
timezoneId: 'Asia/Shanghai',
|
||||
locale: 'zh-CN',
|
||||
geolocation: { longitude: 114.24, latitude: 22.73 },
|
||||
permissions: ['geolocation'],
|
||||
extraHTTPHeaders: {
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
},
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
testDir: './tests',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.BASE_URL,
|
||||
timezoneId: 'Asia/Shanghai',
|
||||
locale: 'zh-CN',
|
||||
geolocation: { longitude: 114.24, latitude: 22.73 },
|
||||
permissions: ['geolocation'],
|
||||
extraHTTPHeaders: {
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
},
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{ name: 'hlk_setup', testMatch: /.*\.setup\.js/ },
|
||||
{ name: 'zhb_setup', testMatch: /.*\.setup\.js/ },
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'], storageState: adminAuthFile },
|
||||
dependencies: ['hlk_setup'],
|
||||
},
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{ name: 'hlk_setup', use: { baseURL: process.env.BASE_URL }, testMatch: /hlk\.setup\.js/ },
|
||||
{ name: 'zhb_setup', use: { baseURL: process.env.ZHB_BASE_URL }, testMatch: /zhb\.setup\.js/ },
|
||||
{ name: 'mgj_setup', use: { baseURL: process.env.MGJ_BASE_URL }, testMatch: /mgj\.setup\.js/ },
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
baseURL: process.env.BASE_URL,
|
||||
...devices['Desktop Chrome'],
|
||||
storageState: hlkAuthFile,
|
||||
},
|
||||
testMatch: '**/tests/hlk/**.spec.js',
|
||||
dependencies: ['hlk_setup'],
|
||||
},
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'], storageState: adminAuthFile },
|
||||
dependencies: ['hlk_setup'],
|
||||
},
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
baseURL: process.env.ZHB_BASE_URL,
|
||||
...devices['Desktop Chrome'],
|
||||
storageState: zhbAuthFile,
|
||||
},
|
||||
testMatch: '**/tests/zhb/**.spec.js',
|
||||
dependencies: ['zhb_setup'],
|
||||
},
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
baseURL: process.env.MGJ_BASE_URL,
|
||||
...devices['Desktop Chrome'],
|
||||
storageState: mgjAuthFile,
|
||||
},
|
||||
testMatch: '**/tests/mgj/**.spec.js',
|
||||
dependencies: ['mgj_setup'],
|
||||
},
|
||||
],
|
||||
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'], storageState: adminAuthFile },
|
||||
dependencies: ['zhb_setup'],
|
||||
},
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: { ...devices['Pixel 5'] },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: { ...devices['iPhone 12'] },
|
||||
// },
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||
// },
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
// command: 'npm run start',
|
||||
// url: 'http://127.0.0.1:3000',
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
// command: 'npm run start',
|
||||
// url: 'http://127.0.0.1:3000',
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
});
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
const { test: setup, expect } = require('@playwright/test');
|
||||
const path = require('path');
|
||||
const authFile = path.join(__dirname, '../.auth/admin.json');
|
||||
const zhbAuthFile = path.join(__dirname, '../.auth/zhb_admin.json');
|
||||
const mgjAuthFile = path.join(__dirname, '../.auth/mgj_admin.json');
|
||||
|
||||
setup('hlk总部管理员登录', async ({ page, baseURL }) => {
|
||||
const $account = page.getByRole('textbox', { name: '请输入您的手机号码' });
|
||||
const $password = page.getByRole('textbox', { name: '请输入登录密码' });
|
||||
const $loginBtn = page.getByRole('button', { name: /登\s录/ });
|
||||
|
||||
const account = process.env.ACCOUNT;
|
||||
const password = process.env.PASSWORD;
|
||||
|
||||
await page.goto(baseURL);
|
||||
await $account.fill(account);
|
||||
const phoneStatsIcon = page.locator('.ant-row', { has: $account }).locator('.pass_svg');
|
||||
await $password.fill(password);
|
||||
await page.getByLabel('请同意慧来客隐私政策和用户协议').check();
|
||||
await expect(phoneStatsIcon).toBeVisible();
|
||||
await $loginBtn.click();
|
||||
await expect(page.getByRole('button', { name: /开\s单/ })).toBeVisible();
|
||||
await page.context().storageState({ path: authFile });
|
||||
});
|
||||
|
||||
setup('zhb总部管理员登录', async ({ page }) => {
|
||||
const baseURL = process.env.ZHB_BASE_URL;
|
||||
const account = process.env.ZHB_ACCOUNT;
|
||||
const password = process.env.ZHB_PASSWORD;
|
||||
|
||||
const $account = page.getByPlaceholder('账户');
|
||||
const $password = page.getByPlaceholder('密码');
|
||||
const $loginBtn = page.getByRole('button', { name: /登\s录/ });
|
||||
|
||||
await page.goto(baseURL);
|
||||
await $account.fill(account);
|
||||
await $password.fill(password);
|
||||
await $loginBtn.click();
|
||||
await expect(page.getByRole('heading', { name: '收银' })).toBeVisible();
|
||||
await page.context().storageState({ path: zhbAuthFile });
|
||||
});
|
||||
|
||||
setup('mgj管理员登录', async ({ page }) => {
|
||||
const baseURL = process.env.MGJ_BASE_URL;
|
||||
const account = process.env.MGJ_ACCOUNT;
|
||||
const password = process.env.MGJ_PASSWORD;
|
||||
|
||||
await page.goto(baseURL);
|
||||
await page.getByPlaceholder('请输入您的用户名').fill(account);
|
||||
await page.getByPlaceholder('请输入密码').fill(password);
|
||||
await page.getByText('登录', { exact: true }).click();
|
||||
await expect(page.getByRole('link', { name: '管理层' })).toBeVisible();
|
||||
await page.context().storageState({ path: mgjAuthFile });
|
||||
});
|
||||
@ -1,73 +0,0 @@
|
||||
const { test, expect } = require('./fixtures/common');
|
||||
const { Customer } = require('./customer');
|
||||
const { faker } = require('@faker-js/faker/locale/zh_CN');
|
||||
|
||||
// test('has title', async ({ page }) => {
|
||||
// await page.goto('https://playwright.dev/');
|
||||
|
||||
// // Expect a title "to contain" a substring.
|
||||
// await expect(page).toHaveTitle(/Playwright/);
|
||||
// });
|
||||
|
||||
// test('get started link', async ({ page }) => {
|
||||
// await page.goto('https://playwright.dev/');
|
||||
|
||||
// // Click the get started link.
|
||||
// await page.getByRole('link', { name: 'Get started' }).click();
|
||||
|
||||
// // Expects page to have a heading with the name of Installation.
|
||||
// await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
|
||||
// });
|
||||
test('登录touch和h5,创建顾客购买会员卡,使用顾客账号到h5商城购买货品', async ({
|
||||
touchPage,
|
||||
h5Page,
|
||||
touchCustomerPage,
|
||||
h5LoginPage,
|
||||
}) => {
|
||||
const phone = faker.helpers.fromRegExp(/1[3-9][0-1]{9}/);
|
||||
const customer = new Customer(1, 1, { phone: phone });
|
||||
await touchCustomerPage.createCustomer(customer);
|
||||
|
||||
await test.step('在touch页面购买会员卡', async () => {
|
||||
await touchPage.getByText('去开单').click();
|
||||
await touchPage.locator('.more > .icon > svg').click();
|
||||
await touchPage.getByText('去开卡').click();
|
||||
const $firstCard = touchPage.locator('.memberCard_box').first();
|
||||
await $firstCard.click();
|
||||
const cardName = await $firstCard.locator('.card_name').innerText();
|
||||
await touchPage.getByRole('button', { name: '去结算' }).click();
|
||||
await touchPage.locator('.row').filter({ hasText: '总额' }).locator('.touchIcon').click();
|
||||
await touchPage.getByPlaceholder('请输入内容').fill('1000');
|
||||
await touchPage.locator('div').filter({ hasText: /^789$/ }).getByRole('button').nth(3).click();
|
||||
await touchPage.locator('.paymentInfoItem', { hasText: '现金' }).click();
|
||||
await touchPage.getByText('推送消费提醒').click();
|
||||
await touchPage.getByLabel('结算签字').uncheck();
|
||||
await touchPage.getByRole('button', { name: /结\s算/ }).click();
|
||||
await touchPage.getByRole('button', { name: /跳\s过/ }).click();
|
||||
});
|
||||
|
||||
await test.step('登录h5,并且商城页面使用会员卡进行购买', async () => {
|
||||
await h5LoginPage.login(customer.phone);
|
||||
await h5Page.locator('.singIn_content > .iconfont').click();
|
||||
await h5Page.locator('.get_btn').click();
|
||||
await h5Page.locator('.back').click();
|
||||
await h5Page.locator('.bar_item', { hasText: '商城' }).click();
|
||||
await expect(h5Page.locator('.title', { hasText: '商城' })).toBeVisible();
|
||||
await h5Page.locator('.li span', { hasText: '全部' }).click();
|
||||
await h5Page.locator('.p-item').first().click();
|
||||
await h5Page.waitForLoadState();
|
||||
await h5Page.getByText('立即购买').click();
|
||||
await h5Page
|
||||
.locator('.goodsClassBoxMain .footerBug_true_all')
|
||||
.filter({ hasText: '确定' })
|
||||
.click();
|
||||
await h5Page.locator('.mgj-picker-head .mgj-picker-btn').filter({ hasText: '确认' }).click();
|
||||
await expect(h5Page.locator('.pay-way .form_row', { hasText: cardName })).toHaveClass(
|
||||
/click-able/
|
||||
);
|
||||
await expect(h5Page.getByText('确认支付')).toBeEnabled();
|
||||
await h5Page.getByText('确认支付').click();
|
||||
await expect(h5Page.getByText('支付成功').first()).toBeVisible();
|
||||
await expect(h5Page.getByText('查看订单')).toBeVisible();
|
||||
});
|
||||
});
|
||||
51
tests/fixtures/base.js
vendored
51
tests/fixtures/base.js
vendored
@ -1,51 +0,0 @@
|
||||
const { test: base, expect, devices } = require('@playwright/test');
|
||||
const path = require('path');
|
||||
const authFile = path.resolve(__dirname, '../../.auth/admin.json');
|
||||
const zhbAuthFile = path.join(__dirname, '../.auth/zhb_admin.json');
|
||||
|
||||
const test = base.extend({
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
touchPage: async ({ browser, baseURL }, use) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: authFile,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL);
|
||||
await use(page);
|
||||
await page.close();
|
||||
await context.close();
|
||||
},
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
h5Page: async ({ browser }, use) => {
|
||||
const iPhone = devices['iPhone 11'];
|
||||
const context = await browser.newContext({
|
||||
...iPhone,
|
||||
storageState: undefined,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(process.env.H5_BASE_URL);
|
||||
await use(page);
|
||||
},
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
zhbPage: async ({ browser, baseURL }, use) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: zhbAuthFile,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL);
|
||||
await use(page);
|
||||
await page.close();
|
||||
await context.close();
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
test,
|
||||
expect,
|
||||
};
|
||||
67
tests/hlk/demo.spec.js
Normal file
67
tests/hlk/demo.spec.js
Normal file
@ -0,0 +1,67 @@
|
||||
const { test, expect } = require('./fixtures/common');
|
||||
const { Customer } = require('./pom/hlk/customer');
|
||||
const { faker } = require('@faker-js/faker/locale/zh_CN');
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
test(`登录touch和h5,创建顾客购买会员卡,使用顾客账号到h5商城购买货品${i}`, async ({
|
||||
touchPage,
|
||||
h5Page,
|
||||
touchCustomerPage,
|
||||
h5LoginPage,
|
||||
}) => {
|
||||
const phone = faker.helpers.fromRegExp(/1[3-9][0-1]{9}/);
|
||||
const customer = new Customer(1, 1, { phone: phone });
|
||||
|
||||
await touchCustomerPage.createCustomer(customer);
|
||||
let cardName;
|
||||
await test.step('在touch页面购买会员卡', async () => {
|
||||
await touchPage.getByText('去开单').click();
|
||||
await touchPage.locator('.more > .icon > svg').click();
|
||||
await touchPage.getByText('去开卡').click();
|
||||
const $firstCard = touchPage.locator('.memberCard_box').first();
|
||||
await $firstCard.click();
|
||||
cardName = await $firstCard.locator('.card_name').innerText();
|
||||
await touchPage.getByRole('button', { name: '去结算' }).click();
|
||||
await touchPage.locator('.row').filter({ hasText: '总额' }).locator('.touchIcon').click();
|
||||
await touchPage.getByPlaceholder('请输入内容').fill('1000');
|
||||
await touchPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^789$/ })
|
||||
.getByRole('button')
|
||||
.nth(3)
|
||||
.click();
|
||||
await touchPage.locator('.paymentInfoItem', { hasText: '现金' }).click();
|
||||
await touchPage.getByText('推送消费提醒').click();
|
||||
await touchPage.getByLabel('结算签字').uncheck();
|
||||
await touchPage.getByRole('button', { name: /结\s算/ }).click();
|
||||
await touchPage.getByRole('button', { name: /跳\s过/ }).click();
|
||||
});
|
||||
|
||||
await test.step('登录h5,并且商城页面使用会员卡进行购买', async () => {
|
||||
await h5LoginPage.login(customer.phone);
|
||||
await h5Page.locator('.singIn_content > .iconfont').click();
|
||||
await h5Page.locator('.get_btn').click();
|
||||
await h5Page.locator('.back').click();
|
||||
await h5Page.locator('.bar_item', { hasText: '商城' }).click();
|
||||
await expect(h5Page.locator('.title', { hasText: '商城' })).toBeVisible();
|
||||
await h5Page.locator('.li span', { hasText: '全部' }).click();
|
||||
await h5Page.locator('.p-item').first().click();
|
||||
await h5Page.waitForLoadState();
|
||||
await h5Page.getByText('立即购买').click();
|
||||
await h5Page
|
||||
.locator('.goodsClassBoxMain .footerBug_true_all')
|
||||
.filter({ hasText: '确定' })
|
||||
.click();
|
||||
await h5Page.locator('.mgj-picker-head .mgj-picker-btn').filter({ hasText: '确认' }).click();
|
||||
await expect(
|
||||
h5Page
|
||||
.locator('.pay-way .form_row', { hasText: cardName })
|
||||
.locator('.radio_btn .uni-radio-input')
|
||||
).toHaveClass(/uni-radio-input-checked/);
|
||||
await expect(h5Page.getByText('确认支付')).toBeEnabled();
|
||||
await h5Page.getByText('确认支付').click();
|
||||
await expect(h5Page.getByText('支付成功').first()).toBeVisible();
|
||||
await expect(h5Page.getByText('查看订单')).toBeVisible();
|
||||
});
|
||||
});
|
||||
}
|
||||
38
tests/hlk/fixtures/base.js
Normal file
38
tests/hlk/fixtures/base.js
Normal file
@ -0,0 +1,38 @@
|
||||
const { test: base, expect, devices } = require('@playwright/test');
|
||||
const authFile = '.auth/hlk_admin.json';
|
||||
|
||||
const test = base.extend({
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
touchPage: async ({ browser, baseURL }, use) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: authFile,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL);
|
||||
|
||||
await use(page);
|
||||
|
||||
await page.close();
|
||||
await context.close();
|
||||
},
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
h5Page: async ({ browser }, use) => {
|
||||
const iPhone = devices['iPhone 11'];
|
||||
const context = await browser.newContext({
|
||||
...iPhone,
|
||||
storageState: undefined,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(process.env.H5_BASE_URL);
|
||||
await use(page);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
test,
|
||||
expect,
|
||||
};
|
||||
@ -1,5 +1,5 @@
|
||||
const { test: base, expect } = require('./base');
|
||||
const { H5LoginPage } = require('../pages/h5LoginPage');
|
||||
const { H5LoginPage } = require('../pom/hlk/h5LoginPage');
|
||||
|
||||
const test = base.extend({
|
||||
/**
|
||||
@ -1,5 +1,5 @@
|
||||
const { test: base, expect } = require('./base');
|
||||
const { CustomerPage } = require('../pages/customerPage');
|
||||
const { CustomerPage } = require('../pom/hlk/customerPage');
|
||||
|
||||
const test = base.extend({
|
||||
/**
|
||||
@ -1,6 +1,6 @@
|
||||
//@ts-check
|
||||
const { expect } = require('@playwright/test');
|
||||
const { Customer } = require('../customer');
|
||||
const { Customer } = require('./customer');
|
||||
|
||||
class CustomerPage {
|
||||
/**
|
||||
97
tests/mgj/demo.spec.js
Normal file
97
tests/mgj/demo.spec.js
Normal file
@ -0,0 +1,97 @@
|
||||
const { test, expect } = require('./fixture/common');
|
||||
const { Customer } = require('./pom/customerPage');
|
||||
|
||||
test('demo', async ({ zhbPage, customerPage }) => {
|
||||
const $area = zhbPage
|
||||
.locator('.area')
|
||||
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
|
||||
const $$room = $area.locator('.room-list .room');
|
||||
|
||||
await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
|
||||
const customer = new Customer();
|
||||
await customerPage.createCustomer(customer);
|
||||
|
||||
let useRoomName;
|
||||
await test.step('购买商品', async () => {
|
||||
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
|
||||
const $emptyRoom = $$room.filter({ has: zhbPage.getByText('空房') }).first();
|
||||
useRoomName = await $emptyRoom.locator('.roomName').innerText();
|
||||
expect(useRoomName).not.toBeNull();
|
||||
await $emptyRoom.click();
|
||||
await expect(async () => {
|
||||
await zhbPage.getByRole('button', { name: '选择顾客' }).click();
|
||||
await expect(zhbPage.locator('#page_searchMember').getByText('创建会员')).toBeVisible();
|
||||
}).toPass();
|
||||
await zhbPage
|
||||
.getByRole('textbox', { name: '输入会员手机号或姓名或卡号搜索' })
|
||||
.fill(customer.phone, { delay: 100 });
|
||||
await zhbPage.locator('#page_searchMember svg').click();
|
||||
|
||||
const $customerTr = zhbPage
|
||||
.locator('.list-warp')
|
||||
.filter({ has: zhbPage.locator('.name', { hasText: customer.name }) });
|
||||
await $customerTr.locator('.list-body').first().click();
|
||||
|
||||
await zhbPage.getByText('项目开单').click();
|
||||
await expect(zhbPage.locator('#page_roomDetail').getByText('服务项目')).toBeVisible();
|
||||
await zhbPage.getByText('选择', { exact: true }).nth(1).click();
|
||||
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
|
||||
await zhbPage.getByText('臻品足疗 (10101)').click();
|
||||
await zhbPage.locator('#serviceSelector').getByText('确认').click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^匠星足浴$/ })
|
||||
.locator('span')
|
||||
.first()
|
||||
.click();
|
||||
await zhbPage.getByRole('button', { name: '完成开单' }).click();
|
||||
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible();
|
||||
await zhbPage.getByRole('button', { name: '结账' }).click();
|
||||
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
|
||||
|
||||
await expect(async () => {
|
||||
await zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' }).click();
|
||||
await expect(zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' })).toHaveClass(
|
||||
/selected/
|
||||
);
|
||||
await zhbPage
|
||||
.locator('#page_footBathPay span')
|
||||
.filter({ hasText: /结\s算/ })
|
||||
.click();
|
||||
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
|
||||
}).toPass();
|
||||
|
||||
await zhbPage.getByText('不想评价').click();
|
||||
await expect(zhbPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('起钟下钟,清理房间', async () => {
|
||||
const $cleanRoom = $$room.filter({
|
||||
has: zhbPage.locator('.roomName', { hasText: new RegExp(`^${useRoomName}$`) }),
|
||||
});
|
||||
await expect($cleanRoom).toContainText('已结清');
|
||||
await $cleanRoom.click();
|
||||
await zhbPage.getByText('技师操作').click();
|
||||
await zhbPage.getByText('起钟', { exact: true }).click();
|
||||
await zhbPage.getByText('起钟成功!').click();
|
||||
await zhbPage.getByText('技师操作').click();
|
||||
await zhbPage.getByText('下钟', { exact: true }).click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^确认返回$/ })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await zhbPage.getByRole('button', { name: '不需要' }).click();
|
||||
|
||||
await expect($cleanRoom).toContainText('打扫');
|
||||
await $cleanRoom.click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^确定取消$/ })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await expect($cleanRoom).toContainText('空房');
|
||||
});
|
||||
});
|
||||
25
tests/mgj/fixture/base.js
Normal file
25
tests/mgj/fixture/base.js
Normal file
@ -0,0 +1,25 @@
|
||||
const { test: base, expect } = require('@playwright/test');
|
||||
const authFile = '.auth/mgj_admin.json';
|
||||
const test = base.extend({
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
mgjPage: async ({ browser, baseURL }, use) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: authFile,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL);
|
||||
console.log(baseURL);
|
||||
|
||||
await use(page);
|
||||
|
||||
await page.close();
|
||||
await context.close();
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
test,
|
||||
expect,
|
||||
};
|
||||
6
tests/mgj/fixture/common.js
Normal file
6
tests/mgj/fixture/common.js
Normal file
@ -0,0 +1,6 @@
|
||||
const { mergeTests } = require('@playwright/test');
|
||||
const { test: customerTest } = require('./customerFixture');
|
||||
|
||||
export const test = mergeTests(customerTest);
|
||||
|
||||
export { expect } from '@playwright/test';
|
||||
12
tests/mgj/fixture/customerFixture.js
Normal file
12
tests/mgj/fixture/customerFixture.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { test as base } from './base';
|
||||
import { CustomerPage } from '../pom/customerPage';
|
||||
|
||||
export const test = base.extend({
|
||||
/**
|
||||
* @type {CustomerPage}
|
||||
*/
|
||||
customerPage: async ({ zhbPage }, use) => {
|
||||
const customerPage = new CustomerPage(zhbPage);
|
||||
await use(customerPage);
|
||||
},
|
||||
});
|
||||
54
tests/mgj/pom/customerPage.js
Normal file
54
tests/mgj/pom/customerPage.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { faker } = require('@faker-js/faker/locale/zh_CN');
|
||||
const { expect } = require('@playwright/test');
|
||||
|
||||
export class Customer {
|
||||
constructor({
|
||||
name = faker.person.fullName(),
|
||||
phone = faker.helpers.fromRegExp(/1[3-9][0-9]{6}/),
|
||||
} = {}) {
|
||||
this.name = name;
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomerPage {
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor(page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建顾客
|
||||
* @param {Customer} customer
|
||||
*/
|
||||
createCustomer = async (customer) => {
|
||||
console.log(customer.name);
|
||||
console.log(customer.phone);
|
||||
|
||||
await expect(this.page.locator('#page_member').getByText('新增顾客档案')).toBeVisible();
|
||||
await this.page.locator('#page_member').getByText('新增顾客档案').click();
|
||||
|
||||
await this.page.getByPlaceholder('请输入会员姓名').fill(customer.name);
|
||||
await this.page.getByPlaceholder('请输入手机号码').click();
|
||||
await expect(this.page.getByText('请输入数字')).toBeVisible();
|
||||
await this.page.getByPlaceholder('在此输入').click();
|
||||
await this.page.keyboard.type(customer.phone, { delay: 100 });
|
||||
// await this.page.getByPlaceholder('在此输入').type(customer.phone, { delay: 100 });
|
||||
await this.page.locator('#maskBoard').getByText('确认').click();
|
||||
await expect(this.page.getByPlaceholder('请输入手机号码')).toHaveValue(customer.phone, {
|
||||
timeout: 2000,
|
||||
});
|
||||
await this.page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^员工带客$/ })
|
||||
.locator('span')
|
||||
.first()
|
||||
.click();
|
||||
await this.page.getByText('创建', { exact: true }).click();
|
||||
await expect(this.page.getByText('用户资料创建成功!')).toBeVisible();
|
||||
await this.page.getByText('以后再说').click();
|
||||
await expect(this.page.getByText('以后再说')).not.toBeVisible();
|
||||
};
|
||||
}
|
||||
22
tests/setup/hlk.setup.js
Normal file
22
tests/setup/hlk.setup.js
Normal file
@ -0,0 +1,22 @@
|
||||
const { test: setup, expect } = require('@playwright/test');
|
||||
const path = require('path');
|
||||
const hlkAuthFile = path.join(__dirname, '../../.auth/hlk_admin.json');
|
||||
|
||||
setup('hlk总部管理员登录', async ({ page, baseURL }) => {
|
||||
const $account = page.getByRole('textbox', { name: '请输入您的手机号码' });
|
||||
const $password = page.getByRole('textbox', { name: '请输入登录密码' });
|
||||
const $loginBtn = page.getByRole('button', { name: /登\s录/ });
|
||||
|
||||
const account = process.env.ACCOUNT;
|
||||
const password = process.env.PASSWORD;
|
||||
|
||||
await page.goto(baseURL);
|
||||
await $account.fill(account);
|
||||
const phoneStatsIcon = page.locator('.ant-row', { has: $account }).locator('.pass_svg');
|
||||
await $password.fill(password);
|
||||
await page.getByLabel('请同意慧来客隐私政策和用户协议').check();
|
||||
await expect(phoneStatsIcon).toBeVisible();
|
||||
await $loginBtn.click();
|
||||
await expect(page.getByRole('button', { name: /开\s单/ })).toBeVisible();
|
||||
await page.context().storageState({ path: hlkAuthFile });
|
||||
});
|
||||
16
tests/setup/mgj.setup.js
Normal file
16
tests/setup/mgj.setup.js
Normal file
@ -0,0 +1,16 @@
|
||||
const { test: setup, expect } = require('@playwright/test');
|
||||
const path = require('path');
|
||||
const mgjAuthFile = path.join(__dirname, '../../.auth/mgj_admin.json');
|
||||
|
||||
|
||||
setup('mgj管理员登录', async ({ page,baseURL }) => {
|
||||
const account = process.env.MGJ_ACCOUNT;
|
||||
const password = process.env.MGJ_PASSWORD;
|
||||
|
||||
await page.goto(baseURL);
|
||||
await page.getByPlaceholder('请输入您的用户名').fill(account);
|
||||
await page.getByPlaceholder('请输入密码').fill(password);
|
||||
await page.getByText('登录', { exact: true }).click();
|
||||
await expect(page.getByRole('link', { name: '管理层' })).toBeVisible();
|
||||
await page.context().storageState({ path: mgjAuthFile });
|
||||
});
|
||||
20
tests/setup/zhb.setup.js
Normal file
20
tests/setup/zhb.setup.js
Normal file
@ -0,0 +1,20 @@
|
||||
const { test: setup, expect } = require('@playwright/test');
|
||||
const path = require('path');
|
||||
const zhbAuthFile = path.join(__dirname, '../../.auth/zhb_admin.json');
|
||||
|
||||
setup('zhb总部管理员登录', async ({ page, baseURL }) => {
|
||||
const account = process.env.ZHB_ACCOUNT;
|
||||
const password = process.env.ZHB_PASSWORD;
|
||||
|
||||
await page.goto(baseURL);
|
||||
await page.getByText('账号登录').click();
|
||||
await page.getByPlaceholder('用户名').fill(account);
|
||||
await page.getByPlaceholder('密码', { exact: true }).fill(password);
|
||||
await page.getByText('登录', { exact: true }).click();
|
||||
await expect(page.getByText('演示一店')).toBeVisible();
|
||||
await expect(page.getByText('演示二店')).toBeVisible();
|
||||
|
||||
await page.getByText('演示一店').click();
|
||||
await expect(page.locator('#tab_main li').filter({ hasText: '营业' })).toBeVisible();
|
||||
await page.context().storageState({ path: zhbAuthFile });
|
||||
});
|
||||
97
tests/zhb/demo.spec.js
Normal file
97
tests/zhb/demo.spec.js
Normal file
@ -0,0 +1,97 @@
|
||||
const { test, expect } = require('./fixture/common');
|
||||
const { Customer } = require('./pom/customerPage');
|
||||
|
||||
test('demo', async ({ zhbPage, customerPage }) => {
|
||||
const $area = zhbPage
|
||||
.locator('.area')
|
||||
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
|
||||
const $$room = $area.locator('.room-list .room');
|
||||
|
||||
await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
|
||||
const customer = new Customer();
|
||||
await customerPage.createCustomer(customer);
|
||||
|
||||
let useRoomName;
|
||||
await test.step('购买商品', async () => {
|
||||
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
|
||||
const $emptyRoom = $$room.filter({ has: zhbPage.getByText('空房') }).first();
|
||||
useRoomName = await $emptyRoom.locator('.roomName').innerText();
|
||||
expect(useRoomName).not.toBeNull();
|
||||
await $emptyRoom.click();
|
||||
await expect(async () => {
|
||||
await zhbPage.getByRole('button', { name: '选择顾客' }).click();
|
||||
await expect(zhbPage.locator('#page_searchMember').getByText('创建会员')).toBeVisible();
|
||||
}).toPass();
|
||||
await zhbPage
|
||||
.getByRole('textbox', { name: '输入会员手机号或姓名或卡号搜索' })
|
||||
.fill(customer.phone, { delay: 100 });
|
||||
await zhbPage.locator('#page_searchMember svg').click();
|
||||
|
||||
const $customerTr = zhbPage
|
||||
.locator('.list-warp')
|
||||
.filter({ has: zhbPage.locator('.name', { hasText: customer.name }) });
|
||||
await $customerTr.locator('.list-body').first().click();
|
||||
|
||||
await zhbPage.getByText('项目开单').click();
|
||||
await expect(zhbPage.locator('#page_roomDetail').getByText('服务项目')).toBeVisible();
|
||||
await zhbPage.getByText('选择', { exact: true }).nth(1).click();
|
||||
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
|
||||
await zhbPage.getByText('臻品足疗 (10101)').click();
|
||||
await zhbPage.locator('#serviceSelector').getByText('确认').click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^匠星足浴$/ })
|
||||
.locator('span')
|
||||
.first()
|
||||
.click();
|
||||
await zhbPage.getByRole('button', { name: '完成开单' }).click();
|
||||
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible();
|
||||
await zhbPage.getByRole('button', { name: '结账' }).click();
|
||||
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
|
||||
|
||||
await expect(async () => {
|
||||
await zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' }).click();
|
||||
await expect(zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' })).toHaveClass(
|
||||
/selected/
|
||||
);
|
||||
await zhbPage
|
||||
.locator('#page_footBathPay span')
|
||||
.filter({ hasText: /结\s算/ })
|
||||
.click();
|
||||
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
|
||||
}).toPass();
|
||||
|
||||
await zhbPage.getByText('不想评价').click();
|
||||
await expect(zhbPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('起钟下钟,清理房间', async () => {
|
||||
const $cleanRoom = $$room.filter({
|
||||
has: zhbPage.locator('.roomName', { hasText: new RegExp(`^${useRoomName}$`) }),
|
||||
});
|
||||
await expect($cleanRoom).toContainText('已结清');
|
||||
await $cleanRoom.click();
|
||||
await zhbPage.getByText('技师操作').click();
|
||||
await zhbPage.getByText('起钟', { exact: true }).click();
|
||||
await zhbPage.getByText('起钟成功!').click();
|
||||
await zhbPage.getByText('技师操作').click();
|
||||
await zhbPage.getByText('下钟', { exact: true }).click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^确认返回$/ })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await zhbPage.getByRole('button', { name: '不需要' }).click();
|
||||
|
||||
await expect($cleanRoom).toContainText('打扫');
|
||||
await $cleanRoom.click();
|
||||
await zhbPage
|
||||
.locator('div')
|
||||
.filter({ hasText: /^确定取消$/ })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await expect($cleanRoom).toContainText('空房');
|
||||
});
|
||||
});
|
||||
25
tests/zhb/fixture/base.js
Normal file
25
tests/zhb/fixture/base.js
Normal file
@ -0,0 +1,25 @@
|
||||
const { test: base, expect } = require('@playwright/test');
|
||||
const authFile = '.auth/zhb_admin.json';
|
||||
const test = base.extend({
|
||||
/**
|
||||
* @type {import('@playwright/test').Page}
|
||||
*/
|
||||
zhbPage: async ({ browser, baseURL }, use) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: authFile,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL);
|
||||
console.log(baseURL);
|
||||
|
||||
await use(page);
|
||||
|
||||
await page.close();
|
||||
await context.close();
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
test,
|
||||
expect,
|
||||
};
|
||||
6
tests/zhb/fixture/common.js
Normal file
6
tests/zhb/fixture/common.js
Normal file
@ -0,0 +1,6 @@
|
||||
const { mergeTests } = require('@playwright/test');
|
||||
const { test: customerTest } = require('./customerFixture');
|
||||
|
||||
export const test = mergeTests(customerTest);
|
||||
|
||||
export { expect } from '@playwright/test';
|
||||
12
tests/zhb/fixture/customerFixture.js
Normal file
12
tests/zhb/fixture/customerFixture.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { test as base } from './base';
|
||||
import { CustomerPage } from '../pom/customerPage';
|
||||
|
||||
export const test = base.extend({
|
||||
/**
|
||||
* @type {CustomerPage}
|
||||
*/
|
||||
customerPage: async ({ zhbPage }, use) => {
|
||||
const customerPage = new CustomerPage(zhbPage);
|
||||
await use(customerPage);
|
||||
},
|
||||
});
|
||||
54
tests/zhb/pom/customerPage.js
Normal file
54
tests/zhb/pom/customerPage.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { faker } = require('@faker-js/faker/locale/zh_CN');
|
||||
const { expect } = require('@playwright/test');
|
||||
|
||||
export class Customer {
|
||||
constructor({
|
||||
name = faker.person.fullName(),
|
||||
phone = faker.helpers.fromRegExp(/1[3-9][0-9]{6}/),
|
||||
} = {}) {
|
||||
this.name = name;
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomerPage {
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor(page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建顾客
|
||||
* @param {Customer} customer
|
||||
*/
|
||||
createCustomer = async (customer) => {
|
||||
console.log(customer.name);
|
||||
console.log(customer.phone);
|
||||
|
||||
await expect(this.page.locator('#page_member').getByText('新增顾客档案')).toBeVisible();
|
||||
await this.page.locator('#page_member').getByText('新增顾客档案').click();
|
||||
|
||||
await this.page.getByPlaceholder('请输入会员姓名').fill(customer.name);
|
||||
await this.page.getByPlaceholder('请输入手机号码').click();
|
||||
await expect(this.page.getByText('请输入数字')).toBeVisible();
|
||||
await this.page.getByPlaceholder('在此输入').click();
|
||||
await this.page.keyboard.type(customer.phone, { delay: 100 });
|
||||
// await this.page.getByPlaceholder('在此输入').type(customer.phone, { delay: 100 });
|
||||
await this.page.locator('#maskBoard').getByText('确认').click();
|
||||
await expect(this.page.getByPlaceholder('请输入手机号码')).toHaveValue(customer.phone, {
|
||||
timeout: 2000,
|
||||
});
|
||||
await this.page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^员工带客$/ })
|
||||
.locator('span')
|
||||
.first()
|
||||
.click();
|
||||
await this.page.getByText('创建', { exact: true }).click();
|
||||
await expect(this.page.getByText('用户资料创建成功!')).toBeVisible();
|
||||
await this.page.getByText('以后再说').click();
|
||||
await expect(this.page.getByText('以后再说')).not.toBeVisible();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user