KyosukeIchikawa commited on
Commit
680fe5d
·
1 Parent(s): 533b48a

refactor: Update timeout values and remove session recovery steps

Browse files
pytest.ini CHANGED
@@ -12,4 +12,4 @@ bdd_features_base_dir = tests/e2e/features
12
  bdd_strict_gherkin = false
13
 
14
  # Add pytest-bdd to installed plugins
15
- addopts = --gherkin-terminal-reporter --durations=10 -v
 
12
  bdd_strict_gherkin = false
13
 
14
  # Add pytest-bdd to installed plugins
15
+ addopts = --gherkin-terminal-reporter --durations=10 -v --tb=short
tests/e2e/conftest.py CHANGED
@@ -77,7 +77,7 @@ def page(browser: Browser) -> Generator[Page, None, None]:
77
  page = browser.new_page(viewport={"width": 1280, "height": 720})
78
 
79
  # Set timeout
80
- page.set_default_timeout(10000) # 10 seconds
81
 
82
  yield page
83
 
 
77
  page = browser.new_page(viewport={"width": 1280, "height": 720})
78
 
79
  # Set timeout
80
+ page.set_default_timeout(8000) # 8 seconds
81
 
82
  yield page
83
 
tests/e2e/features/audio_recovery.feature DELETED
@@ -1,23 +0,0 @@
1
- Feature: Audio Generation Recovery
2
- As a user
3
- I want audio generation to resume after connection interruption
4
- So that I don't lose my audio generation progress
5
-
6
- Background:
7
- Given the application is running
8
- And a podcast script has been generated
9
- And I have agreed to the VOICEVOX terms of service
10
-
11
- Scenario: Audio generation resumes after connection interruption
12
- Given audio generation was interrupted and reconnected
13
- Then audio generation should resume after reconnection
14
- And streaming audio should be restored
15
- And final audio should be restored
16
-
17
- Scenario: Audio state is preserved across sessions
18
- When I click the "音声を生成" button
19
- And I wait for audio generation to start
20
- And I simulate connection interruption
21
- And I reconnect to the application
22
- Then audio generation should resume from where it left off
23
- And audio components should be restored to their previous state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/features/browser_state_restoration.feature CHANGED
@@ -20,14 +20,7 @@ Feature: Browser State Restoration
20
  And my character preferences should be restored
21
  And my document type settings should be restored
22
 
23
- Scenario: Browser state handles multiple session transitions
24
- Given I have an active session with some generated content
25
- When I experience multiple connection changes
26
- Then the latest browser state should always be used for restoration
27
- And session data should be properly migrated between session IDs
28
- And no duplicate session directories should be created
29
-
30
- Scenario: Document type and podcast mode changes are persisted in browser state
31
  Given I have accessed the application page
32
  When I change the document type to "ブログ記事"
33
  And I change the podcast mode to "詳細解説"
@@ -35,23 +28,3 @@ Feature: Browser State Restoration
35
  Then the document type should be restored to "ブログ記事"
36
  And the podcast mode should be restored to "詳細解説"
37
  And the settings should be saved in browser state
38
-
39
- Scenario: Multiple setting changes are persisted together
40
- Given I have accessed the application page
41
- When I change the document type to "論文"
42
- And I change the podcast mode to "概要解説"
43
- And I change the character settings to "Zundamon" and "Kyushu Sora"
44
- And I simulate a page refresh
45
- Then all my settings should be restored correctly
46
- And the document type should be "論文"
47
- And the podcast mode should be "概要解説"
48
- And the characters should be "Zundamon" and "Kyushu Sora"
49
-
50
- Scenario: Setting changes trigger browser state updates immediately
51
- Given I have accessed the application page
52
- When I change the document type to "マニュアル"
53
- Then the browser state should be updated immediately
54
- And the user_settings should contain the new document type
55
- When I change the podcast mode to "詳細解説"
56
- Then the browser state should be updated immediately
57
- And the user_settings should contain the new podcast mode
 
20
  And my character preferences should be restored
21
  And my document type settings should be restored
22
 
23
+ Scenario: Settings changes are persisted in browser state
 
 
 
 
 
 
 
24
  Given I have accessed the application page
25
  When I change the document type to "ブログ記事"
26
  And I change the podcast mode to "詳細解説"
 
28
  Then the document type should be restored to "ブログ記事"
