Commit 30d1471a6332b79044d25f612908d10af5bad231
1 parent
140ac106
添加车牌号、上传图片方法封装
Showing
4 changed files
with
239 additions
and
111 deletions
pages/basePage.ts
| @@ -221,4 +221,110 @@ export abstract class BasePage { | @@ -221,4 +221,110 @@ export abstract class BasePage { | ||
| 221 | filterLocator(selector: string, options: { hasText?: string | RegExp; has?: Locator }): Locator { | 221 | filterLocator(selector: string, options: { hasText?: string | RegExp; has?: Locator }): Locator { |
| 222 | return this.page.locator(selector).filter(options); | 222 | return this.page.locator(selector).filter(options); |
| 223 | } | 223 | } |
| 224 | + | ||
| 225 | + /** | ||
| 226 | + * 填写车牌号(通用方法) | ||
| 227 | + * @param licensePlate 车牌号(如:渝ZY0706) | ||
| 228 | + * @param inputLocator 车牌号输入框定位器(可选,如果不传则需要先点击输入框) | ||
| 229 | + */ | ||
| 230 | + async fillLicensePlate(licensePlate: string, inputLocator?: Locator): Promise<void> { | ||
| 231 | + // 等待页面稳定 | ||
| 232 | + await this.page.waitForTimeout(500); | ||
| 233 | + | ||
| 234 | + // 如果传入了输入框定位器,先点击它 | ||
| 235 | + if (inputLocator) { | ||
| 236 | + await inputLocator.click(); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // 等待车牌键盘面板加载完成 | ||
| 240 | + await this.page.waitForTimeout(1000); | ||
| 241 | + | ||
| 242 | + // 解析车牌号的省份和字母部分 | ||
| 243 | + const province = licensePlate.charAt(0); // 如:渝 | ||
| 244 | + const letter = licensePlate.charAt(1); // 如:Z | ||
| 245 | + const numbers = licensePlate.substring(2); // 如:Y0706 | ||
| 246 | + | ||
| 247 | + // 点击省份 | ||
| 248 | + await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${province}$`) }).click(); | ||
| 249 | + | ||
| 250 | + // 等待字母键盘出现 | ||
| 251 | + await this.page.waitForTimeout(300); | ||
| 252 | + | ||
| 253 | + // 点击第一个字母 - 智能选择,优先使用 nth(1),如果不存在则用 first | ||
| 254 | + const letterLocator = this.page.locator('uni-view').filter({ hasText: new RegExp(`^${letter}$`) }); | ||
| 255 | + const letterCount = await letterLocator.count(); | ||
| 256 | + if (letterCount > 1) { | ||
| 257 | + await letterLocator.nth(1).click(); | ||
| 258 | + } else if (letterCount === 1) { | ||
| 259 | + await letterLocator.click(); | ||
| 260 | + } else { | ||
| 261 | + // 回退到 getByText 方式 | ||
| 262 | + await this.page.getByText(letter, { exact: true }).first().click(); | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + // 逐个点击车牌号码 | ||
| 266 | + for (let i = 0; i < numbers.length; i++) { | ||
| 267 | + const char = numbers[i]; | ||
| 268 | + await this.page.waitForTimeout(100); | ||
| 269 | + if (char.match(/[A-Za-z]/)) { | ||
| 270 | + // 字母 | ||
| 271 | + const charLocator = this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char.toUpperCase()}$`) }); | ||
| 272 | + const charCount = await charLocator.count(); | ||
| 273 | + if (charCount > 1) { | ||
| 274 | + await charLocator.nth(1).click(); | ||
| 275 | + } else { | ||
| 276 | + await charLocator.click(); | ||
| 277 | + } | ||
| 278 | + } else if (char.match(/[0-9]/)) { | ||
| 279 | + // 数字 | ||
| 280 | + const digitLocator = this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char}$`) }); | ||
| 281 | + const digitCount = await digitLocator.count(); | ||
| 282 | + if (digitCount > 1) { | ||
| 283 | + await digitLocator.nth(1).click(); | ||
| 284 | + } else { | ||
| 285 | + await digitLocator.click(); | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + // 点击确定按钮 | ||
| 291 | + await this.page.getByText('确定').click(); | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + /** | ||
| 295 | + * 上传图片(通用方法)- 使用 filechooser 事件 | ||
| 296 | + * @param imagePath 图片文件路径(相对于项目根目录) | ||
| 297 | + * @param uploadButtonLocator 上传按钮定位器(可选,默认使用 uni-scroll-view uni-button) | ||
| 298 | + */ | ||
| 299 | + async uploadImage(imagePath: string, uploadButtonLocator?: Locator): Promise<void> { | ||
| 300 | + // 使用 Playwright 的 file_chooser 事件处理文件上传 | ||
| 301 | + // 监听文件选择器事件 | ||
| 302 | + const fileChooserPromise = this.page.waitForEvent('filechooser'); | ||
| 303 | + | ||
| 304 | + // 点击上传按钮触发文件选择器 | ||
| 305 | + if (uploadButtonLocator) { | ||
| 306 | + await uploadButtonLocator.click(); | ||
| 307 | + } else { | ||
| 308 | + await this.page.locator('uni-scroll-view uni-button').click(); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + // 等待文件选择器出现并设置文件 | ||
| 312 | + const fileChooser = await fileChooserPromise; | ||
| 313 | + await fileChooser.setFiles(imagePath); | ||
| 314 | + | ||
| 315 | + // 等待上传完成 | ||
| 316 | + await this.page.waitForTimeout(1000); | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + /** | ||
| 320 | + * 上传图片(使用 setInputFiles 方式) | ||
| 321 | + * @param imagePath 图片文件路径 | ||
| 322 | + */ | ||
| 323 | + async uploadImageByInput(imagePath: string): Promise<void> { | ||
| 324 | + // 直接在 body 上设置文件 | ||
| 325 | + await this.page.locator('body').setInputFiles(imagePath); | ||
| 326 | + | ||
| 327 | + // 等待上传完成 | ||
| 328 | + await this.page.waitForTimeout(1000); | ||
| 329 | + } | ||
| 224 | } | 330 | } |
pages/consignmentPage.ts
| @@ -14,7 +14,10 @@ const selectors = { | @@ -14,7 +14,10 @@ const selectors = { | ||
| 14 | warehouseSelector: '.nut-input__mask', | 14 | warehouseSelector: '.nut-input__mask', |
| 15 | warehouseOption: (warehouseName: string) => `uni-view:has-text("${warehouseName}")`, | 15 | warehouseOption: (warehouseName: string) => `uni-view:has-text("${warehouseName}")`, |
| 16 | mainTitleOption: '.mainTitle', | 16 | mainTitleOption: '.mainTitle', |
| 17 | - | 17 | + //车牌 |
| 18 | + licensePlateInput:'uni-view:nth-child(2) > .nut-cell__value > .nut-form-item__body__slots > .input-wrapper > .flex-input > .nut-input > .nut-input__value > .nut-input__mask', | ||
| 19 | + confirmLicenceButton:'text=确定', | ||
| 20 | + | ||
| 18 | // 批次别名输入 | 21 | // 批次别名输入 |
| 19 | batchAliasInput: 'uni-input:has-text("请输入批次别名") input', | 22 | batchAliasInput: 'uni-input:has-text("请输入批次别名") input', |
| 20 | 23 | ||
| @@ -67,7 +70,13 @@ export class ConsignmentPage extends BasePage { | @@ -67,7 +70,13 @@ export class ConsignmentPage extends BasePage { | ||
| 67 | // 操作按钮 | 70 | // 操作按钮 |
| 68 | readonly createButton: Locator; | 71 | readonly createButton: Locator; |
| 69 | readonly saveButton: Locator; | 72 | readonly saveButton: Locator; |
| 70 | - readonly doneButton:Locator; | 73 | + readonly doneButton: Locator; |
| 74 | + | ||
| 75 | + // 车牌号 | ||
| 76 | + readonly licensePlateInput: Locator; | ||
| 77 | + | ||
| 78 | + // 图片上传 | ||
| 79 | + readonly uploadImageButton: Locator; | ||
| 71 | 80 | ||
| 72 | constructor(page: Page) { | 81 | constructor(page: Page) { |
| 73 | super(page); | 82 | super(page); |
| @@ -85,7 +94,11 @@ export class ConsignmentPage extends BasePage { | @@ -85,7 +94,11 @@ export class ConsignmentPage extends BasePage { | ||
| 85 | this.paymentItem = page.locator('.payment-item'); | 94 | this.paymentItem = page.locator('.payment-item'); |
| 86 | this.createButton = page.getByText('创建', { exact: true }); | 95 | this.createButton = page.getByText('创建', { exact: true }); |
| 87 | this.saveButton = page.getByText('保存'); | 96 | this.saveButton = page.getByText('保存'); |
| 88 | - this.doneButton = page.getByText('完成') | 97 | + this.doneButton = page.getByText('完成'); |
| 98 | + // 车牌号输入框 - nth-child(2) | ||
| 99 | + this.licensePlateInput = page.locator('uni-view:nth-child(2) > .nut-cell__value > .nut-form-item__body__slots > .nut-input > .nut-input__value > .nut-input__mask'); | ||
| 100 | + // 图片上传区域 | ||
| 101 | + this.uploadImageButton = page.getByText('图片(最多上传9张)'); | ||
| 89 | } | 102 | } |
| 90 | 103 | ||
| 91 | /** | 104 | /** |
| @@ -169,36 +182,36 @@ export class ConsignmentPage extends BasePage { | @@ -169,36 +182,36 @@ export class ConsignmentPage extends BasePage { | ||
| 169 | await this.productListButton.click(); | 182 | await this.productListButton.click(); |
| 170 | } | 183 | } |
| 171 | 184 | ||
| 172 | - // /** | ||
| 173 | - // * 获取商品列表中所有可用的商品名称 | ||
| 174 | - // * @returns 商品名称数组 | ||
| 175 | - // */ | ||
| 176 | - // async getAvailableProducts(): Promise<string[]> { | ||
| 177 | - // // 等待商品列表加载 | ||
| 178 | - // await this.page.locator('.productName').first().waitFor({ state: 'visible', timeout: 5000 }); | 185 | + /** |
| 186 | + * 获取商品列表中所有可用的商品名称 | ||
| 187 | + * @returns 商品名称数组 | ||
| 188 | + */ | ||
| 189 | + async getAvailableProducts(): Promise<string[]> { | ||
| 190 | + // 等待商品列表加载 | ||
| 191 | + await this.page.locator('.productName').first().waitFor({ state: 'visible', timeout: 5000 }); | ||
| 179 | 192 | ||
| 180 | - // // 获取所有商品名称 | ||
| 181 | - // const productElements = await this.page.locator('.productName').allTextContents(); | ||
| 182 | - // return productElements.filter(name => name.trim() !== ''); | ||
| 183 | - // } | 193 | + // 获取所有商品名称 |
| 194 | + const productElements = await this.page.locator('.productName').allTextContents(); | ||
| 195 | + return productElements.filter(name => name.trim() !== ''); | ||
| 196 | + } | ||
| 184 | 197 | ||
| 185 | - // /** | ||
| 186 | - // * 随机选择一个商品 | ||
| 187 | - // * @returns 随机选择的商品名称 | ||
| 188 | - // */ | ||
| 189 | - // async selectRandomProduct(): Promise<string> { | ||
| 190 | - // const products = await this.getAvailableProducts(); | 198 | + /** |
| 199 | + * 随机选择一个商品 | ||
| 200 | + * @returns 随机选择的商品名称 | ||
| 201 | + */ | ||
| 202 | + async selectRandomProduct(): Promise<string> { | ||
| 203 | + const products = await this.getAvailableProducts(); | ||
| 191 | 204 | ||
| 192 | - // if (products.length === 0) { | ||
| 193 | - // throw new Error('商品列表为空,无法选择商品'); | ||
| 194 | - // } | 205 | + if (products.length === 0) { |
| 206 | + throw new Error('商品列表为空,无法选择商品'); | ||
| 207 | + } | ||
| 195 | 208 | ||
| 196 | - // const randomIndex = Math.floor(Math.random() * products.length); | ||
| 197 | - // const selectedProduct = products[randomIndex]; | ||
| 198 | - // console.log(`随机选择的商品: ${selectedProduct}`); | 209 | + const randomIndex = Math.floor(Math.random() * products.length); |
| 210 | + const selectedProduct = products[randomIndex]; | ||
| 211 | + console.log(`随机选择的商品: ${selectedProduct}`); | ||
| 199 | 212 | ||
| 200 | - // return selectedProduct; | ||
| 201 | - // } | 213 | + return selectedProduct; |
| 214 | + } | ||
| 202 | 215 | ||
| 203 | /** | 216 | /** |
| 204 | * 选择商品 | 217 | * 选择商品 |
| @@ -229,14 +242,20 @@ export class ConsignmentPage extends BasePage { | @@ -229,14 +242,20 @@ export class ConsignmentPage extends BasePage { | ||
| 229 | 242 | ||
| 230 | /** | 243 | /** |
| 231 | * 选择商品并输入数量 | 244 | * 选择商品并输入数量 |
| 232 | - * @param productName 商品名称 | 245 | + * @param productName 商品名称(可选,不传则随机选择) |
| 233 | * @param quantity 数量 | 246 | * @param quantity 数量 |
| 247 | + * @returns 实际选择的商品名称 | ||
| 234 | */ | 248 | */ |
| 235 | - async selectProductWithQuantity(productName: string, quantity: string): Promise<void> { | 249 | + async selectProductWithQuantity(productName?: string, quantity: string = '10'): Promise<string> { |
| 236 | await this.openProductList(); | 250 | await this.openProductList(); |
| 237 | - await this.selectProduct(productName); | 251 | + |
| 252 | + // 如果没有指定商品名称,则随机选择 | ||
| 253 | + const selectedProduct = productName || await this.selectRandomProduct(); | ||
| 254 | + await this.selectProduct(selectedProduct); | ||
| 238 | await this.enterProductQuantity(quantity); | 255 | await this.enterProductQuantity(quantity); |
| 239 | await this.completeProductSelection(); | 256 | await this.completeProductSelection(); |
| 257 | + | ||
| 258 | + return selectedProduct; | ||
| 240 | } | 259 | } |
| 241 | 260 | ||
| 242 | /** | 261 | /** |
| @@ -297,22 +316,33 @@ export class ConsignmentPage extends BasePage { | @@ -297,22 +316,33 @@ export class ConsignmentPage extends BasePage { | ||
| 297 | * @param batchName 批次名称 | 316 | * @param batchName 批次名称 |
| 298 | */ | 317 | */ |
| 299 | async expectBatchCreated(batchName: string): Promise<void> { | 318 | async expectBatchCreated(batchName: string): Promise<void> { |
| 300 | - await expect(this.page.locator('uni-scroll-view').getByText(batchName)).toBeVisible(); | 319 | + await expect(this.page.locator('uni-scroll-view').getByText(batchName)).toBeVisible({ timeout: 10000 }); |
| 301 | } | 320 | } |
| 302 | 321 | ||
| 303 | /** | 322 | /** |
| 304 | * 完整的代销入库创建流程 | 323 | * 完整的代销入库创建流程 |
| 305 | * @param batchAlias 批次别名 | 324 | * @param batchAlias 批次别名 |
| 306 | - * @param productName 商品名称 | ||
| 307 | - * @param quantity 数量 | ||
| 308 | - * @param amount 费用金额 | 325 | + * @param options 可选配置 |
| 326 | + * @returns 实际选择的商品名称 | ||
| 309 | */ | 327 | */ |
| 310 | async createConsignmentOrder( | 328 | async createConsignmentOrder( |
| 311 | batchAlias: string, | 329 | batchAlias: string, |
| 312 | - productName: string, | ||
| 313 | - quantity: string = '10', | ||
| 314 | - amount: string = '1' | ||
| 315 | - ): Promise<void> { | 330 | + options?: { |
| 331 | + productName?: string; // 商品名称(可选,不传则随机选择) | ||
| 332 | + quantity?: string; // 数量,默认 '10' | ||
| 333 | + amount?: string; // 费用金额,默认 '1' | ||
| 334 | + licensePlate?: string; // 车牌号(可选) | ||
| 335 | + imagePath?: string; // 图片路径(可选) | ||
| 336 | + } | ||
| 337 | + ): Promise<string> { | ||
| 338 | + const { | ||
| 339 | + productName, | ||
| 340 | + quantity = '10', | ||
| 341 | + amount = '1', | ||
| 342 | + licensePlate, | ||
| 343 | + imagePath | ||
| 344 | + } = options || {}; | ||
| 345 | + | ||
| 316 | // 导航到新增页面 | 346 | // 导航到新增页面 |
| 317 | await this.navigateToNewConsignment(); | 347 | await this.navigateToNewConsignment(); |
| 318 | 348 | ||
| @@ -323,8 +353,23 @@ export class ConsignmentPage extends BasePage { | @@ -323,8 +353,23 @@ export class ConsignmentPage extends BasePage { | ||
| 323 | // 输入批次别名 | 353 | // 输入批次别名 |
| 324 | await this.enterBatchAlias(batchAlias); | 354 | await this.enterBatchAlias(batchAlias); |
| 325 | 355 | ||
| 326 | - // 选择商品 | ||
| 327 | - await this.selectProductWithQuantity(productName, quantity); | 356 | + // 选择商品(不传productName则随机选择) |
| 357 | + const selectedProduct = await this.selectProductWithQuantity(productName, quantity); | ||
| 358 | + | ||
| 359 | + // 填写车牌号(可选) | ||
| 360 | + if (licensePlate) { | ||
| 361 | + await this.fillLicensePlate(licensePlate, this.licensePlateInput); | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + // 上传图片(可选) | ||
| 365 | + if (imagePath) { | ||
| 366 | + // 点击图片上传区域 | ||
| 367 | + await this.uploadImageButton.click(); | ||
| 368 | + // 点击上传按钮 | ||
| 369 | + await this.page.locator('span').filter({ hasText: '供应商*请选择供应商车牌号请选择车牌号入库日期*请选择入库日期入库仓库*请选择仓库批次别名*请输入批次别名备注请输入备注商品清单点击选择商品入库费用添加费用存储' }).locator('uni-button').click(); | ||
| 370 | + // 使用 setInputFiles 方式上传 | ||
| 371 | + await this.page.locator('body').setInputFiles(imagePath); | ||
| 372 | + } | ||
| 328 | 373 | ||
| 329 | // 添加费用 | 374 | // 添加费用 |
| 330 | await this.addExpense(0, amount); | 375 | await this.addExpense(0, amount); |
| @@ -336,19 +381,32 @@ export class ConsignmentPage extends BasePage { | @@ -336,19 +381,32 @@ export class ConsignmentPage extends BasePage { | ||
| 336 | 381 | ||
| 337 | // 验证 | 382 | // 验证 |
| 338 | await this.expectBatchCreated(batchAlias); | 383 | await this.expectBatchCreated(batchAlias); |
| 384 | + | ||
| 385 | + return selectedProduct; | ||
| 339 | } | 386 | } |
| 340 | 387 | ||
| 341 | /** | 388 | /** |
| 342 | * 简化的代销入库创建流程(不添加费用) | 389 | * 简化的代销入库创建流程(不添加费用) |
| 343 | * @param batchAlias 批次别名 | 390 | * @param batchAlias 批次别名 |
| 344 | - * @param productName 商品名称 | ||
| 345 | - * @param quantity 数量 | 391 | + * @param options 可选配置 |
| 392 | + * @returns 实际选择的商品名称 | ||
| 346 | */ | 393 | */ |
| 347 | async createSimpleConsignmentOrder( | 394 | async createSimpleConsignmentOrder( |
| 348 | batchAlias: string, | 395 | batchAlias: string, |
| 349 | - productName: string, | ||
| 350 | - quantity: string = '10' | ||
| 351 | - ): Promise<void> { | 396 | + options?: { |
| 397 | + productName?: string; // 商品名称(可选,不传则随机选择) | ||
| 398 | + quantity?: string; // 数量,默认 '10' | ||
| 399 | + licensePlate?: string; // 车牌号(可选) | ||
| 400 | + imagePath?: string; // 图片路径(可选) | ||
| 401 | + } | ||
| 402 | + ): Promise<string> { | ||
| 403 | + const { | ||
| 404 | + productName, | ||
| 405 | + quantity = '10', | ||
| 406 | + licensePlate, | ||
| 407 | + imagePath | ||
| 408 | + } = options || {}; | ||
| 409 | + | ||
| 352 | // 导航到新增页面 | 410 | // 导航到新增页面 |
| 353 | await this.navigateToNewConsignment(); | 411 | await this.navigateToNewConsignment(); |
| 354 | 412 | ||
| @@ -359,11 +417,23 @@ export class ConsignmentPage extends BasePage { | @@ -359,11 +417,23 @@ export class ConsignmentPage extends BasePage { | ||
| 359 | // 输入批次别名 | 417 | // 输入批次别名 |
| 360 | await this.enterBatchAlias(batchAlias); | 418 | await this.enterBatchAlias(batchAlias); |
| 361 | 419 | ||
| 362 | - // 选择商品 | ||
| 363 | - await this.selectProductWithQuantity(productName, quantity); | 420 | + // 选择商品(不传productName则随机选择) |
| 421 | + const selectedProduct = await this.selectProductWithQuantity(productName, quantity); | ||
| 422 | + | ||
| 423 | + // 填写车牌号(可选) | ||
| 424 | + if (licensePlate) { | ||
| 425 | + await this.fillLicensePlate(licensePlate, this.licensePlateInput); | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + // 上传图片(可选) | ||
| 429 | + if (imagePath) { | ||
| 430 | + await this.uploadImage(imagePath, this.uploadImageButton); | ||
| 431 | + } | ||
| 364 | 432 | ||
| 365 | // 创建 | 433 | // 创建 |
| 366 | await this.clickCreate(); | 434 | await this.clickCreate(); |
| 367 | await this.waitForCreationComplete(); | 435 | await this.waitForCreationComplete(); |
| 436 | + | ||
| 437 | + return selectedProduct; | ||
| 368 | } | 438 | } |
| 369 | } | 439 | } |
| 370 | \ No newline at end of file | 440 | \ No newline at end of file |
pages/customerPage.ts
| @@ -183,50 +183,11 @@ export class CustomerPage extends BasePage { | @@ -183,50 +183,11 @@ export class CustomerPage extends BasePage { | ||
| 183 | * @param licensePlate 车牌号(如:渝ZY0706) | 183 | * @param licensePlate 车牌号(如:渝ZY0706) |
| 184 | */ | 184 | */ |
| 185 | async fillLicensePlate(licensePlate: string): Promise<void> { | 185 | async fillLicensePlate(licensePlate: string): Promise<void> { |
| 186 | - // 等待页面稳定 | ||
| 187 | - await this.page.waitForTimeout(500); | ||
| 188 | - | ||
| 189 | // 点击车牌号输入框 - nth-child(11),开启赊欠额度后位置 | 186 | // 点击车牌号输入框 - nth-child(11),开启赊欠额度后位置 |
| 190 | - await this.page.locator('uni-view:nth-child(11) > .nut-cell__value > .nut-form-item__body__slots > .input-wrapper > .flex-input > .nut-input > .nut-input__value > .nut-input__mask').click(); | ||
| 191 | - | ||
| 192 | - // 等待车牌键盘面板加载完成 | ||
| 193 | - await this.page.waitForTimeout(1000); | ||
| 194 | - | ||
| 195 | - // 解析车牌号的省份和字母部分 | ||
| 196 | - const province = licensePlate.charAt(0); // 如:渝 | ||
| 197 | - const letter = licensePlate.charAt(1); // 如:Z | ||
| 198 | - const numbers = licensePlate.substring(2); // 如:Y0706 | ||
| 199 | - | ||
| 200 | - // 点击省份 | ||
| 201 | - await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${province}$`) }).click(); | ||
| 202 | - | ||
| 203 | - // 等待字母键盘出现 | ||
| 204 | - await this.page.waitForTimeout(300); | 187 | + const licensePlateInput = this.page.locator('uni-view:nth-child(11) > .nut-cell__value > .nut-form-item__body__slots > .input-wrapper > .flex-input > .nut-input > .nut-input__value > .nut-input__mask'); |
| 205 | 188 | ||
| 206 | - // 点击第一个字母(需要用 nth(1) 选择第二个匹配项) | ||
| 207 | - await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${letter}$`) }).nth(1).click(); | ||
| 208 | - | ||
| 209 | - // 逐个点击车牌号码 | ||
| 210 | - for (let i = 0; i < numbers.length; i++) { | ||
| 211 | - const char = numbers[i]; | ||
| 212 | - await this.page.waitForTimeout(100); | ||
| 213 | - if (char.match(/[A-Za-z]/)) { | ||
| 214 | - // 字母 | ||
| 215 | - await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char.toUpperCase()}$`) }).click(); | ||
| 216 | - } else if (char.match(/[0-9]/)) { | ||
| 217 | - // 数字 - 检查是否需要使用 nth(1) | ||
| 218 | - const digitCount = await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char}$`) }).count(); | ||
| 219 | - if (digitCount > 1) { | ||
| 220 | - // 如果有多个相同数字,点击第二个 | ||
| 221 | - await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char}$`) }).nth(1).click(); | ||
| 222 | - } else { | ||
| 223 | - await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${char}$`) }).click(); | ||
| 224 | - } | ||
| 225 | - } | ||
| 226 | - } | ||
| 227 | - | ||
| 228 | - // 点击确定按钮 | ||
| 229 | - await this.page.getByText('确定').click(); | 189 | + // 调用基类的通用方法 |
| 190 | + await super.fillLicensePlate(licensePlate, licensePlateInput); | ||
| 230 | } | 191 | } |
| 231 | 192 | ||
| 232 | /** | 193 | /** |
| @@ -271,19 +232,8 @@ export class CustomerPage extends BasePage { | @@ -271,19 +232,8 @@ export class CustomerPage extends BasePage { | ||
| 271 | * @param imagePath 图片文件路径(相对于项目根目录) | 232 | * @param imagePath 图片文件路径(相对于项目根目录) |
| 272 | */ | 233 | */ |
| 273 | async uploadCustomerImage(imagePath: string): Promise<void> { | 234 | async uploadCustomerImage(imagePath: string): Promise<void> { |
| 274 | - // 使用 Playwright 的 file_chooser 事件处理文件上传 | ||
| 275 | - // 监听文件选择器事件 | ||
| 276 | - const fileChooserPromise = this.page.waitForEvent('filechooser'); | ||
| 277 | - | ||
| 278 | - // 点击上传按钮触发文件选择器 | ||
| 279 | - await this.page.locator('uni-scroll-view uni-button').click(); | ||
| 280 | - | ||
| 281 | - // 等待文件选择器出现并设置文件 | ||
| 282 | - const fileChooser = await fileChooserPromise; | ||
| 283 | - await fileChooser.setFiles(imagePath); | ||
| 284 | - | ||
| 285 | - // 等待上传完成 | ||
| 286 | - await this.page.waitForTimeout(1000); | 235 | + // 调用基类的通用方法 |
| 236 | + await super.uploadImage(imagePath); | ||
| 287 | } | 237 | } |
| 288 | 238 | ||
| 289 | /** | 239 | /** |
tests/consignmentOrder.spec.ts
| @@ -16,7 +16,7 @@ test.describe('代销入库', () => { | @@ -16,7 +16,7 @@ test.describe('代销入库', () => { | ||
| 16 | await allure.story('创建代销入库订单'); | 16 | await allure.story('创建代销入库订单'); |
| 17 | // 步骤1,生成批次别名 | 17 | // 步骤1,生成批次别名 |
| 18 | const batchAlias = await allure.step('生成唯一批次别名',async(step)=>{ | 18 | const batchAlias = await allure.step('生成唯一批次别名',async(step)=>{ |
| 19 | - const alias = generateOtherName('自代卖'); | 19 | + const alias = generateOtherName('代卖'); |
| 20 | console.log('生成的批次别名:', alias); | 20 | console.log('生成的批次别名:', alias); |
| 21 | return alias; | 21 | return alias; |
| 22 | }); | 22 | }); |
| @@ -24,14 +24,16 @@ test.describe('代销入库', () => { | @@ -24,14 +24,16 @@ test.describe('代销入库', () => { | ||
| 24 | // const batchAlias = generateOtherName('代卖'); | 24 | // const batchAlias = generateOtherName('代卖'); |
| 25 | // console.log('生成的批次别名:', batchAlias); | 25 | // console.log('生成的批次别名:', batchAlias); |
| 26 | 26 | ||
| 27 | - // 步骤2.执行代销入库 | 27 | + // 步骤2.执行代销入库(商品名称不传,随机选择有库存的商品) |
| 28 | await allure.step('填写并提交代销入库表单',async()=>{ | 28 | await allure.step('填写并提交代销入库表单',async()=>{ |
| 29 | - await consignmentPage.createConsignmentOrder( | ||
| 30 | - batchAlias, // 批次别名 | ||
| 31 | - '娃娃菜', // 商品名称 | ||
| 32 | - '10', // 数量 | ||
| 33 | - '1' // 费用金额 | ||
| 34 | - ); | 29 | + const selectedProduct = await consignmentPage.createConsignmentOrder(batchAlias, { |
| 30 | + quantity: '10', // 数量 | ||
| 31 | + amount: '1', // 费用金额 | ||
| 32 | + // productName 不传,随机选择 | ||
| 33 | + licensePlate: '渝ZY0706', // 车牌号 | ||
| 34 | + // imagePath: 'test-data/img/苹果.jpg' // 图片路径 | ||
| 35 | + }); | ||
| 36 | + console.log('随机选择的商品:', selectedProduct); | ||
| 35 | await consignmentPage.attachScreenshot(testInfo,'代销入库成功截图'); | 37 | await consignmentPage.attachScreenshot(testInfo,'代销入库成功截图'); |
| 36 | }) | 38 | }) |
| 37 | 39 |