ci(gitlab): 添加 GitLab CI 配置并更新测试相关代码

- 新增 .gitlab-ci.yml 文件,配置 GitLab CI/CD 管道
- 移除 AuthAccount 类中未使用的 indexedDBFile 属性
- 简化 baseFixture 中的测试初始化流程
- 更新 CustomerPage 中的顾客创建逻辑
- 调整 boss_cashier.spec.ts 中的二维码解码和输入值设置
- 新增 boss_test.spec.ts 文件,添加创建顾客的测试用例
This commit is contained in:
LingandRX 2025-03-12 00:22:22 +08:00
parent 649efd4f78
commit 3547f32493
6 changed files with 61 additions and 42 deletions

29
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,29 @@
stages:
- test
- report
playwright_tests:
stage: test
image: mcr.microsoft.com/playwright:focal
script:
- npm install
- npx playwright install
- npx playwright test
artifacts:
paths:
- test-results/
expire_in: 1 week
send_report:
stage: report
image: alpine:latest
script:
- apk add --no-cache curl
- |
if [ -d test-results ]; then
echo "Test Successful."
else
echo "No test results found."
fi
only:
- main

View File

@ -10,27 +10,11 @@ class AuthAccount {
account: string; account: string;
password: string; password: string;
authFile: string; authFile: string;
indexedDBFile: string;
constructor(account: string, password: string, authFile: string, indexedDBFile: string) { constructor(account: string, password: string, authFile: string) {
this.account = account; this.account = account;
this.password = password; this.password = password;
this.authFile = authFile; this.authFile = authFile;
this.indexedDBFile = indexedDBFile;
}
static loadIndexedDBFile(account: string, accountArray: AuthAccount[]) {
try {
for (const item of accountArray) {
if (item.account === account) {
return JSON.parse(readFileSync(item.indexedDBFile, 'utf-8'));
}
}
} catch (e) {
throw new Error('indexedDB文件读取失败');
}
throw new Error('未找到该账户');
} }
} }
@ -38,14 +22,12 @@ const firstAccount = new AuthAccount(
getEnvVar('boss_account'), getEnvVar('boss_account'),
getEnvVar('boss_password'), getEnvVar('boss_password'),
`${authConfig.authFilePath}${getEnvVar('boss_account')}.json`, `${authConfig.authFilePath}${getEnvVar('boss_account')}.json`,
`${authConfig.indexedDBFilePath}${getEnvVar('boss_account')}_indexedDB.json`,
); );
const secondAccount = new AuthAccount( const secondAccount = new AuthAccount(
getEnvVar('boss_account_2'), getEnvVar('boss_account_2'),
getEnvVar('boss_password_2'), getEnvVar('boss_password_2'),
`${authConfig.authFilePath}${getEnvVar('boss_account_2')}.json`, `${authConfig.authFilePath}${getEnvVar('boss_account_2')}.json`,
`${authConfig.indexedDBFilePath}${getEnvVar('boss_account_2')}_indexedDB.json`,
); );

View File

@ -16,19 +16,14 @@ export const test = base.extend<MyFixture>({
if (!baseURL) throw new Error('baseURL is required'); if (!baseURL) throw new Error('baseURL is required');
await page.goto(baseURL); await page.goto(baseURL);
// await page.getByRole('button', { name: /开\s单/ }).waitFor();
const mobileObject = await page.evaluate(() => { await expect(page.getByRole('button', { name: /开\s单/ })).toBeEnabled();
return window.localStorage.getItem('hlk_touch_mobile');
});
if (!mobileObject && mobileObject !== 'null') {
throw new Error('localStorage does not contain boss_account or boss_account2');
}
const mobileString = JSON.parse(mobileObject);
const data = AuthAccount.loadIndexedDBFile(mobileString.val, [firstAccount, secondAccount]);
await page.reload(); await page.reload();
await page.getByRole('button', { name: /开\s单/ }).waitFor(); await page.getByRole('button', { name: /开\s单/ }).click();
// await page.getByRole('button', { name: /开\s单/ }).waitFor();
await expect(page.getByRole('button', { name: '创建会员' })).toBeEnabled();
await use(page); await use(page);
}, },

View File