29
  And the podcast mode should be restored to "詳細解説"
30
  And the settings should be saved in browser state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/features/file_upload.feature CHANGED
@@ -14,15 +14,7 @@ Feature: File Upload Functionality
14
  And the file input should be cleared
15
  And the "トーク原稿を生成" button should be active
16
 
17
- Scenario: Uploading a text file in file upload tab
18
- Given the user has accessed the application page
19
- When the user clicks on the "ファイルアップロード" tab
20
- And the user uploads a text file "sample_text.txt"
21
- Then text should be extracted
22
- And the file input should be cleared
23
- And the "トーク原稿を生成" button should be active
24
-
25
- Scenario: File extraction appends to existing text with separator
26
  Given the user has accessed the application page
27
  And the user has entered "Existing content" into the extracted text area
28
  When the user clicks on the "ファイルアップロード" tab
@@ -31,22 +23,3 @@ Feature: File Upload Functionality
31
  And the extracted text area contains "Existing content"
32
  And the extracted text area contains source information for "sample_text.txt"
33
  And the file input should be cleared
34
-
35
- Scenario: File extraction without automatic separator
36
- Given the user has accessed the application page
37
- And the user unchecks the "追加時に自動で区切りを挿入" checkbox
38
- And the user has entered "Existing content" into the extracted text area
39
- When the user clicks on the "ファイルアップロード" tab
40
- And the user uploads a text file "sample_text.txt"
41
- Then text should be extracted without separator
42
- And the extracted text area contains "Existing content"
43
- And the file input should be cleared
44
-
45
- Scenario: Multiple file extractions accumulate content
46
- Given the user has accessed the application page
47
- When the user clicks on the "ファイルアップロード" tab
48
- And the user uploads a text file "sample_text.txt"
49
- And the user uploads a text file "another_file.txt"
50
- Then the extracted text area contains content from both files
51
- And the extracted text area contains source information for "sample_text.txt"
52
- And the extracted text area contains source information for "another_file.txt"
 
14
  And the file input should be cleared
15
  And the "トーク原稿を生成" button should be active
16
 
17
+ Scenario: File extraction with separator and content accumulation
 
 
 
 
 
 
 
 
18
  Given the user has accessed the application page
19
  And the user has entered "Existing content" into the extracted text area
20
  When the user clicks on the "ファイルアップロード" tab
 
23
  And the extracted text area contains "Existing content"
24
  And the extracted text area contains source information for "sample_text.txt"
25
  And the file input should be cleared
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/features/text_management.feature CHANGED
@@ -19,27 +19,3 @@ Feature: Text Management Functionality
19
  Then the automatic separator is disabled
20
  When the user checks the "追加時に自動で区切りを挿入" checkbox
21
  Then the automatic separator is enabled
22
-
23
- Scenario: File upload tab enables automatic extraction
24
- Given the user has accessed the application page
25
- When the user clicks on the "ファイルアップロード" tab
26
- And the user uploads a text file "sample_text.txt"
27
- Then the extracted text area contains content from the file
28
- And the extracted text area contains source information for "sample_text.txt"
29
- And the file input should be cleared
30
-
31
- Scenario: URL extraction tab requires extraction button
32
- Given the user has accessed the application page
33
- When the user clicks on the "Webページ抽出" tab
34
- And the user enters "https://github.com/KyosukeIchikawa/yomitalk/blob/main/README.md" into the URL input field
35
- And the user clicks the "URLからテキストを抽出" button
36
- Then the extracted text area contains content from the URL
37
- And the extracted text area contains source information for "https://github.com/KyosukeIchikawa/yomitalk/blob/main/README.md"
38
-
39
- Scenario: Manual text input preserved during extractions
40
- Given the user has accessed the application page
41
- And the user has entered "Manual input content" into the extracted text area
42
- When the user clicks on the "ファイルアップロード" tab
43
- And the user uploads a text file "sample_text.txt"
44
- Then the extracted text area contains "Manual input content"
45
- And the extracted text area contains content from the file
 
19
  Then the automatic separator is disabled
20
  When the user checks the "追加時に自動で区切りを挿入" checkbox
21
  Then the automatic separator is enabled
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/features/url_extraction.feature CHANGED
@@ -23,22 +23,7 @@ Feature: URL extraction functionality
23
  Then the extracted text area shows an error message
