Compare commits

...

6 Commits

6 changed files with 74 additions and 74 deletions

View File

@ -5,7 +5,7 @@ on:
pull_request:
branches: [main, master]
schedule:
- cron: '30 9 * * *' # 每天凌晨 12 点执行一次
- cron: '30 1 * * *' # 每天 上午 9.30 执行一次
workflow_dispatch: # 手动触发
jobs:
test:

View File

@ -7,6 +7,7 @@
"mgj_codegen": "npx playwright codegen https://vip1.meiguanjia.net/shair/?v=mgj",
"zhb_codegen": "npx playwright codegen https://shengyibao.meiguanjia.net/young/",
"test:repeat": "npx playwright test ./tests/zhb ./tests/mgj ./tests/hlk --repeat-each=3",
"test:simple": "npx playwright test ./tests/zhb ./tests/mgj ./tests/hlk",
"ui": "npx playwright test --ui",
"pwi": "npm ci && npx playwright install",
"pwu": "npx playwright install --with-deps"

View File

@ -24,12 +24,18 @@ module.exports = defineConfig({
/* 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,
retries: process.env.CI ? 1 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : 1,
/* 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. */
timeout: 3 * 60000,
expect: {
toPass: {
timeout: 30000,
},
},
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: process.env.BASE_URL,
@ -41,7 +47,7 @@ module.exports = defineConfig({
'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',
trace: 'retain-on-failure',
},
/* Configure projects for major browsers */

View File

@ -2,59 +2,50 @@ const { test, expect } = require('./fixtures/common');
const { Customer } = require('./pom/customer');
const { faker } = require('@faker-js/faker/locale/zh_CN');
test('登录touch和h5创建顾客购买会员卡使用顾客账号到h5商城购买货品', async ({
touchPage,
h5Page,
touchCustomerPage,
h5LoginPage,
}) => {
test.describe
.serial('登录touch和h5创建顾客购买会员卡使用顾客账号到h5商城购买货品', async () => {
const phone = faker.helpers.fromRegExp(/1[3-9][0-1]{9}/);
const customer = new Customer(1, 1, { phone: phone });
console.log(`${customer.phone}-${customer.username}`);
await touchCustomerPage.createCustomer(customer);
/** @type string*/
let cardName;
test('登录touch和h5创建顾客购买会员卡', async ({ touchPage, touchCustomerPage }) => {
await test.step('在touch页面购买会员卡', async () => {
await touchCustomerPage.createCustomer(customer);
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('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.getByLabel('结算签字').uncheck();
await touchPage.getByRole('button', { name: /结\s算/ }).click();
await touchPage.getByRole('button', { name: /跳\s过/ }).click();
});
});
await test.step('登录h5并且商城页面使用会员卡进行购买', async () => {
test('登录h5并且商城页面使用会员卡进行购买', async ({ h5Page, h5LoginPage }) => {
await h5LoginPage.login(customer.phone);
await h5Page.locator('.singIn_content > .iconfont').click();
const element = h5Page.locator('.coupon_content');
const boundingBox = await element.boundingBox();
if (boundingBox) {
const x = boundingBox.x + boundingBox.width / 2; // 元素水平中心
const y = boundingBox.y - 10; // 元素上侧空白区域
await h5Page.mouse.click(x, y);
}
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').nth(2).click();
await h5Page.locator('.p-item').filter({ hasText: '美肤' }).first().click();
await h5Page.getByText('立即购买').click();
await h5Page.locator('uni-text').filter({ hasText: '佘山二店' }).click();
await h5Page.getByText('确认').click();
await h5Page.getByText('哎哟代理卡').click();
await expect(h5Page.getByText('确认支付')).toBeEnabled();
await h5Page.getByText('确认支付').click();
await expect(h5Page.getByText('支付成功').first()).toBeVisible();
await expect(h5Page.getByText('查看订单')).toBeVisible();
});
});

View File

@ -39,18 +39,17 @@ test('demo', async ({ mgjPage, customerPage }) => {
await expect($signature).not.toHaveClass(/checked/, { timeout: 2000 });
}).toPass();
await expect(async () => {
const $cashBtn = mgjPage.locator('#page_pay .pay_cash');
await expect(async () => {
if ($cashBtn.isVisible()) {
await $cashBtn.click();
await expect(mgjPage.locator('#page_pay .pay_cash.selected')).toBeVisible();
}
await expect(mgjPage.locator('#page_pay .pay_cash.selected')).toBeVisible({ timeout: 2000 });
}).toPass();
await mgjPage
.locator('#page_pay span')
.filter({ hasText: /结\s算/ })
.click();
await expect(mgjPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
}).toPass();
await mgjPage.getByText('不想评价').click();
await expect(mgjPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
await expect(mgjPage.getByText('顾客满意度点评')).toBeVisible();
});
});

View File

@ -5,17 +5,18 @@ const { faker } = require('@faker-js/faker');
const { test, expect } = require('./fixture/common');
const { Customer } = require('./pom/customerPage');
/**@type {{name: string, phone: string}[]} */
const records = parse(fs.readFileSync(path.join(__dirname, 'zhb.csv')), {
columns: true,
skip_empty_lines: true,
});
test('csv', async ({ zhbPage }, workerInfo) => {
test('csv', async ({ zhbPage }) => {
console.log(records.length);
const $area = zhbPage
const $$emptyRoom = zhbPage
.locator('.area')
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
const $$room = $area.locator('.room-list .room');
.locator('.room-list .room')
.filter({ has: zhbPage.getByText('空房') });
// 随机csv文件中的任意一个顾客
const record = records[faker.number.int({ min: 0, max: records.length - 1 })];
@ -23,16 +24,13 @@ test('csv', async ({ zhbPage }, workerInfo) => {
console.log({ name, phone });
const customer = new Customer({ name: name, phone: name });
// 使用房间名称
/**@type {string} 房间名称 */
let useRoomName;
await test.step('购买商品', async () => {
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
const $emptyRoom = $$room
.filter({ has: zhbPage.getByText('空房') })
.nth(workerInfo.workerIndex % 3);
useRoomName = await $emptyRoom.locator('.roomName').innerText();
expect(useRoomName).not.toBeNull();
await $emptyRoom.click();
await $$emptyRoom.first().waitFor();
useRoomName = await $$emptyRoom.first().locator('.roomName').innerText();
await $$emptyRoom.first().click();
await expect(async () => {
if (await zhbPage.locator('.close > .iconfont').first().isVisible()) {
await zhbPage.locator('.close > .iconfont').first().click();
@ -56,7 +54,7 @@ test('csv', async ({ zhbPage }, workerInfo) => {
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
await zhbPage
.locator('.goods-content-item')
.nth(faker.number.int({ min: 0, max: 14 }))
.nth(faker.number.int({ min: 0, max: 10 }))
.click();
await zhbPage.locator('#serviceSelector').getByText('确认').click();
await zhbPage
@ -65,8 +63,10 @@ test('csv', async ({ zhbPage }, workerInfo) => {
.locator('span')
.first()
.click();
await expect(async () => {
await zhbPage.getByRole('button', { name: '完成开单' }).click();
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible({ timeout: 30_000 });
await zhbPage.getByRole('button', { name: '结账' }).waitFor();
}).toPass();
await zhbPage.getByRole('button', { name: '结账' }).click();
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
@ -75,26 +75,29 @@ test('csv', async ({ zhbPage }, workerInfo) => {
await expect(zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' })).toHaveClass(
/selected/
);
}).toPass();
await zhbPage
.locator('#page_footBathPay span')
.filter({ hasText: /结\s算/ })
.click();
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
}).toPass();
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible();
await zhbPage.getByText('不想评价').click();
await zhbPage.locator('#page_footBathPay').getByText('立即返回').click();
});
await test.step('起钟下钟,清理房间', async () => {
const $$room = zhbPage.locator('.area').locator('.room-list .room');
const $cleanRoom = $$room.filter({
has: zhbPage.locator('.roomName', { hasText: new RegExp(`^${useRoomName}$`) }),
});
await expect($cleanRoom).toContainText('已结清');
await $cleanRoom.click();
await zhbPage.getByText('技师操作').click();
await expect(async () => {
await zhbPage.getByText('起钟', { exact: true }).click();
await zhbPage.getByText('起钟成功!').click();
await zhbPage.getByText('起钟成功!').waitFor();
}).toPass();
await zhbPage.getByText('技师操作').click();
await zhbPage.getByText('下钟', { exact: true }).click();
await zhbPage