@ -27,7 +27,7 @@ export class CustomerPage {
private readonly secondStore = { private readonly secondStore = {
firstDepartment: { no: 1, name: '美容部' }, firstDepartment: { no: 1, name: '美容部' },
}; };
private readonly source: string[] = [ private readonly sourceChannel: string[] = [
'邀客', '邀客',
'员工带客', '员工带客',
'美团', '美团',
@ -156,6 +156,7 @@ export class CustomerPage {
createCustomer = async (customer: Customer) => { createCustomer = async (customer: Customer) => {
const customerPage = '/#/member/member-schame'; const customerPage = '/#/member/member-schame';
await this.page.goto(customerPage); await this.page.goto(customerPage);
await expect(this.page.getByRole('button', { name: '新增顾客' })).toBeEnabled();
await this.selectStore(customer.store); await this.selectStore(customer.store);
await this.fillCustomerDetails(customer); await this.fillCustomerDetails(customer);
await this.selectDepartment(customer); await this.selectDepartment(customer);
@ -321,7 +322,7 @@ export class CustomerPage {
* @param {number} source * @param {number} source
*/ */
private readonly selectSource = async (source: number) => { private readonly selectSource = async (source: number) => {
await this.$register.getByLabel(this.source[source]).click(); await this.$register.getByLabel(this.sourceChannel[source]).click();
}; };
/** /**
@ -339,25 +340,27 @@ export class CustomerPage {
*/ */
private readonly confirmCreation = async (phone: string) => { private readonly confirmCreation = async (phone: string) => {
const [response] = await Promise.all([ const [response] = await Promise.all([
this.page.waitForResponse( this.page.waitForResponse(async res => res.url().includes('/invalid_check') && (await res.json()).code === 'SUCCESS'),
async res => res.url().includes('/invalid_check') && (await res.json()).code === 'SUCCESS',
),
this.page.getByRole('button', { name: '确认创建' }).click(), this.page.getByRole('button', { name: '确认创建' }).click(),
]); ]);
const responseBody = await response.json(); const responseBody = await response.json();
const phoneStatus = responseBody?.content?.status; const phoneStatus = responseBody?.content?.status;
if (phoneStatus === undefined || phoneStatus === null) { if (phoneStatus === undefined || phoneStatus === null) {
// 创建顾客成功
return; return;
} }
await this.page.getByText('系统查询到当前手机号被建档后转为无效客,是否要恢复无效客?').waitFor(); await this.page.getByText('系统查询到当前手机号被建档后转为无效客,是否要恢复无效客?').waitFor();
await this.page.getByRole('button', { name: '重新建档' }).click(); await this.page.getByRole('button', { name: '重新建档' }).click();
const popupWindow = this.page.locator('.ant-message'); const popupWindow = this.page.locator('.ant-message');
await popupWindow.waitFor();
const popupContent = (await popupWindow.innerText()).trim(); await expect(popupWindow).not.toContainText('该手机号码已经被使用');
if (popupContent.includes('该手机号码已经被使用')) {
throw new Error(`手机号码 ${phone} 已被使用,无法创建新顾客`); // await popupWindow.waitFor();
} // const popupContent = (await popupWindow.innerText()).trim();
// if (popupContent.includes('该手机号码已经被使用')) {
// throw new Error(`手机号码 ${phone} 已被使用,无法创建新顾客`);
// }
}; };
/** /**

View File

@ -306,6 +306,8 @@ test.describe('挂单', () => {
const phone = customer.phone; const phone = customer.phone;
const username = customer.username; const username = customer.username;
await page.pause();
await homeNavigation.gotoModule('收银'); await homeNavigation.gotoModule('收银');
await page.getByRole('button', { name: /^开\s单$/ }).click(); await page.getByRole('button', { name: /^开\s单$/ }).click();
await customerPage.searchCustomer(phone); await customerPage.searchCustomer(phone);
@ -417,7 +419,7 @@ test.describe('挂单', () => {
await page.locator('.qrcode').screenshot({ path: filePath }); await page.locator('.qrcode').screenshot({ path: filePath });
}).toPass(); }).toPass();
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);
@ -1111,7 +1113,7 @@ test.describe('收银-开单&结算', () => {
await page.getByRole('button', { name: /^确\s认$/ }).click(); await page.getByRole('button', { name: /^确\s认$/ }).click();
// 修改数量 // 修改数量
await page.locator('.edit_txt div:nth-child(2)').first().click(); await page.locator('.edit_txt div:nth-child(2)').first().click();
await numberInput.setValue(2); await numberInput.setValue('common', 2);
await numberInput.confirmValue(); await numberInput.confirmValue();
const quantity = (await page.locator('.buy_number').last().innerText()).trim(); const quantity = (await page.locator('.buy_number').last().innerText()).trim();
// 结算 // 结算
@ -1270,7 +1272,7 @@ test.describe('收银-开单&结算', () => {
await page.getByText('赠金').nth(2).click(); await page.getByText('赠金').nth(2).click();
await page.getByRole('button', { name: '增加收款' }).click(); await page.getByRole('button', { name: '增加收款' }).click();
// 输入金额 // 输入金额
await numberInput.setCommonValue(90); await numberInput.setValue('common', 90);
await numberInput.confirmValue(); await numberInput.confirmValue();
// 结算 // 结算
await page.getByRole('button', { name: /^结\s算$/ }).click(); await page.getByRole('button', { name: /^结\s算$/ }).click();

View File

@ -0,0 +1,8 @@
// @ts-check
import { test, expect } from '@/fixtures/boss_common.js'; //使用公共套件
for (let i = 0; i < 10; i++) {
test(`创建顾客${i}`, async ({ createCustomer }) => {
console.log('创建顾客成功');
});
}