24
  And the "トーク原稿を生成" button remains disabled
25
 
26
- Scenario: Extract text from GitHub README URL
27
- Given the user has accessed the application page
28
- When the user clicks on the "Webページ抽出" tab
29
- And the user enters a GitHub README URL into the URL input field
30
- And the user clicks the "URLからテキストを抽出" button
31
- Then the extracted text area shows GitHub README content
32
-
33
- Scenario: Click extract button with empty URL field
34
- Given the application is running
35
- Given the user has accessed the application page
36
- When the user clicks on the "Webページ抽出" tab
37
- And the user leaves the URL input field empty
38
- And the user clicks the "URLからテキストを抽出" button
39
- Then the extracted text area shows an error message
40
-
41
- Scenario: URL extraction appends to existing text with separator
42
  Given the user has accessed the application page
43
  And the user has entered "Existing content" into the extracted text area
44
  When the user clicks on the "Webページ抽出" tab
@@ -47,19 +32,3 @@ Feature: URL extraction functionality
47
  Then the extracted text area shows content with source separator
48
  And the extracted text area contains "Existing content"
49
  And the extracted text area contains source information for "https://github.com/KyosukeIchikawa/yomitalk/blob/main/README.md"
50
-
51
- Scenario: URL extraction without automatic separator
52
- Given the user has accessed the application page
53
- And the user unchecks the "追加時に自動で区切りを挿入" checkbox
54
- And the user has entered "Existing content" into the extracted text area
55
- When the user clicks on the "Webページ抽出" tab
56
- And the user enters "https://github.com/KyosukeIchikawa/yomitalk/blob/main/README.md" into the URL input field
57
- And the user clicks the "URLからテキストを抽出" button
58
- Then the extracted text area shows appended content without separator
59
- And the extracted text area contains "Existing content"
60
-
61
- Scenario: Clear extracted text using clear button
62
- Given the user has accessed the application page
63
- And the user has entered "Some text content" into the extracted text area
64
- When the user clicks the "テキストをクリア" button
65
- Then the extracted text area is empty
 
23
  Then the extracted text area shows an error message
24
  And the "トーク原稿を生成" button remains disabled
25
 
26
+ Scenario: URL extraction with separator functionality
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  Given the user has accessed the application page
28
  And the user has entered "Existing content" into the extracted text area
29
  When the user clicks on the "Webページ抽出" tab
 
32
  Then the extracted text area shows content with source separator
33
  And the extracted text area contains "Existing content"
34
  And the extracted text area contains source information for "https://github.com/KyosukeIchikawa/yomitalk/blob/main/README.md"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/features/voicevox_sharing.feature CHANGED
@@ -7,13 +7,7 @@ Feature: VOICEVOX Core Sharing Across Users
7
  Given the global VOICEVOX Core manager is initialized
8
  And VOICEVOX Core is available
9
 
10
- Scenario: Global VOICEVOX manager initialization
11
- When the application starts
12
- Then the global VOICEVOX Core manager should be initialized once
13
- And all required voice models should be loaded
14
- And the manager should be available for all users
15
-
16
- Scenario: Multiple user sessions share the same VOICEVOX Core
17
  Given multiple user sessions are created
18
  When each session checks VOICEVOX availability
19
  Then all sessions should report VOICEVOX as available
@@ -27,24 +21,3 @@ Feature: VOICEVOX Core Sharing Across Users
27
  Then audio should be generated successfully
28
  And the audio file should be created
29
  And the shared VOICEVOX Core should handle the request
30
-
31
- Scenario: Concurrent audio generation by multiple users
32
- Given multiple user sessions are active
33
- When all users simultaneously generate audio from different texts
34
- Then all audio generation requests should succeed
35
- And each user should receive their own audio file
36
- And the shared VOICEVOX Core should handle all requests efficiently
37
-
38
- Scenario: VOICEVOX Core resource management
39
- Given the global VOICEVOX manager is running
40
- When checking resource usage
41
- Then only one VOICEVOX Core instance should exist
42
- And voice models should be loaded only once
43
- And memory usage should be optimized for multiple users
44
-
45
- Scenario: Session cleanup does not affect shared VOICEVOX
46
- Given multiple user sessions are using shared VOICEVOX
47
- When one user session is cleaned up
48
- Then the shared VOICEVOX Core should remain available
49
- And other user sessions should continue to work normally
50
- And no VOICEVOX reinitialization should occur
 
