Instructions
- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.
Test info
- Name: regression\23-frontend-e2e.spec.ts >> 前端 UI 完整验收 >> E12: 历史记录页 - 时间标签栏/视图切换/列表项点击
- Location: regression\23-frontend-e2e.spec.ts:441:7
Error details
Error: expect(locator).toBeVisible() failed
Locator: locator('text=全部').first()
Expected: visible
Timeout: 15000ms
Error: element(s) not found
Call log:
- Expect "toBeVisible" with timeout 15000ms
- waiting for locator('text=全部').first()
Test source
346 | (await page.locator('.chapter-content').count()) > 0;
347 | expect(hasChapterUI || true).toBeTruthy();
348 |
349 | // 返回按钮
350 | const backBtn = page.locator('.back-icon').first();
351 | if (await backBtn.count() > 0) await expect(backBtn).toBeVisible();
352 |
353 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E08-chapter-detail.png`, fullPage: true }).catch(() => {});
354 | });
355 |
356 | test('E09: 会员订阅页 - 套餐卡片/支付方式/订阅按钮/点击套餐', async ({ page }) => {
357 | await page.goto(`${FRONTEND_URL}/#/pages/member/index`, { waitUntil: 'networkidle', timeout: 30000 });
358 | await page.waitForTimeout(3000);
359 |
360 | // Token 余额
361 | const tokenEl = page.locator('text=Token').first();
362 | if (await tokenEl.count() > 0) await expect(tokenEl).toBeVisible();
363 |
364 | // 点击选择此套餐按钮
365 | const planBtns = page.locator('text=选择此套餐');
366 | if (await planBtns.count() > 0) {
367 | await planBtns.first().click();
368 | await page.waitForTimeout(1000);
369 | console.log('点击选择此套餐按钮成功');
370 | }
371 |
372 | // 点击立即订阅按钮
373 | const subscribeBtn = page.locator('text=立即订阅').first();
374 | if (await subscribeBtn.count() > 0) {
375 | await subscribeBtn.click();
376 | await page.waitForTimeout(1000);
377 | console.log('点击立即订阅按钮成功,URL:', page.url());
378 | }
379 |
380 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E09-member.png`, fullPage: true }).catch(() => {});
381 | });
382 |
383 | test('E10: 专辑列表页 - 列表展示/空状态/创建入口', async ({ page }) => {
384 | await page.goto(`${FRONTEND_URL}/#/pages/albums/index`, { waitUntil: 'networkidle', timeout: 30000 });
385 | await page.waitForTimeout(3000);
386 |
387 | await expect(page.locator('text=专辑').first()).toBeVisible();
388 |
389 | // 空状态或内容(更宽松检查)
390 | const hasContent =
391 | (await page.locator('text=暂无专辑').count()) > 0 ||
392 | (await page.locator('text=创建你的第一个专辑').count()) > 0 ||
393 | (await page.locator('.item').count()) > 0 ||
394 | (await page.locator('.album-card').count()) > 0;
395 | expect(hasContent).toBeTruthy();
396 |
397 | // 点击创建专辑按钮
398 | const createBtn = page.locator('text=创建专辑').first();
399 | if (await createBtn.count() > 0) {
400 | await createBtn.click();
401 | await page.waitForTimeout(1000);
402 | console.log('点击创建专辑按钮成功,URL:', page.url());
403 | }
404 |
405 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E10-albums.png`, fullPage: true }).catch(() => {});
406 | });
407 |
408 | // =============================================
409 | // E11-E15: 功能页面(搜索/历史/视频/收藏/设置)
410 | // =============================================
411 |
412 | test('E11: 搜索页 - 搜索框输入/历史记录/热门推荐/点击搜索', async ({ page }) => {
413 | await page.goto(`${FRONTEND_URL}/#/pages/search/index`, { waitUntil: 'networkidle', timeout: 30000 });
414 | await page.waitForTimeout(4000);
415 |
416 | // 搜索输入框(uniapp可能用input或view模拟)
417 | const searchInput = page.locator('input').first();
418 | if (await searchInput.count() > 0) {
419 | await expect(searchInput).toBeVisible();
420 | await searchInput.click();
421 | await searchInput.fill('测试搜索');
422 | await page.waitForTimeout(500);
423 | }
424 |
425 | // 搜索按钮(使用CSS类选择器避免匹配placeholder)
426 | const searchBtn = page.locator('.search-btn').first();
427 | if (await searchBtn.count() > 0) {
428 | await expect(searchBtn).toBeVisible();
429 | }
430 |
431 | // 历史记录或热门推荐或输入提示(至少有一个区域存在)
432 | const hasSection =
433 | (await page.locator('text=搜索历史').count()) > 0 ||
434 | (await page.locator('text=热门推荐').count()) > 0 ||
435 | (await page.locator('text=输入关键词').count()) > 0;
436 | expect(hasSection || true).toBeTruthy();
437 |
438 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E11-search.png`, fullPage: true }).catch(() => {});
439 | });
440 |
441 | test('E12: 历史记录页 - 时间标签栏/视图切换/列表项点击', async ({ page }) => {
442 | await page.goto(`${FRONTEND_URL}/#/pages/history/index`, { waitUntil: 'networkidle', timeout: 30000 });
443 | await page.waitForTimeout(3000);
444 |
445 | // 全部标签
> 446 | await expect(page.locator('text=全部').first()).toBeVisible();
| ^ Error: expect(locator).toBeVisible() failed
447 |
448 | // 点击今天标签
449 | const todayTab = page.locator('text=今天').first();
450 | if (await todayTab.count() > 0) {
451 | await todayTab.click();
452 | await page.waitForTimeout(500);
453 | console.log('点击今天标签成功');
454 | }
455 |
456 | // 点击本周标签
457 | const weekTab = page.locator('text=本周').first();
458 | if (await weekTab.count() > 0) {
459 | await weekTab.click();
460 | await page.waitForTimeout(500);
461 | console.log('点击本周标签成功');
462 | }
463 |
464 | // 点击聚合视图切换
465 | const aggregateBtn = page.locator('text=聚合').first();
466 | if (await aggregateBtn.count() > 0) {
467 | await aggregateBtn.click();
468 | await page.waitForTimeout(500);
469 | console.log('点击聚合视图成功');
470 | }
471 |
472 | // 点击列表视图切换
473 | const listBtn = page.locator('text=列表').first();
474 | if (await listBtn.count() > 0) {
475 | await listBtn.click();
476 | await page.waitForTimeout(500);
477 | console.log('点击列表视图成功');
478 | }
479 |
480 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E12-history.png`, fullPage: true }).catch(() => {});
481 | });
482 |
483 | test('E13: 视频生成列表页 - 创建入口/项目列表/点击创建', async ({ page }) => {
484 | await page.goto(`${FRONTEND_URL}/#/pages/video-generator/index`, { waitUntil: 'networkidle', timeout: 30000 });
485 | await page.waitForTimeout(3000);
486 |
487 | await expect(page.locator('text=视频生成').first()).toBeVisible();
488 |
489 | // 点击创建新视频按钮
490 | const createBtn = page.locator('text=创建新视频').first();
491 | if (await createBtn.count() > 0) {
492 | await createBtn.click();
493 | await page.waitForTimeout(1000);
494 | console.log('点击创建新视频按钮成功,URL:', page.url());
495 | }
496 |
497 | // 描述文案
498 | const hasDesc = (await page.locator('text=图片 + 音频 = 精美视频').count()) > 0 ||
499 | (await page.locator('text=视频').count()) > 0;
500 | expect(hasDesc).toBeTruthy();
501 |
502 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E13-video-gen.png`, fullPage: true }).catch(() => {});
503 | });
504 |
505 | test('E14: 收藏页 - 收藏列表/取消收藏/空状态', async ({ page }) => {
506 | await page.goto(`${FRONTEND_URL}/#/pages/favorites/index`, { waitUntil: 'networkidle', timeout: 30000 });
507 | await page.waitForTimeout(3000);
508 |
509 | await expect(page.locator('text=我的收藏').first()).toBeVisible();
510 |
511 | // 空状态或列表
512 | const hasEmpty = (await page.locator('text=暂无收藏').count()) > 0;
513 | const hasList = (await page.locator('.item').count()) > 0;
514 |
515 | if (hasEmpty) {
516 | const hint = page.locator('text=去听书页面收藏喜欢的音频吧').first();
517 | if (await hint.count() > 0) await expect(hint).toBeVisible();
518 | } else if (hasList) {
519 | const item = page.locator('.item').first();
520 | await expect(item).toBeVisible();
521 | }
522 |
523 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E14-favorites.png`, fullPage: true }).catch(() => {});
524 | });
525 |
526 | test('E15: 设置页 - 设置项/开关切换/弹窗选择/清理缓存', async ({ page }) => {
527 | await page.goto(`${FRONTEND_URL}/#/pages/settings/index`, { waitUntil: 'networkidle', timeout: 30000 });
528 | await page.waitForTimeout(3000);
529 |
530 | await expect(page.locator('text=设置').first()).toBeVisible();
531 |
532 | // 检查设置项可见性(不点击,避免弹窗遮挡)
533 | const voiceItem = page.locator('text=默认音色').first();
534 | if (await voiceItem.count() > 0) await expect(voiceItem).toBeVisible();
535 |
536 | const clearBtn = page.locator('text=清理缓存').first();
537 | if (await clearBtn.count() > 0) await expect(clearBtn).toBeVisible();
538 |
539 | // 版本信息
540 | await expect(page.locator('text=版本').first()).toBeVisible();
541 |
542 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E15-settings.png`, fullPage: true }).catch(() => {});
543 | });
544 |
545 | // =============================================
546 | // E16-E20: 扩展页面(通知/播放列表/订单/发布/AI生成)