Commit 4ae5c8c5bc68e11c9961299c0df3c283a3899d3a

Authored by 赵旭婷
1 parent 0d108388

新增员工管理用例,客户管理选择分组优化

pages/customerPage.ts
@@ -182,17 +182,20 @@ export class CustomerPage extends BasePage { @@ -182,17 +182,20 @@ export class CustomerPage extends BasePage {
182 } 182 }
183 183
184 /** 184 /**
185 - * 选择客户分组(选择"普通客户" 185 + * 选择客户分组(随机选择
186 */ 186 */
187 async selectCustomerGroup(): Promise<void> { 187 async selectCustomerGroup(): Promise<void> {
188 // 点击客户分组选择器 188 // 点击客户分组选择器
189 await this.customerGroupPicker.click(); 189 await this.customerGroupPicker.click();
190 - 190 +
191 // 等待弹窗出现 191 // 等待弹窗出现
192 await this.page.waitForTimeout(500); 192 await this.page.waitForTimeout(500);
193 193
194 - // 选择"普通客户"(使用 nth(4) 和 force: true 绕过遮罩层)  
195 - await this.page.locator('uni-view').filter({ hasText: /^普通客户$/ }).nth(4).click({ force: true }); 194 + // 随机选择一个客户分组
  195 + const items = this.page.locator('.zp-paging-container-content .default-item');
  196 + const count = await items.count();
  197 + const randomIndex = Math.floor(Math.random() * count);
  198 + await items.nth(randomIndex).click({ force: true });
196 } 199 }
197 200
198 /** 201 /**
pages/employeePage.ts 0 → 100644
  1 +import { Page, Locator, expect } from '@playwright/test';
  2 +import { BasePage } from './basePage';
  3 +
  4 +/**
  5 + * 员工管理页面类
  6 + * 处理员工管理相关操作
  7 + */
  8 +export class EmployeePage extends BasePage {
  9 + // 导航定位器
  10 + readonly employeeMenu: Locator;
  11 +
  12 + // 操作按钮
  13 + readonly newEmployeeButton: Locator;
  14 + readonly manualAddButton: Locator;
  15 + readonly confirmButton: Locator;
  16 +
  17 + // 表单字段
  18 + readonly employeeNameInput: Locator;
  19 + readonly phoneInput: Locator;
  20 + readonly remarkInput: Locator;
  21 + readonly positionInput: Locator;
  22 +
  23 + // 岗位列表
  24 + readonly positionOption: Locator;
  25 +
  26 + constructor(page: Page) {
  27 + super(page);
  28 +
  29 + this.employeeMenu = page.getByText('员工管理').first();
  30 + this.newEmployeeButton = page.getByText('新建员工');
  31 + this.manualAddButton = page.getByText('手动添加');
  32 + this.confirmButton = page.getByText('确定');
  33 + this.employeeNameInput = page.locator('uni-input').filter({ hasText: '请输入员工姓名' }).getByRole('textbox');
  34 + this.phoneInput = page.getByRole('spinbutton');
  35 + this.remarkInput = page.locator('uni-input').filter({ hasText: '请输入备注信息' }).getByRole('textbox');
  36 + this.positionInput = page.locator('.nut-cell__link').first();
  37 + this.positionOption = page.locator('uni-view').filter({ hasText: /^岗位名称$/ }).first();
  38 + }
  39 +
  40 + /**
  41 + * 进入员工管理页面
  42 + */
  43 + async openEmployeeManagement(): Promise<void> {
  44 + await this.navigate('/');
  45 + await this.employeeMenu.click();
  46 + await this.page.waitForLoadState('networkidle', { timeout: 30000 });
  47 + }
  48 +
  49 + /**
  50 + * 点击新建员工按钮
  51 + */
  52 + async clickNewEmployee(): Promise<void> {
  53 + await this.newEmployeeButton.click();
  54 + await this.page.waitForTimeout(500);
  55 + }
  56 +
  57 + /**
  58 + * 点击手动添加
  59 + */
  60 + async clickManualAdd(): Promise<void> {
  61 + await this.manualAddButton.click();
  62 + await this.page.waitForTimeout(500);
  63 + }
  64 +
  65 + /**
  66 + * 填写员工姓名
  67 + * @param name 员工姓名
  68 + */
  69 + async fillEmployeeName(name: string): Promise<void> {
  70 + await this.employeeNameInput.click();
  71 + await this.employeeNameInput.fill(name);
  72 + }
  73 +
  74 + /**
  75 + * 填写联系电话
  76 + * @param phone 联系电话
  77 + */
  78 + async fillPhone(phone: string): Promise<void> {
  79 + await this.phoneInput.click();
  80 + await this.phoneInput.fill(phone);
  81 + }
  82 +
  83 + /**
  84 + * 填写备注
  85 + * @param remark 备注信息
  86 + */
  87 + async fillRemark(remark: string): Promise<void> {
  88 + await this.remarkInput.click();
  89 + await this.remarkInput.fill(remark);
  90 + }
  91 +
  92 + /**
  93 + * 选择岗位
  94 + * @param position 岗位名称(可选,不传则随机选择)
  95 + */
  96 + async selectPosition(position?: string): Promise<void> {
  97 + // 点击岗位名称输入框打开下拉列表
  98 + await this.page.locator('uni-view:nth-child(6) > .nut-cell__value > .nut-form-item__body__slots > .nut-input > .nut-input__value > .nut-input__mask').click();
  99 + await this.page.waitForTimeout(500);
  100 +
  101 + if (position) {
  102 + // 选择指定岗位
  103 + await this.page.locator('uni-view').filter({ hasText: position }).first().click();
  104 + } else {
  105 + // 随机选择岗位 - 获取所有岗位选项并随机选择一个
  106 + const options = this.page.locator('uni-view').filter({ hasText: /^销售员$|^仓库管理员$/ });
  107 + const count = await options.count();
  108 + if (count > 0) {
  109 + const randomIndex = Math.floor(Math.random() * count);
  110 + await options.nth(randomIndex).click();
  111 + }
  112 + }
  113 + await this.page.waitForTimeout(300);
  114 + }
  115 +
  116 + /**
  117 + * 点击确定按钮
  118 + */
  119 + async clickConfirm(): Promise<void> {
  120 + await this.confirmButton.click();
  121 + await this.page.waitForTimeout(1000);
  122 + }
  123 +
  124 + /**
  125 + * 搜索员工
  126 + * @param name 员工姓名
  127 + */
  128 + async searchEmployee(name: string): Promise<void> {
  129 + await this.page.getByRole('textbox').click();
  130 + await this.page.getByRole('textbox').fill(name);
  131 + await this.page.waitForTimeout(1000);
  132 + }
  133 +
  134 + /**
  135 + * 验证员工是否存在
  136 + * @param name 员工姓名
  137 + * @returns 是否存在
  138 + */
  139 + async verifyEmployeeExists(name: string): Promise<boolean> {
  140 + const isVisible = await this.page.getByText(name).first().isVisible().catch(() => false);
  141 + return isVisible;
  142 + }
  143 +
  144 + /**
  145 + * 新增员工完整流程
  146 + * @param name 员工姓名
  147 + * @param phone 联系电话
  148 + * @param remark 备注
  149 + * @param position 岗位(可选)
  150 + */
  151 + async createEmployee(name: string, phone: string, remark: string, position?: string): Promise<void> {
  152 + await this.openEmployeeManagement();
  153 + await this.clickNewEmployee();
  154 + await this.clickManualAdd();
  155 + await this.fillEmployeeName(name);
  156 + await this.fillPhone(phone);
  157 + await this.fillRemark(remark);
  158 + await this.selectPosition(position);
  159 + await this.clickConfirm();
  160 + }
  161 +
  162 + /**
  163 + * 点击修改按钮
  164 + */
  165 + async clickEditButton(): Promise<void> {
  166 + await this.page.locator('uni-button.execute-plain-btn').getByText('修改').click();
  167 + await this.page.waitForTimeout(500);
  168 + }
  169 +
  170 + /**
  171 + * 填写备注(修改页面)
  172 + * @param remark 备注信息
  173 + */
  174 + async fillRemarkForEdit(remark: string): Promise<void> {
  175 + await this.page.locator('uni-input').filter({ hasText: '请输入备注信息' }).getByRole('textbox').click();
  176 + await this.page.locator('uni-input').filter({ hasText: '请输入备注信息' }).getByRole('textbox').fill(remark);
  177 + }
  178 +
  179 + /**
  180 + * 点击状态开关
  181 + */
  182 + async clickStatusSwitch(): Promise<void> {
  183 + await this.page.locator('uni-view:nth-child(5) > .nut-cell__value > .nut-form-item__body__slots > .nut-switch > .nut-switch-button').click();
  184 + await this.page.waitForTimeout(300);
  185 + }
  186 +
  187 + /**
  188 + * 选择岗位(修改页面)
  189 + * @param position 岗位名称
  190 + */
  191 + async selectPositionForEdit(position: string): Promise<void> {
  192 + // 点击岗位名称输入框打开下拉列表(使用与新增相同的selector)
  193 + await this.page.locator('uni-view:nth-child(6) > .nut-cell__value > .nut-form-item__body__slots > .nut-input > .nut-input__value > .nut-input__mask').click();
  194 + await this.page.waitForTimeout(500);
  195 + // 选择岗位
  196 + await this.page.locator('uni-view').filter({ hasText: position }).first().click();
  197 + await this.page.waitForTimeout(300);
  198 + }
  199 +
  200 + /**
  201 + * 验证员工备注是否包含指定内容
  202 + * @param expectedRemark 期望的备注内容
  203 + * @returns 是否包含
  204 + */
  205 + async verifyEmployeeRemarkContains(expectedRemark: string): Promise<boolean> {
  206 + const remarkElement = this.page.getByText(expectedRemark).first();
  207 + const isVisible = await remarkElement.isVisible({ timeout: 3000 }).catch(() => false);
  208 + return isVisible;
  209 + }
  210 +
  211 + /**
  212 + * 点击解绑按钮
  213 + */
  214 + async clickUnbindButton(): Promise<void> {
  215 + await this.page.locator('uni-button.warning-plain-btn').getByText('解绑').click();
  216 + await this.page.waitForTimeout(500);
  217 + }
  218 +
  219 + /**
  220 + * 确认解绑
  221 + */
  222 + async confirmUnbind(): Promise<void> {
  223 + await this.page.getByText('确定', { exact: true }).click();
  224 + await this.page.waitForTimeout(1000);
  225 + }
  226 +
  227 + /**
  228 + * 验证员工不存在
  229 + * @param name 员工姓名
  230 + * @returns 是否不存在
  231 + */
  232 + async verifyEmployeeNotExists(name: string): Promise<boolean> {
  233 + const employeeElement = this.page.getByText(name).first();
  234 + const isHidden = await employeeElement.isHidden({ timeout: 3000 }).catch(() => true);
  235 + return isHidden;
  236 + }
  237 +}