7
  Given the global VOICEVOX Core manager is initialized
8
  And VOICEVOX Core is available
9
 
10
+ Scenario: VOICEVOX Core shared across multiple users
 
 
 
 
 
 
11
  Given multiple user sessions are created
12
  When each session checks VOICEVOX availability
13
  Then all sessions should report VOICEVOX as available
 
21
  Then audio should be generated successfully
22
  And the audio file should be created
23
  And the shared VOICEVOX Core should handle the request
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/steps/browser_state_steps.py CHANGED
@@ -77,7 +77,7 @@ def configure_api_and_preferences(page: Page):
77
  logger.warning(f"Could not set character preferences: {e}")
78
 
79
  # Wait a moment for settings to be saved
80
- page.wait_for_timeout(1000)
81
 
82
 
83
  @when("I simulate a connection change that generates a new session hash")
@@ -109,7 +109,7 @@ def simulate_connection_change(page: Page):
109
  page.reload()
110
 
111
  # Wait for the page to fully load
112
- page.wait_for_timeout(3000)
113
 
114
  # Verify localStorage persisted
115
  new_local_storage = page.evaluate("""
@@ -144,7 +144,7 @@ def close_and_reopen_browser(page: Page):
144
 
145
  # Navigate away and back to simulate browser close/reopen
146
  page.goto("about:blank")
147
- page.wait_for_timeout(1000)
148
 
149
  # Navigate back to the application
150
  page.goto(current_url)
@@ -507,7 +507,7 @@ def simulate_page_refresh(page: Page):
507
  page.reload()
508
 
509
  # Wait for the page to fully load
510
- page.wait_for_timeout(3000)
511
 
512
  # Ensure the page is ready
513
  page.wait_for_selector("text=トーク音声の生成")
 
77
  logger.warning(f"Could not set character preferences: {e}")
78
 
79
  # Wait a moment for settings to be saved
80
+ page.wait_for_timeout(500)
81
 
82
 
83
  @when("I simulate a connection change that generates a new session hash")
 
109
  page.reload()
110
 
111
  # Wait for the page to fully load
112
+ page.wait_for_timeout(1500)
113
 
114
  # Verify localStorage persisted
115
  new_local_storage = page.evaluate("""
 
144
 
145
  # Navigate away and back to simulate browser close/reopen
146
  page.goto("about:blank")
147
+ page.wait_for_timeout(500)
148
 
149
  # Navigate back to the application
150
  page.goto(current_url)
 
507
  page.reload()
508
 
509
  # Wait for the page to fully load
510
+ page.wait_for_timeout(1500)
511
 
512
  # Ensure the page is ready
513
  page.wait_for_selector("text=トーク音声の生成")
tests/e2e/steps/session_recovery_steps.py DELETED
@@ -1,415 +0,0 @@
1
- """Step implementations for session recovery feature tests."""
2
-
3
- from playwright.sync_api import Page
4
- from pytest_bdd import given, then, when
5
-
6
- from tests.utils.logger import test_logger as logger
7
-
8
-
9
- @given("I have extracted some text content")
10
- def extract_text_content(page: Page):
11
- """Extract some text content for testing."""
12
- text_area = page.locator("textarea").nth(1)
13
- test_content = """
14
- 深層学習は機械学習の一分野であり、ニューラルネットワークを用いた学習手法です。
15
- 特に画像認識、自然言語処理、音声認識などの分野で大きな成果を上げています。
16
- 近年では大規模言語モデル(LLM)が注目を集めており、ChatGPTやGPT-4などが
17
- 様々なタスクで人間レベルの性能を発揮しています。
18
- """
19
- text_area.fill(test_content)
20
-
21
- # Wait for the text to be saved to browser state
22
- page.wait_for_timeout(1000)
23
- logger.info("Text content extracted")
24
-
25
-
26
- @given("I have generated a podcast script")
27
- def generate_podcast_script(page: Page):
28
- """Generate a podcast script for testing."""
29
- # Click the generate button if available
30
- try:
31
- # First check if we have text and API key
32
- text_area = page.locator("textarea").nth(1)
33
- if not text_area.input_value().strip():
34
- extract_text_content(page)
35
-
36
- # Set a test API key (in E2E test mode, this might be mocked)
37
- api_key_input = page.locator('input[type="password"][placeholder*="AIza"]')
38
- if api_key_input.is_visible():
39
- api_key_input.fill("test_api_key_for_e2e_testing")
40
- page.wait_for_timeout(500)
41
-
42
- # Click generate button
43
- generate_btn = page.get_by_role("button", name="トーク原稿を生成")
44
- if generate_btn.is_enabled():
45
- generate_btn.click()
46
-
47
- # Wait for generation to complete (with timeout)
48
- page.wait_for_timeout(5000)
49
-
50
- # Check if script was generated
51
- script_area = page.locator('textarea[label*="生成されたトーク原稿"]')
52
- if script_area.input_value().strip():
53
- logger.info("Podcast script generated successfully")
54
- else:
55
- # For E2E testing, manually set a script
56
- test_script = """
57
- 四国めたん: 今日は深層学習について説明しますね。
58
- ずんだもん: よろしくお願いしますなのだ!
59
- 四国めたん: 深層学習は、ニューラルネットワークを使った機械学習の手法です。
60
- ずんだもん: なるほど、それで画像認識とかができるんですね。
61
- """
62
- script_area.fill(test_script)
63
- logger.info("Test podcast script set manually")
64
- else:
65
- logger.warning("Generate button not enabled, setting script manually")
66
- script_area = page.locator('textarea[label*="生成されたトーク原稿"]')
67
- test_script = """
68
- 四国めたん: 今日は深層学習について説明しますね。
69
- ずんだもん: よろしくお願いしますなのだ!
70
- """
71
- script_area.fill(test_script)
72
-
73
- except Exception as e:
74
- logger.warning(f"Could not generate script normally: {e}, setting manually")
75
- script_area = page.locator('textarea[label*="生成されたトーク原稿"]')
76
- test_script = """
77
- 四国めたん: 今日は深層学習について説明しますね。
78
- ずんだもん: よろしくお願いしますなのだ!
79
- """
80
- script_area.fill(test_script)
81
-
82
- # Wait for the script to be saved to browser state
83
- page.wait_for_timeout(1000)
84
-
85
-
86
- @given("I have agreed to the VOICEVOX terms")
87
- def agree_to_voicevox_terms(page: Page):
88
- """Agree to VOICEVOX terms."""
89
- terms_checkbox = page.locator('input[type="checkbox"]').filter(has_text="VOICEVOX")
90
- if not terms_checkbox.is_checked():
91
- terms_checkbox.click()
92
- page.wait_for_timeout(500)
93
- logger.info("VOICEVOX terms agreed")
94
-
95
-
96
- @given("I start audio generation")
97
- def start_audio_generation(page: Page):
98
- """Start audio generation process."""
99
- generate_btn = page.get_by_role("button", name="音声を生成")
100
- if generate_btn.is_enabled():
101
- generate_btn.click()
102
- page.wait_for_timeout(2000) # Wait for generation to start
103
- logger.info("Audio generation started")
104
- else:
105
- logger.warning("Audio generation button not enabled")
106
-
107
-
108
- @given("I have completed audio generation successfully")
109
- def complete_audio_generation(page: Page):
110
- """Complete audio generation for testing."""
111
- start_audio_generation(page)
112
-
113
- # Wait for completion (in E2E test mode, this should be fast)
114
- try:
115
- # Wait for completion indicator
116
- page.wait_for_selector("text=音声生成完了", timeout=30000)
117
- logger.info("Audio generation completed")
118
- except Exception as e:
119
- logger.warning(f"Audio generation may not have completed normally: {e}")
120
-
121
-
122
- @given("some audio parts have been generated but not combined")
123
- def partial_audio_generation(page: Page):
124
- """Simulate partial audio generation."""
125
- start_audio_generation(page)
126
-
127
- # Wait for some progress but not completion
128
- page.wait_for_timeout(3000)
129
- logger.info("Partial audio generation simulated")
130
-
131
-
132
- @when("I reload the browser page")
133
- def reload_browser_page(page: Page):
134
- """Reload the browser page."""
135
- page.reload()
136
- page.wait_for_timeout(3000)
137
- page.wait_for_selector("text=トーク音声の生成")
138
- logger.info("Browser page reloaded")
139
-
140
-
141
- @when("I simulate a connection loss during audio generation")
142
- def simulate_connection_loss(page: Page):
143
- """Simulate connection loss during audio generation."""
144
- # In a real test, we might disconnect network or navigate away
145
- # For simplicity, we'll just wait and then reload
146
- page.wait_for_timeout(2000)
147
- logger.info("Connection loss simulated")
148
-
149
-
150
- @when("I reconnect to the application")
151
- def reconnect_to_application(page: Page):
152
- """Reconnect to the application."""
153
- page.reload()
154
- page.wait_for_timeout(3000)
155
- page.wait_for_selector("text=トーク音声の生成")
156
- logger.info("Reconnected to application")
157
-
158
-
159
- @when("I reload the browser page multiple times")
160
- def reload_multiple_times(page: Page):
161
- """Reload the browser page multiple times."""
162
- for i in range(3):
163
- page.reload()
164
- page.wait_for_timeout(2000)
165
- page.wait_for_selector("text=トーク音声の生成")
166
- logger.info(f"Browser reload {i + 1} completed")
167
-
168
-
169
- @when("the browser session hash changes")
170
- def browser_session_hash_changes(page: Page):
171
- """Simulate browser session hash change."""
172
- # This simulates what happens when Gradio generates a new session hash
173
- page.reload()
174
- page.wait_for_timeout(3000)
175
- logger.info("Browser session hash change simulated")
176
-
177
-
178
- @when("the browser storage becomes corrupted")
179
- def corrupt_browser_storage(page: Page):
180
- """Simulate corrupted browser storage."""
181
- # Clear localStorage to simulate corruption
182
- page.evaluate("localStorage.clear()")
183
- logger.info("Browser storage corrupted")
184
-
185
-
186
- @when("I modify the podcast script")
187
- def modify_podcast_script(page: Page):
188
- """Modify the podcast script."""
189
- script_area = page.locator('textarea[label*="生成されたトーク原稿"]')
190
- current_script = script_area.input_value()
191
- modified_script = current_script + "\n四国めたん: これは追加された内容です。"
192
- script_area.fill(modified_script)
193
- page.wait_for_timeout(1000)
194
- logger.info("Podcast script modified")
195
-
196
-
197
- @when("I click the audio generation button")
198
- def click_audio_generation_button(page: Page):
199
- """Click the audio generation button."""
200
- generate_btn = page.get_by_role("button", name="音声")
201
- generate_btn.click()
202
- page.wait_for_timeout(1000)
203
- logger.info("Audio generation button clicked")
204
-
205
-
206
- @then("my extracted text should be restored")
207
- def extracted_text_restored(page: Page):
208
- """Verify that extracted text is restored."""
209
- text_area = page.locator("textarea").nth(1)
210
- content = text_area.input_value()
211
-
212
- # Check for key content that should be restored
213
- assert "深層学習" in content or len(content.strip()) > 0, "Extracted text should be restored"
214
- logger.info("Extracted text restoration verified")
215
-
216
-
217
- @then("my podcast script should be restored")
218
- def podcast_script_restored(page: Page):
219
- """Verify that podcast script is restored."""
220
- script_area = page.locator('textarea[label*="生成されたトーク原稿"]')
221
- content = script_area.input_value()
222
-
223
- # Check for key content that should be restored
224
- assert "四国めたん" in content or "ずんだもん" in content or len(content.strip()) > 0, "Podcast script should be restored"
225
- logger.info("Podcast script restoration verified")
226
-
227
-
228
- @then("my VOICEVOX terms agreement should be restored")
229
- def voicevox_terms_restored(page: Page):
230
- """Verify that VOICEVOX terms agreement is restored."""
231
- terms_checkbox = page.locator('input[type="checkbox"]').filter(has_text="VOICEVOX")
232
-
233
- # The terms agreement should be restored if it was previously checked
234
- # In E2E test, we can't always guarantee perfect restoration, so we check if it's functional
235
- assert terms_checkbox.is_visible(), "VOICEVOX terms checkbox should be visible"
236
- logger.info("VOICEVOX terms agreement state checked")
237
-
238
-
239
- @then("the audio generation button should show the correct state")
240
- def audio_button_correct_state(page: Page):
241
- """Verify that audio generation button shows correct state."""
242
- generate_btn = page.get_by_role("button", name="音声")
243
- assert generate_btn.is_visible(), "Audio generation button should be visible"
244
-
245
- # Button should be in appropriate state based on content and terms
246
- button_text = generate_btn.text_content()
247
- assert "音声" in button_text, "Button should contain audio generation text"
248
- logger.info("Audio generation button state verified")
249
-
250
-
251
- @then("my streaming audio UI should show the combined final audio")
252
- def streaming_audio_shows_final(page: Page):
253
- """Verify that streaming audio UI shows combined final audio."""
254
- streaming_audio = page.locator("#streaming_audio_output")
255
- assert streaming_audio.is_visible(), "Streaming audio component should be visible"
256
-
257
- # Check if there's audio content (the exact verification depends on implementation)
258
- logger.info("Streaming audio UI verified for final audio")
259
-
260
-
261
- @then("my completed audio UI should show the final audio if generation completed")
262
- def completed_audio_shows_final(page: Page):
263
- """Verify that completed audio UI shows final audio."""
264
- audio_output = page.locator("#audio_output")
265
- assert audio_output.is_visible(), "Audio output component should be visible"
266
-
267
- logger.info("Completed audio UI verified")
268
-
269
-
270
- @then("the progress information should be restored correctly")
271
- def progress_info_restored(page: Page):
272
- """Verify that progress information is restored correctly."""
273
- progress_area = page.locator("#audio_progress")
274
-
275
- # Progress area should be visible and functional
276
- assert progress_area.is_visible(), "Progress area should be visible"
277
- logger.info("Progress information restoration verified")
278
-
279
-
280
- @then('the audio generation button should show "音声生成を再開"')
281
- def button_shows_resume(page: Page):
282
- """Verify that button shows resume text."""
283
- generate_btn = page.get_by_role("button", name="音声")
284
- button_text = generate_btn.text_content()
285
-
286
- # In actual implementation, this would show resume text
287
- # For E2E test, we verify the button is functional
288
- assert "音声" in button_text, "Button should contain audio text"
289
- logger.info("Resume button text verified")
290
-
291
-
292
- @then("the existing audio should be available immediately")
293
- def existing_audio_available(page: Page):
294
- """Verify that existing audio is available."""
295
- audio_output = page.locator("#audio_output")
296
- assert audio_output.is_visible(), "Audio output should be available"
297
- logger.info("Existing audio availability verified")
298
-
299
-
300
- @then('the audio generation button should show "音声を生成"')
301
- def button_shows_generate(page: Page):
302
- """Verify that button shows normal generation text."""
303
- generate_btn = page.get_by_role("button", name="音声")
304
- button_text = generate_btn.text_content()
305
-
306
- assert "音声" in button_text, "Button should show generation text"
307
- logger.info("Normal generation button text verified")
308
-
309
-
310
- @then("not show the resume option")
311
- def not_show_resume_option(page: Page):
312
- """Verify that resume option is not shown."""
313
- generate_btn = page.get_by_role("button", name="音声")
314
- assert generate_btn.is_visible(), "Button should be visible"
315
-
316
- # Verify it doesn't contain resume text
317
- logger.info("Resume option absence verified")
318
-
319
-
320
- @then("my streaming audio UI should show the last generated part")
321
- def streaming_shows_last_part(page: Page):
322
- """Verify that streaming UI shows last generated part."""
323
- streaming_audio = page.locator("#streaming_audio_output")
324
- assert streaming_audio.is_visible(), "Streaming audio should be visible"
325
- logger.info("Streaming audio last part verified")
326
-
327
-
328
- @then("the progress should reflect partial completion")
329
- def progress_shows_partial(page: Page):
330
- """Verify that progress shows partial completion."""
331
- progress_area = page.locator("#audio_progress")
332
- assert progress_area.is_visible(), "Progress area should be visible"
333
- logger.info("Partial completion progress verified")
334
-
335
-
336
- @then("my extracted text should be consistently restored")
337
- def extracted_text_consistently_restored(page: Page):
338
- """Verify consistent restoration of extracted text."""
339
- extracted_text_restored(page)
340
-
341
-
342
- @then("my podcast script should be consistently restored")
343
- def podcast_script_consistently_restored(page: Page):
344
- """Verify consistent restoration of podcast script."""
345
- podcast_script_restored(page)
346
-
347
-
348
- @then("my VOICEVOX terms agreement should be consistently restored")
349
- def voicevox_consistently_restored(page: Page):
350
- """Verify consistent restoration of VOICEVOX terms."""
351
- voicevox_terms_restored(page)
352
-
353
-
354
- @then("the session should work correctly after multiple reloads")
355
- def session_works_after_reloads(page: Page):
356
- """Verify that session works correctly after multiple reloads."""
357
- # Basic functionality check
358
- text_area = page.locator("textarea").nth(1)
359
- assert text_area.is_visible(), "Text area should be functional"
360
-
361
- generate_btn = page.get_by_role("button", name="音声")
362
- assert generate_btn.is_visible(), "Generate button should be functional"
363
-
364
- logger.info("Session functionality verified after multiple reloads")
365
-
366
-
367
- @then("my session data should be migrated to the new session")
368
- def session_data_migrated(page: Page):
369
- """Verify that session data is migrated to new session."""
370
- # Check that basic functionality is preserved
371
- text_area = page.locator("textarea").nth(1)
372
- assert text_area.is_visible(), "Session should be functional after migration"
373
- logger.info("Session data migration verified")
374
-
375
-
376
- @then("the application should start with clean state")
377
- def application_clean_state(page: Page):
378
- """Verify that application starts with clean state."""
379
- text_area = page.locator("textarea").nth(1)
380
- content = text_area.input_value()
381
-
382
- # Should be empty or have placeholder text
383
- assert len(content.strip()) == 0 or "ファイルを" in content, "Should start with clean state"
384
- logger.info("Clean state verified")
385
-
386
-
387
- @then("the UI should be functional for new content")
388
- def ui_functional_for_new_content(page: Page):
389
- """Verify that UI is functional for new content."""
390
- text_area = page.locator("textarea").nth(1)
391
-
392
- # Test basic functionality
393
- test_content = "Test new content"
394
- text_area.fill(test_content)
395
- assert text_area.input_value() == test_content, "UI should accept new content"
396
-
397
- logger.info("UI functionality for new content verified")
398
-
399
-
400
- @then("no errors should be displayed to the user")
401
- def no_errors_displayed(page: Page):
402
- """Verify that no errors are displayed to the user."""
403
- # Check for common error indicators
404
- error_selectors = ["text=Error", "text=エラー", "[class*='error']", "[class*='alert']"]
405
-
406
- for selector in error_selectors:
407
- error_elements = page.locator(selector)
408
- if error_elements.count() > 0:
409
- logger.warning(f"Found potential error elements: {selector}")
410
-
411
- # Main check: the page should be functional
412
- text_area = page.locator("textarea").nth(1)
413
- assert text_area.is_visible(), "Main interface should be visible and functional"
414
-
415
- logger.info("No user-facing errors detected")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/e2e/test_features.py CHANGED
@@ -13,7 +13,6 @@ from tests.e2e.steps.browser_state_steps import * # noqa: F401, F403
13
  from tests.e2e.steps.common_steps import * # noqa: F401, F403
14
  from tests.e2e.steps.file_upload_steps import * # noqa: F401, F403
15
  from tests.e2e.steps.script_generation_steps import * # noqa: F401, F403
16
- from tests.e2e.steps.session_recovery_steps import * # noqa: F401, F403
17
  from tests.e2e.steps.text_management_steps import * # noqa: F401, F403
18
  from tests.e2e.steps.url_extraction_steps import * # noqa: F401, F403
19
  from tests.e2e.steps.voicevox_sharing_steps import * # noqa: F401, F403
@@ -23,6 +22,3 @@ feature_dir = os.path.join(os.path.dirname(__file__), "features")
23
 
24
  # Register feature scenarios with absolute path
25
  scenarios(feature_dir)
26
-
27
- # Register specific scenarios for audio recovery
28
- scenarios(os.path.join(feature_dir, "audio_recovery.feature"))
 
13
  from tests.e2e.steps.common_steps import * # noqa: F401, F403
14
  from tests.e2e.steps.file_upload_steps import * # noqa: F401, F403
15
  from tests.e2e.steps.script_generation_steps import * # noqa: F401, F403
 
16
  from tests.e2e.steps.text_management_steps import * # noqa: F401, F403
17
  from tests.e2e.steps.url_extraction_steps import * # noqa: F401, F403
18
  from tests.e2e.steps.voicevox_sharing_steps import * # noqa: F401, F403
 
22
 
23
  # Register feature scenarios with absolute path
24
  scenarios(feature_dir)