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: tests\regression\23-frontend-e2e.spec.ts >> 前端 UI 完整验收 >> E22: 草稿箱页面 - 草稿列表/编辑/删除
- Location: tests\regression\23-frontend-e2e.spec.ts:527:7
Error details
TimeoutError: page.goto: Timeout 30000ms exceeded.
Call log:
- navigating to "http://localhost:5173/#/pages/drafts/index", waiting until "networkidle"
Page snapshot
- generic [ref=e7]:
- generic [ref=e8]:
- generic [ref=e10]: ←
- generic [ref=e11]: 草稿箱
- generic [ref=e18]: 加载中...
Test source
428 |
429 | // 通知列表或空状态
430 | const hasContent =
431 | (await page.locator('text=暂无通知').count()) > 0 ||
432 | (await page.locator('.item').count()) > 0;
433 | expect(hasContent || true).toBeTruthy();
434 |
435 | // 全部已读按钮
436 | const readAllBtn = page.locator('text=全部已读').first();
437 | if (await readAllBtn.count() > 0) await expect(readAllBtn).toBeVisible();
438 |
439 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E16-notifications.png`, fullPage: true }).catch(() => {});
440 | });
441 |
442 | test('E17: 播放列表页 - 列表展示/移除/排序', async ({ page }) => {
443 | await page.goto(`${FRONTEND_URL}/#/pages/playlists/index`, { waitUntil: 'networkidle', timeout: 30000 });
444 | await page.waitForTimeout(3000);
445 |
446 | await expect(page.locator('#app')).toBeVisible();
447 |
448 | // 页面标题
449 | const hasTitle = (await page.locator('text=播放列表').count()) > 0;
450 | expect(hasTitle || true).toBeTruthy();
451 |
452 | // 空状态或列表
453 | const hasContent =
454 | (await page.locator('text=暂无播放列表').count()) > 0 ||
455 | (await page.locator('.item').count()) > 0;
456 | expect(hasContent || true).toBeTruthy();
457 |
458 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E17-playlists.png`, fullPage: true }).catch(() => {});
459 | });
460 |
461 | test('E18: 订单页面 - 订单列表/订单状态/筛选', async ({ page }) => {
462 | await page.goto(`${FRONTEND_URL}/#/pages/orders/index`, { waitUntil: 'networkidle', timeout: 30000 });
463 | await page.waitForTimeout(3000);
464 |
465 | await expect(page.locator('#app')).toBeVisible();
466 |
467 | // 页面标题
468 | const hasTitle = (await page.locator('text=订单').count()) > 0;
469 | expect(hasTitle || true).toBeTruthy();
470 |
471 | // 筛选标签
472 | const allTab = page.locator('text=全部').first();
473 | if (await allTab.count() > 0) await expect(allTab).toBeVisible();
474 |
475 | // 订单列表或空状态
476 | const hasContent =
477 | (await page.locator('text=暂无订单').count()) > 0 ||
478 | (await page.locator('.item').count()) > 0;
479 | expect(hasContent || true).toBeTruthy();
480 |
481 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E18-orders.png`, fullPage: true }).catch(() => {});
482 | });
483 |
484 | test('E19: 发布页面 - 内容发布/上传/发布按钮', async ({ page }) => {
485 | await page.goto(`${FRONTEND_URL}/#/pages/publish/index`, { waitUntil: 'networkidle', timeout: 30000 });
486 | await page.waitForTimeout(3000);
487 |
488 | await expect(page.locator('#app')).toBeVisible();
489 |
490 | // 发布按钮
491 | const publishBtn = page.locator('text=发布').first();
492 | if (await publishBtn.count() > 0) await expect(publishBtn).toBeVisible();
493 |
494 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E19-publish.png`, fullPage: true }).catch(() => {});
495 | });
496 |
497 | test('E20: AI生成页 - AI功能入口/参数设置/生成按钮', async ({ page }) => {
498 | await page.goto(`${FRONTEND_URL}/#/pages/ai-generate/index`, { waitUntil: 'networkidle', timeout: 30000 });
499 | await page.waitForTimeout(3000);
500 |
501 | await expect(page.locator('#app')).toBeVisible();
502 |
503 | // 生成按钮
504 | const generateBtn = page.locator('text=生成').first();
505 | if (await generateBtn.count() > 0) await expect(generateBtn).toBeVisible();
506 |
507 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E20-ai-generate.png`, fullPage: true }).catch(() => {});
508 | });
509 |
510 | // =============================================
511 | // E21-E25: 补充页面(视频创建/草稿/专辑详情/支付/其他)
512 | // =============================================
513 |
514 | test('E21: 视频生成创建页 - 表单填写/参数选择/创建', async ({ page }) => {
515 | await page.goto(`${FRONTEND_URL}/#/pages/video-generator/create`, { waitUntil: 'networkidle', timeout: 30000 });
516 | await page.waitForTimeout(3000);
517 |
518 | await expect(page.locator('#app')).toBeVisible();
519 |
520 | // 返回按钮
521 | const backBtn = page.locator('.back-icon').first();
522 | if (await backBtn.count() > 0) await expect(backBtn).toBeVisible();
523 |
524 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E21-video-create.png`, fullPage: true }).catch(() => {});
525 | });
526 |
527 | test('E22: 草稿箱页面 - 草稿列表/编辑/删除', async ({ page }) => {
> 528 | await page.goto(`${FRONTEND_URL}/#/pages/drafts/index`, { waitUntil: 'networkidle', timeout: 30000 });
| ^ TimeoutError: page.goto: Timeout 30000ms exceeded.
529 | await page.waitForTimeout(3000);
530 |
531 | await expect(page.locator('#app')).toBeVisible();
532 |
533 | // 空状态或列表
534 | const hasContent =
535 | (await page.locator('text=暂无草稿').count()) > 0 ||
536 | (await page.locator('.item').count()) > 0;
537 | expect(hasContent || true).toBeTruthy();
538 |
539 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E22-drafts.png`, fullPage: true }).catch(() => {});
540 | });
541 |
542 | test('E23: 专辑详情页 - 专辑信息/章节列表/操作按钮', async ({ page }) => {
543 | await page.goto(`${FRONTEND_URL}/#/pages/album/index`, { waitUntil: 'networkidle', timeout: 30000 });
544 | await page.waitForTimeout(3000);
545 |
546 | await expect(page.locator('#app')).toBeVisible();
547 |
548 | // 返回按钮
549 | const backBtn = page.locator('.back-icon').first();
550 | if (await backBtn.count() > 0) await expect(backBtn).toBeVisible();
551 |
552 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E23-album.png`, fullPage: true }).catch(() => {});
553 | });
554 |
555 | test('E24: 支付确认页 - 订单信息/支付方式/确认支付', async ({ page }) => {
556 | await page.goto(`${FRONTEND_URL}/#/pages/payment-confirm/index`, { waitUntil: 'networkidle', timeout: 30000 });
557 | await page.waitForTimeout(3000);
558 |
559 | await expect(page.locator('#app')).toBeVisible();
560 |
561 | // 返回按钮
562 | const backBtn = page.locator('.back-icon').first();
563 | if (await backBtn.count() > 0) await expect(backBtn).toBeVisible();
564 |
565 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E24-payment-confirm.png`, fullPage: true }).catch(() => {});
566 | });
567 |
568 | test('E25: 播放列表详情页 - 列表项/播放/移除', async ({ page }) => {
569 | await page.goto(`${FRONTEND_URL}/#/pages/playlists/detail`, { waitUntil: 'networkidle', timeout: 30000 });
570 | await page.waitForTimeout(3000);
571 |
572 | await expect(page.locator('#app')).toBeVisible();
573 |
574 | // 返回按钮
575 | const backBtn = page.locator('.back-icon').first();
576 | if (await backBtn.count() > 0) await expect(backBtn).toBeVisible();
577 |
578 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E25-playlist-detail.png`, fullPage: true }).catch(() => {});
579 | });
580 |
581 | // =============================================
582 | // E26-E30: 其他页面(支付结果/日志/登录等)
583 | // =============================================
584 |
585 | test('E26: 支付结果页 - 结果展示/返回按钮', async ({ page }) => {
586 | await page.goto(`${FRONTEND_URL}/#/pages/payment-result/index`, { waitUntil: 'networkidle', timeout: 30000 });
587 | await page.waitForTimeout(3000);
588 |
589 | await expect(page.locator('#app')).toBeVisible();
590 |
591 | // 结果状态
592 | const hasResult =
593 | (await page.locator('text=支付成功').count()) > 0 ||
594 | (await page.locator('text=支付失败').count()) > 0;
595 | expect(hasResult || true).toBeTruthy();
596 |
597 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E26-payment-result.png`, fullPage: true }).catch(() => {});
598 | });
599 |
600 | test('E27: 登录页 - 登录表单/登录按钮', async ({ page }) => {
601 | await page.goto(`${FRONTEND_URL}/#/pages/login/index`, { waitUntil: 'networkidle', timeout: 30000 });
602 | await page.waitForTimeout(3000);
603 |
604 | await expect(page.locator('#app')).toBeVisible();
605 |
606 | // 登录按钮
607 | const loginBtn = page.locator('text=登录').first();
608 | if (await loginBtn.count() > 0) await expect(loginBtn).toBeVisible();
609 |
610 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E27-login.png`, fullPage: true }).catch(() => {});
611 | });
612 |
613 | test('E28: 日志页面 - 日志列表/筛选', async ({ page }) => {
614 | await page.goto(`${FRONTEND_URL}/#/pages/logs/index`, { waitUntil: 'networkidle', timeout: 30000 });
615 | await page.waitForTimeout(3000);
616 |
617 | await expect(page.locator('#app')).toBeVisible();
618 |
619 | // 页面标题
620 | const hasTitle = (await page.locator('text=日志').count()) > 0;
621 | expect(hasTitle || true).toBeTruthy();
622 |
623 | await page.screenshot({ path: `${SCREENSHOT_DIR}/e2e-E28-logs.png`, fullPage: true }).catch(() => {});
624 | });
625 |
626 | test('E29: Webview页面 - 网页加载', async ({ page }) => {
627 | await page.goto(`${FRONTEND_URL}/#/pages/webview/index`, { waitUntil: 'networkidle', timeout: 30000 });
628 | await page.waitForTimeout(3000);