agora-stt.page.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { Page, Locator, expect } from '@playwright/test';
  2. export class AgoraSTTPage {
  3. readonly page: Page;
  4. readonly pageTitle: Locator;
  5. readonly joinChannelButton: Locator;
  6. readonly leaveChannelButton: Locator;
  7. readonly startRecordingButton: Locator;
  8. readonly stopRecordingButton: Locator;
  9. readonly clearTranscriptionsButton: Locator;
  10. readonly connectionStatusBadge: Locator;
  11. readonly recordingStatusBadge: Locator;
  12. readonly microphonePermissionBadge: Locator;
  13. readonly transcriptionCountBadge: Locator;
  14. readonly errorAlert: Locator;
  15. readonly interimTranscription: Locator;
  16. readonly finalTranscriptions: Locator;
  17. readonly usageInstructions: Locator;
  18. constructor(page: Page) {
  19. this.page = page;
  20. this.pageTitle = page.getByRole('heading', { name: '语音转文字' });
  21. this.joinChannelButton = page.getByTestId('join-channel-button');
  22. this.leaveChannelButton = page.getByTestId('leave-channel-button');
  23. this.startRecordingButton = page.getByTestId('start-recording-button');
  24. this.stopRecordingButton = page.getByTestId('stop-recording-button');
  25. this.clearTranscriptionsButton = page.getByTestId('clear-transcriptions-button');
  26. // 状态徽章
  27. this.connectionStatusBadge = page.getByText(/已连接|未连接/).first();
  28. this.recordingStatusBadge = page.getByText(/录制中|未录制/).first();
  29. this.microphonePermissionBadge = page.getByText(/麦克风已授权|麦克风被拒绝|麦克风权限/).first();
  30. this.transcriptionCountBadge = page.getByText(/条转录/).first();
  31. // 转录结果显示
  32. this.errorAlert = page.getByRole('alert');
  33. this.interimTranscription = page.getByText('正在识别...').first();
  34. this.finalTranscriptions = page.getByText('转录结果:').first();
  35. this.usageInstructions = page.getByText('使用说明:');
  36. }
  37. async expectToBeVisible(options?: { timeout?: number }) {
  38. await expect(this.pageTitle).toBeVisible(options);
  39. await expect(this.joinChannelButton).toBeVisible(options);
  40. }
  41. async navigateFromDashboard(dashboardPage: any) {
  42. // 检查是否为移动端,需要先打开菜单
  43. const isMobile = (this.page.viewportSize()?.width || 0) < 768;
  44. if (isMobile) {
  45. // 移动端需要先点击菜单按钮
  46. const menuButton = this.page.getByTestId('mobile-menu-button');
  47. await expect(menuButton).toBeVisible({ timeout: 10000 });
  48. await menuButton.click({ timeout: 15000 });
  49. await this.page.waitForTimeout(1000); // 等待菜单完全展开
  50. }
  51. // 导航到Agora STT页面
  52. const agoraSTTLink = this.page.getByRole('button', { name: '语音转文字' }).first();
  53. await expect(agoraSTTLink).toBeVisible({ timeout: 10000 });
  54. await agoraSTTLink.click({ timeout: 10000 });
  55. await this.page.waitForLoadState('networkidle');
  56. await this.expectToBeVisible();
  57. }
  58. async goto() {
  59. // 直接访问Agora STT页面URL
  60. await this.page.goto('/admin/agora-stt');
  61. await this.page.waitForLoadState('networkidle');
  62. await this.expectToBeVisible();
  63. }
  64. async joinChannel() {
  65. await this.joinChannelButton.click();
  66. // 等待连接状态更新
  67. await expect(this.connectionStatusBadge).toHaveText('已连接', { timeout: 15000 });
  68. // 等待按钮状态更新 - 先等待加入按钮消失
  69. await expect(this.joinChannelButton).not.toBeVisible({ timeout: 5000 });
  70. // 然后等待离开频道按钮可见
  71. await expect(this.leaveChannelButton).toBeVisible({ timeout: 10000 });
  72. }
  73. async leaveChannel() {
  74. await this.leaveChannelButton.click();
  75. await expect(this.connectionStatusBadge).toHaveText('未连接');
  76. }
  77. async startRecording() {
  78. await this.startRecordingButton.click();
  79. // 等待录制状态更新,增加超时时间
  80. await expect(this.recordingStatusBadge).toHaveText('录制中', { timeout: 15000 });
  81. }
  82. async stopRecording() {
  83. await this.stopRecordingButton.click();
  84. await expect(this.recordingStatusBadge).toHaveText('未录制');
  85. }
  86. async clearTranscriptions() {
  87. await this.clearTranscriptionsButton.click();
  88. // 验证转录结果被清空
  89. await expect(this.finalTranscriptions).not.toBeVisible();
  90. }
  91. async getConnectionStatus(): Promise<string> {
  92. return await this.connectionStatusBadge.textContent() || '';
  93. }
  94. async getRecordingStatus(): Promise<string> {
  95. return await this.recordingStatusBadge.textContent() || '';
  96. }
  97. async getMicrophonePermissionStatus(): Promise<string> {
  98. return await this.microphonePermissionBadge.textContent() || '';
  99. }
  100. async getTranscriptionCount(): Promise<number> {
  101. const text = await this.transcriptionCountBadge.textContent() || '';
  102. const match = text.match(/(\d+)\s*条转录/);
  103. return match ? parseInt(match[1]) : 0;
  104. }
  105. async hasError(): Promise<boolean> {
  106. return await this.errorAlert.isVisible();
  107. }
  108. async hasInterimTranscription(): Promise<boolean> {
  109. return await this.interimTranscription.isVisible();
  110. }
  111. async hasFinalTranscriptions(): Promise<boolean> {
  112. return await this.finalTranscriptions.isVisible();
  113. }
  114. clone(newPage: Page): AgoraSTTPage {
  115. return new AgoraSTTPage(newPage);
  116. }
  117. }