feat(tests): add global setup and test specification for identity verification
- Created a global setup file to handle user login and merchant selection based on identity verification. - Implemented a test specification to verify the identity verification tool and log merchant details.
This commit is contained in:
parent
5e33762358
commit
729b6de180
10
config/SidebarPageConfig.json
Normal file
10
config/SidebarPageConfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"setting": {
|
||||
"name": "设置",
|
||||
"selector": "#app > div.routerView.page_view > div > div.navStore_view > div.left_menu_area > div.menu_area.scroll0 > ul > li:nth-child(3)",
|
||||
"content": [
|
||||
{ "name": "微信设置", "selector": "" },
|
||||
{ "name": "支付设置", "selector": "" }
|
||||
]
|
||||
}
|
||||
}
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dotenv": "^16.5.0",
|
||||
"playwright": "^1.53.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -42,6 +43,18 @@
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.5.0.tgz",
|
||||
"integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"dotenv": "^16.5.0",
|
||||
"playwright": "^1.53.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
@ -30,24 +32,32 @@ export default defineConfig({
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
baseURL: process.env.BASE_URL || 'http://localhost:3000',
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'setup',
|
||||
testMatch: /global\.setup\.ts/,
|
||||
},
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
},
|
||||
dependencies: ['setup'],
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: { ...devices['Desktop Firefox'] },
|
||||
// },
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: { ...devices['Desktop Safari'] },
|
||||
// },
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
|
||||
@ -28,6 +28,24 @@ export class LoginPage {
|
||||
await this.login_button.click();
|
||||
}
|
||||
|
||||
async user_select_merchant(merchantName: string) {
|
||||
const merchantLocator = this.page.getByText(merchantName, { exact: true });
|
||||
await expect(merchantLocator).toBeVisible();
|
||||
await merchantLocator.click();
|
||||
await this.page.waitForLoadState('networkidle');
|
||||
await this.page.waitForTimeout(1000); // 等待页面加载完成
|
||||
console.log(`已选择租户: ${merchantName}`);
|
||||
}
|
||||
|
||||
async user_select_employee(employeeName: string) {
|
||||
const employeeLocator = this.page.getByText(employeeName).first();
|
||||
await expect(employeeLocator).toBeVisible();
|
||||
await employeeLocator.click();
|
||||
await this.page.waitForLoadState('networkidle');
|
||||
await this.page.waitForTimeout(1000); // 等待页面加载完成
|
||||
console.log(`已选择员工: ${employeeName}`);
|
||||
}
|
||||
|
||||
user_login_success() {
|
||||
return this.first_menu;
|
||||
}
|
||||
|
||||
12
src/page/SidebarPage.ts
Normal file
12
src/page/SidebarPage.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { expect, type Locator, type Page } from '@playwright/test';
|
||||
|
||||
export class SidebarPage {
|
||||
readonly page: Page;
|
||||
readonly first_menu: Locator;
|
||||
readonly second_menu: Locator;
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.first_menu
|
||||
this.second_menu
|
||||
}
|
||||
}
|
||||
67
src/util/authUtil.ts
Normal file
67
src/util/authUtil.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { request } from '@playwright/test';
|
||||
|
||||
async function getApiRequestContext() {
|
||||
return await request.newContext({
|
||||
baseURL: 'https://px.meiguanjia.net',
|
||||
extraHTTPHeaders: {
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||||
'Content-Type': 'application/json',
|
||||
DNT: '1',
|
||||
Origin: 'https://px.meiguanjia.net',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
currVersion: 'PX-PC_20250625155429',
|
||||
lang: 'zh_CN',
|
||||
'req-type': 'json',
|
||||
'sec-ch-ua': '"Microsoft Edge";v="137", "Chromium";v="137", "Not/A)Brand";v="24"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'system-code': 'MGJ',
|
||||
zoneId: 'UTC+08:00',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 身份验证工具
|
||||
* @param mobile 手机号
|
||||
* @param password 密码
|
||||
* @returns false 多租户 true 单租户
|
||||
* @description 该函数用于验证用户身份,返回一个包含状态和内容的对象
|
||||
* @example
|
||||
* const result = await identityVerificationTool('17770898274', 'a123456');
|
||||
* console.log(result.status); // true or false
|
||||
* console.log(result.content); // 返回的内容对象
|
||||
* @throws {Error} 如果请求失败或响应格式不正确
|
||||
*/
|
||||
export const identityVerificationTool = async (mobile: string, password: string) => {
|
||||
const apiRequestContext = await getApiRequestContext();
|
||||
const response = await apiRequestContext.post('/prestg/pixiu/api/login', {
|
||||
data: {
|
||||
mobile: mobile,
|
||||
password: password,
|
||||
sn: '8ebc3002-b398-4c11-8323-100e729fcf39',
|
||||
clientId: 'touch',
|
||||
deviceType: 'windows',
|
||||
},
|
||||
});
|
||||
|
||||
const responseBody = await response.json();
|
||||
|
||||
if (responseBody?.code === 'ACCOUNT_NEED_CHOOSE_MERCHANT') {
|
||||
return new verifyContent(false, responseBody?.content);
|
||||
} else if (responseBody?.code === 'SUCCESS') {
|
||||
return new verifyContent(true, {});
|
||||
}
|
||||
|
||||
return new verifyContent(true, {});
|
||||
};
|
||||
|
||||
function verifyContent(status: boolean, content: Object) {
|
||||
this.status = status;
|
||||
this.content = content;
|
||||
}
|
||||
647
state.json
Normal file
647
state.json
Normal file
File diff suppressed because one or more lines are too long
40
tests/global.setup.ts
Normal file
40
tests/global.setup.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { test as setup } from '@playwright/test';
|
||||
import { LoginPage } from '../src/page/LoginPage';
|
||||
import { identityVerificationTool } from '../src/util/authUtil';
|
||||
|
||||
setup('state setup', async ({ page }) => {
|
||||
const body = await identityVerificationTool('17770898274', 'a123456');
|
||||
if (!body.status) {
|
||||
console.log('身份验证失败,请选择租户');
|
||||
let merchanName: string | undefined = undefined;
|
||||
let employeeName: string | undefined = undefined;
|
||||
const content = body?.content;
|
||||
for (const merchant in content) {
|
||||
if (content[merchant]?.merchantId === 373) {
|
||||
merchanName = content[merchant]?.merchantName;
|
||||
if (content[merchant]?.users.length > 0) {
|
||||
employeeName = content[merchant]?.users[0]?.userName;
|
||||
}
|
||||
}
|
||||
}
|
||||
await page.goto(process.env.BASE_URL || 'http://localhost:3000');
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.user_login('17770898274', 'a123456');
|
||||
await loginPage.user_select_merchant(merchanName || '美管家');
|
||||
console.log(employeeName);
|
||||
if (employeeName) {
|
||||
await loginPage.user_select_employee(employeeName);
|
||||
}
|
||||
await page.pause();
|
||||
await loginPage.user_login_success().waitFor();
|
||||
await page.context().storageState({ path: 'state.json', indexedDB: true });
|
||||
return;
|
||||
}
|
||||
console.log('身份验证成功');
|
||||
await page.goto(process.env.BASE_URL || 'http://localhost:3000');
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.user_login('17770898274', 'a123456');
|
||||
await page.pause();
|
||||
await loginPage.user_login_success().waitFor();
|
||||
await page.context().storageState({ path: 'state.json', indexedDB: true });
|
||||
});
|
||||
15
tests/test.spec.ts
Normal file
15
tests/test.spec.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { identityVerificationTool } from '../src/util/authUtil';
|
||||
|
||||
test('test1', async ({ page, baseURL }) => {
|
||||
const body = await identityVerificationTool('17770898274', 'a123456');
|
||||
const content = body?.content;
|
||||
for (const merchant in content) {
|
||||
if (content[merchant]?.merchantId === 373) {
|
||||
console.log(
|
||||
`租户名称:${content[merchant]?.merchantName},租户ID:${content[merchant]?.merchantId}`
|
||||
);
|
||||
console.log(content[merchant]?.users);
|
||||
}
|
||||
}
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user