tests/employee.spec.ts 0 → 100644
  1 +import { test, expect } from '@playwright/test';
  2 +import * as allure from 'allure-js-commons';
  3 +import { EmployeePage } from '../pages/employeePage';
  4 +import { generateCustomerName, generatePhoneNumber } from '../utils/dataGenerator';
  5 +
  6 +/**
  7 + * 员工管理测试
  8 + */
  9 +test.describe('员工管理', () => {
  10 + // 使用已保存的认证状态
  11 + test.use({ storageState: 'auth.json' });
  12 +
  13 + // 强制测试串行执行
  14 + test.describe.configure({ mode: 'serial' });
  15 +
  16 + /**
  17 + * 生成随机员工姓名(使用已有函数)
  18 + */
  19 + function generateEmployeeName(): string {
  20 + return generateCustomerName();
  21 + }
  22 +
  23 + /**
  24 + * 生成随机联系电话(使用已有函数)
  25 + */
  26 + function generatePhone(): string {
  27 + return generatePhoneNumber();
  28 + }
  29 +
  30 + /**
  31 + * 生成包含"自动化"的备注
  32 + */
  33 + function generateRemark(): string {
  34 + const timestamp = Date.now().toString().slice(-6);
  35 + return `自动化员工测试备注${timestamp}`;
  36 + }
  37 +
  38 + test('新增员工', async ({ page }, testInfo) => {
  39 + const employeePage = new EmployeePage(page);
  40 +
  41 + // 添加allure元素
  42 + await allure.epic('员工管理');
  43 + await allure.feature('员工信息');
  44 + await allure.story('新增员工');
  45 +
  46 + // 生成随机员工数据
  47 + const employeeName = generateEmployeeName();
  48 + const phone = generatePhone();
  49 + const remark = generateRemark();
  50 +
  51 + console.log('员工姓名:', employeeName);
  52 + console.log('联系电话:', phone);
  53 + console.log('备注:', remark);
  54 +
  55 + // 步骤1:进入员工管理页面
  56 + await allure.step('进入员工管理页面', async () => {
  57 + await employeePage.openEmployeeManagement();
  58 + });
  59 +
  60 + // 步骤2:点击新建员工按钮
  61 + await allure.step('点击新建员工按钮', async () => {
  62 + await employeePage.clickNewEmployee();
  63 + });
  64 +
  65 + // 步骤3:点击手动添加
  66 + await allure.step('点击手动添加', async () => {
  67 + await employeePage.clickManualAdd();
  68 + });
  69 +
  70 + // 步骤4:填写员工表单
  71 + await allure.step('填写员工表单', async () => {
  72 + await employeePage.fillEmployeeName(employeeName);
  73 + await employeePage.fillPhone(phone);
  74 + await employeePage.fillRemark(remark);
  75 + await employeePage.selectPosition(); // 不传参数,随机选择岗位
  76 + });
  77 +
  78 + // 步骤5:保存员工
  79 + await allure.step('保存员工', async () => {
  80 + await employeePage.clickConfirm();
  81 + });
  82 +
  83 + // 步骤6:验证员工创建成功
  84 + await allure.step('验证员工创建成功', async () => {
  85 + // 使用员工姓名搜索
  86 + await employeePage.searchEmployee(employeeName);
  87 + const isExists = await employeePage.verifyEmployeeExists(employeeName);
  88 + expect(isExists).toBeTruthy();
  89 + });
  90 + });
  91 +
  92 + test('修改员工', async ({ page }, testInfo) => {
  93 + const employeePage = new EmployeePage(page);
  94 +
  95 + // 添加allure元素
  96 + await allure.epic('员工管理');
  97 + await allure.feature('员工信息');
  98 + await allure.story('修改员工');
  99 +
  100 + // 先生成一个新员工用于修改测试
  101 + const employeeName = generateEmployeeName();
  102 + const phone = generatePhone();
  103 + const originalRemark = '新建员工备注';
  104 +
  105 + console.log('待修改员工姓名:', employeeName);
  106 + console.log('联系电话:', phone);
  107 +
  108 + // 步骤1:新增员工
  109 + await allure.step('新增员工', async () => {
  110 + await employeePage.openEmployeeManagement();
  111 + await employeePage.clickNewEmployee();
  112 + await employeePage.clickManualAdd();
  113 + await employeePage.fillEmployeeName(employeeName);
  114 + await employeePage.fillPhone(phone);
  115 + await employeePage.fillRemark(originalRemark);
  116 + await employeePage.selectPosition();
  117 + await employeePage.clickConfirm();
  118 + });
  119 +
  120 + // 步骤2:搜索员工
  121 + await allure.step('搜索员工', async () => {
  122 + await employeePage.searchEmployee(employeeName);
  123 + await employeePage.verifyEmployeeExists(employeeName);
  124 + });
  125 +
  126 + // 步骤3:点击修改按钮
  127 + await allure.step('点击修改按钮', async () => {
  128 + await employeePage.clickEditButton();
  129 + });
  130 +
  131 + // 步骤4:填写修改信息(姓名和电话不允许修改,只修改备注、状态、岗位)
  132 + await allure.step('填写修改信息', async () => {
  133 + const newRemark = '修改后的备注';
  134 + await employeePage.fillRemarkForEdit(newRemark);
  135 + await employeePage.clickStatusSwitch();
  136 + await employeePage.selectPositionForEdit('采购员');
  137 + });
  138 +
  139 + // 步骤5:保存修改
  140 + await allure.step('保存修改', async () => {
  141 + await employeePage.clickConfirm();
  142 + await employeePage.page.waitForTimeout(1000);
  143 + });
  144 +
  145 + // 步骤6:验证修改成功 - 搜索员工并检查备注是否包含"修改"
  146 + await allure.step('验证修改成功', async () => {
  147 + await employeePage.searchEmployee(employeeName);
  148 + const isSuccess = await employeePage.verifyEmployeeRemarkContains('修改');
  149 + expect(isSuccess).toBeTruthy();
  150 + });
  151 + });
  152 +
  153 + test('解绑员工', async ({ page }, testInfo) => {
  154 + const employeePage = new EmployeePage(page);
  155 +
  156 + // 添加allure元素
  157 + await allure.epic('员工管理');
  158 + await allure.feature('员工信息');
  159 + await allure.story('解绑员工');
  160 +
  161 + // 先生成一个新员工用于解绑测试
  162 + const employeeName = generateEmployeeName();
  163 + const phone = generatePhone();
  164 + const originalRemark = '解绑测试备注';
  165 +
  166 + console.log('待解绑员工姓名:', employeeName);
  167 + console.log('联系电话:', phone);
  168 +
  169 + // 步骤1:新增员工
  170 + await allure.step('新增员工', async () => {
  171 + await employeePage.openEmployeeManagement();
  172 + await employeePage.clickNewEmployee();
  173 + await employeePage.clickManualAdd();
  174 + await employeePage.fillEmployeeName(employeeName);
  175 + await employeePage.fillPhone(phone);
  176 + await employeePage.fillRemark(originalRemark);
  177 + await employeePage.selectPosition();
  178 + await employeePage.clickConfirm();
  179 + });
  180 +
  181 + // 步骤2:搜索员工
  182 + await allure.step('搜索员工', async () => {
  183 + await employeePage.searchEmployee(employeeName);
  184 + await employeePage.verifyEmployeeExists(employeeName);
  185 + });
  186 +
  187 + // 步骤3:点击解绑按钮
  188 + await allure.step('点击解绑按钮', async () => {
  189 + await employeePage.clickUnbindButton();
  190 + });
  191 +
  192 + // 步骤4:确认解绑
  193 + await allure.step('确认解绑', async () => {
  194 + await employeePage.confirmUnbind();
  195 + });
  196 +
  197 + // 步骤5:验证解绑成功 - 页面不再显示该员工
  198 + await allure.step('验证解绑成功', async () => {
  199 + const isNotExists = await employeePage.verifyEmployeeNotExists(employeeName);
  200 + expect(isNotExists).toBeTruthy();
  201 + });
  202 + });
  203 +});
0 \ No newline at end of file 204 \ No newline at end of file