diff --git a/features/agent.feature b/features/agent.feature index 1f55e818..24c996d9 100644 --- a/features/agent.feature +++ b/features/agent.feature @@ -10,8 +10,9 @@ Feature: Agent Workflow - Tool Usage and Multi-Round Conversation And I should see a "page body" element with selector "body" # Ensure we are in the correct workspace before each scenario to avoid wrong starting state And I click on "agent workspace button and new tab button" elements with selectors: - | [data-testid='workspace-agent'] | - | [data-tab-id='new-tab-button'] | + | element description | selector | + | agent workspace | [data-testid='workspace-agent'] | + | new tab button | [data-tab-id='new-tab-button'] | @agent @mockOpenAI Scenario: Wiki-search tool usage @@ -36,8 +37,9 @@ Feature: Agent Workflow - Tool Usage and Multi-Round Conversation Then I should see 4 messages in chat history # Verify the last message contains the AI explanation about Index And I should see "explanation in last message and explanation about edit" elements with selectors: - | [data-testid='message-bubble']:last-child:has-text('Index') | - | [data-testid='message-bubble']:last-child:has-text('编辑') | + | element description | selector | + | explanation in last message| [data-testid='message-bubble']:last-child:has-text('Index') | + | explanation about edit | [data-testid='message-bubble']:last-child:has-text('编辑') | @agent @mockOpenAI Scenario: Wiki operation @@ -64,14 +66,16 @@ Feature: Agent Workflow - Tool Usage and Multi-Round Conversation And I should see a "workspace not exist error" element with selector "[data-testid='message-bubble']:has-text('test-expected-to-fail'):has-text('不存在')" # Verify the last message contains success confirmation And I should see "success in last message and wiki workspace in last message" elements with selectors: - | [data-testid='message-bubble']:last-child:has-text('已成功') | - | [data-testid='message-bubble']:last-child:has-text('wiki') | + | element description | selector | + | success in last message | [data-testid='message-bubble']:last-child:has-text('已成功') | + | wiki workspace in last message| [data-testid='message-bubble']:last-child:has-text('wiki') | @agent Scenario: Create default agent from New Tab quick access When I click on "new tab button and create default agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-default-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create default agent button| [data-testid='create-default-agent-button'] | And I should see a "message input box" element with selector "[data-testid='agent-message-input']" @agent @@ -95,17 +99,19 @@ Feature: Agent Workflow - Tool Usage and Multi-Round Conversation | response | stream | | partial_chunk_1partial_chunk_2partial_chunk_3partial_chunk_4 | true | And I click on "new tab button and create default agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-default-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create default agent button| [data-testid='create-default-agent-button'] | And I should see a "message input box" element with selector "[data-testid='agent-message-input']" When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']" When I type "Start long streaming" in "chat input" element with selector "[data-testid='agent-message-input']" And I press "Enter" key # Wait for streaming container to appear and contain the first chunk Then I should see "assistant streaming container and partial assistant text and cancel icon" elements with selectors: - | [data-testid='assistant-streaming-text'] | - | *:has-text('partial_chunk_1') | - | [data-testid='cancel-icon'] | + | element description | selector | + | assistant streaming container| [data-testid='assistant-streaming-text'] | + | partial assistant text | *:has-text('partial_chunk_1') | + | cancel icon | [data-testid='cancel-icon'] | # Click cancel button mid-stream When I click on a "cancel button" element with selector "[data-testid='agent-send-button']" And I should see a "send icon" element with selector "[data-testid='send-icon']" diff --git a/features/aiCommitMessage.feature b/features/aiCommitMessage.feature index f75af407..e708494c 100644 --- a/features/aiCommitMessage.feature +++ b/features/aiCommitMessage.feature @@ -51,5 +51,6 @@ Feature: AI-Generated Git Commit Messages # After commit, verify AI-generated message and file in git log table # Message is in p.MuiTypography-body2, file div has aria-label Then I should see "commit with AI message and Index.tid file" elements with selectors: - | p.MuiTypography-body2:has-text('更新 Index 条目') | - | div.MuiBox-root[aria-label*='Index.tid'] | + | element description | selector | + | commit with AI message | p.MuiTypography-body2:has-text('更新 Index 条目') | + | Index.tid file | div.MuiBox-root[aria-label*='Index.tid'] | diff --git a/features/configError.feature b/features/configError.feature index 400cc3b3..45a2008d 100644 --- a/features/configError.feature +++ b/features/configError.feature @@ -18,8 +18,9 @@ Feature: Configuration Error Handling And I should see a "new tab button" element with selector "[data-tab-id='new-tab-button']" # Create a default agent (this should work without AI config) When I click on "new tab button and create default agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-default-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create default agent button | [data-testid='create-default-agent-button'] | And I should see a "message input box" element with selector "[data-testid='agent-message-input']" # Try to send a message - this should fail with MissingConfigError When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']" @@ -27,9 +28,10 @@ Feature: Configuration Error Handling And I press "Enter" key # Verify error message wrapper, internationalized title, and "Go to Settings" button are present Then I should see "error message wrapper and configuration issue title and go to settings button" elements with selectors: - | [data-testid='error-message'] | - | [data-testid='error-message']:has-text('配置问题') | - | [data-testid='error-message'] button:has-text('前往设置') | + | element description | selector | + | error message wrapper | [data-testid='error-message'] | + | configuration issue title | [data-testid='error-message']:has-text('配置问题') | + | go to settings button | [data-testid='error-message'] button:has-text('前往设置') | # Verify we don't see the raw translation key Then I should not see a "raw error key text" element with selector "text='Chat.ConfigError.MissingConfigError'" # Click the button to open preferences diff --git a/features/defaultWiki.feature b/features/defaultWiki.feature index 91f0a829..bdc4fd77 100644 --- a/features/defaultWiki.feature +++ b/features/defaultWiki.feature @@ -13,8 +13,9 @@ Feature: TidGi Default Wiki @wiki Scenario: Application has default wiki workspace Then I should see "page body and wiki workspace" elements with selectors: - | body | - | div[data-testid^='workspace-']:has-text('wiki') | + | element description | selector | + | page body | body | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | And the window title should contain "太记" @wiki diff --git a/features/gitLog.feature b/features/gitLog.feature index f212da22..b59bf0f6 100644 --- a/features/gitLog.feature +++ b/features/gitLog.feature @@ -83,10 +83,11 @@ Feature: Git Log Window Then I should not see a "uncommitted changes row" element with selector "[data-testid='uncommitted-changes-row']" # Verify the correct commit is selected and we're on the latest commit (should show amend button) Then I should see "selected commit row and commit message and amend button and revert button" elements with selectors: - | [data-testid^='commit-row-'][data-selected='true']:has-text('使用太记桌面版备份') | - | p.MuiTypography-body2:has-text('使用太记桌面版备份') | - | button:has-text('修改') | - | button:has-text('回滚') | + | element description | selector | + | selected commit row | [data-testid^='commit-row-'][data-selected='true']:has-text('使用太记桌面版备份') | + | commit message | p.MuiTypography-body2:has-text('使用太记桌面版备份') | + | amend button | button:has-text('修改') | + | revert button | button:has-text('回滚') | # Click revert button When I click on a "revert button" element with selector "button:has-text('回滚')" # Wait for git revert operation to complete diff --git a/features/hibernation.feature b/features/hibernation.feature index 0cffb21e..b1656845 100644 --- a/features/hibernation.feature +++ b/features/hibernation.feature @@ -21,8 +21,9 @@ Feature: Workspace Hibernation And I switch to "editWorkspace" window And I wait for the page to load completely When I click on "misc options accordion and hibernation switch" elements with selectors: - | [data-testid='preference-section-miscOptions'] | - | [data-testid='hibernate-when-unused-switch'] | + | element description | selector | + | misc options accordion | [data-testid='preference-section-miscOptions'] | + | hibernation switch | [data-testid='hibernate-when-unused-switch'] | When I click on a "save button" element with selector "[data-testid='edit-workspace-save-button']" Then I should not see a "save button" element with selector "[data-testid='edit-workspace-save-button']" Then I switch to "main" window @@ -32,8 +33,9 @@ Feature: Workspace Hibernation And I switch to "editWorkspace" window And I wait for the page to load completely When I click on "misc options accordion and hibernation switch" elements with selectors: - | [data-testid='preference-section-miscOptions'] | - | [data-testid='hibernate-when-unused-switch'] | + | element description | selector | + | misc options accordion | [data-testid='preference-section-miscOptions'] | + | hibernation switch | [data-testid='hibernate-when-unused-switch'] | When I click on a "save button" element with selector "[data-testid='edit-workspace-save-button']" Then I should not see a "save button" element with selector "[data-testid='edit-workspace-save-button']" Then I switch to "main" window diff --git a/features/newAgent.feature b/features/newAgent.feature index 6556aff8..aaa91e2c 100644 --- a/features/newAgent.feature +++ b/features/newAgent.feature @@ -20,13 +20,15 @@ Feature: Create New Agent Workflow | 作为代码助手,我可以帮您解决编程问题。请问需要什么帮助? | false | # Step 1: Open new tab and navigate to CreateNewAgent When I click on "new tab button and create new agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-new-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create new agent button | [data-testid='create-new-agent-button'] | # Step 2: Verify first step content (Setup Agent: Name + Template) Then I should see "step title and search input and agent name input field" elements with selectors: - | *:has-text('设置智能体') | - | .aa-Input | - | [data-testid='agent-name-input-field'] | + | element description | selector | + | step title | *:has-text('设置智能体') | + | search input | .aa-Input | + | agent name input field | [data-testid='agent-name-input-field'] | # Step 3: Select template to advance to step 2 When I click on a "search input" element with selector ".aa-Input" # Immediately click on the Example Agent template (don't wait or panel will close) @@ -47,9 +49,10 @@ Feature: Create New Agent Workflow And I should see a "config tabs" element with selector "[data-testid='prompt-config-form'] .MuiTabs-root" # Click on the first tab, expand array item, and click on the system prompt text field When I click on "first config tab and expand array item button and system prompt text field" elements with selectors: - | [data-testid='prompt-config-form'] .MuiTab-root:first-of-type | - | [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) button[title*='展开'], [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) button svg[data-testid='ExpandMoreIcon'] | - | [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly]) | + | element description | selector | + | first config tab | [data-testid='prompt-config-form'] .MuiTab-root:first-of-type | + | expand array item button | [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) button[title*='展开'], [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) button svg[data-testid='ExpandMoreIcon'] | + | system prompt text field | [data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly]) | When I clear text in "system prompt text field" element with selector "[data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly])" And I wait for 0.1 seconds for "clear to complete and DOM to stabilize" When I type "你是一个专业的代码助手,请用中文回答编程问题。" in "system prompt text field" element with selector "[data-testid='prompt-config-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly])" @@ -64,8 +67,9 @@ Feature: Create New Agent Workflow And I press "Enter" key # Verify the agent responds in the preview interface Then I should see "user message and assistant message" elements with selectors: - | *:has-text('帮我写个 Hello World') | - | *:has-text('作为代码助手') | + | element description | selector | + | user message | *:has-text('帮我写个 Hello World') | + | assistant message | *:has-text('作为代码助手') | And the last AI request should contain system prompt "你是一个专业的代码助手,请用中文回答编程问题。" # Step 8: Save and start using (after testing in step 3) When I click on a "save and use button" element with selector "button:has-text('保存并使用智能体')" @@ -86,10 +90,11 @@ Feature: Create New Agent Workflow When I click on a "edit definition menu item" element with selector "[data-testid='edit-definition-menu-item']" # Step 4: Verify direct edit interface (no steps - all content visible) And I should see "edit agent title and basic info section and edit prompt section and immediate use section" elements with selectors: - | *:has-text('编辑智能体定义') | - | *:has-text('编辑基本信息') | - | *:has-text('编辑提示词') | - | *:has-text('测试并使用') | + | element description | selector | + | edit agent title | *:has-text('编辑智能体定义') | + | basic info section | *:has-text('编辑基本信息') | + | edit prompt section | *:has-text('编辑提示词') | + | immediate use section | *:has-text('测试并使用') | # Step 5: Edit agent name in the basic info section And I should see a "agent name input" element with selector "[data-testid='edit-agent-name-input']" When I clear text in "agent name input" element with selector "[data-testid='edit-agent-name-input-field']" @@ -102,9 +107,10 @@ Feature: Create New Agent Workflow And I should see a "config tabs" element with selector "[data-testid='edit-agent-prompt-form'] .MuiTabs-root" # Click on the first tab, expand array item, and click on the system prompt text field When I click on "first config tab and expand array item button and system prompt text field" elements with selectors: - | [data-testid='edit-agent-prompt-form'] .MuiTab-root:first-of-type | - | [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) button[title*='展开'], [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) button svg[data-testid='ExpandMoreIcon'] | - | [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly]) | + | element description | selector | + | first config tab | [data-testid='edit-agent-prompt-form'] .MuiTab-root:first-of-type | + | expand array item button | [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) button[title*='展开'], [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) button svg[data-testid='ExpandMoreIcon'] | + | system prompt text field | [data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly]) | When I clear text in "system prompt text field" element with selector "[data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly])" When I type "你是一个经过编辑的专业代码助手,请用中文详细回答编程问题。" in "system prompt text field" element with selector "[data-testid='edit-agent-prompt-form'] [role='tabpanel']:not([hidden]) textarea[id*='_text']:not([readonly])" # Step 7: Test in the immediate use section (embedded chat) @@ -115,8 +121,9 @@ Feature: Create New Agent Workflow And I press "Enter" key # Verify the agent responds in the embedded chat Then I should see "user message and assistant message" elements with selectors: - | *:has-text('你好,请介绍一下自己') | - | *:has-text('已编辑的代码助手') | + | element description | selector | + | user message | *:has-text('你好,请介绍一下自己') | + | assistant message | *:has-text('已编辑的代码助手') | # Verify that the server received the request with the modified system prompt And the last AI request should contain system prompt "你是一个经过编辑的专业代码助手,请用中文详细回答编程问题。" # Step 8: Save the edited agent definition diff --git a/features/oauthLogin.feature b/features/oauthLogin.feature index b2cc07ef..67a7cdc2 100644 --- a/features/oauthLogin.feature +++ b/features/oauthLogin.feature @@ -13,20 +13,19 @@ Feature: OAuth Login Flow # Step 1: Start Mock OAuth Server When I start Mock OAuth Server on port 8888 - # Step 2: Open preferences window + # Step 2: Open preferences window and navigate to Sync section When I click on a "settings button" element with selector "#open-preferences-button" When I switch to "preferences" window + When I click on "sync section and custom server tab" elements with selectors: + | element description | selector | + | sync section | [data-testid='preference-section-sync'] | + | custom server tab | [data-testid='custom-server-tab'] | - # Step 2: Navigate to Sync section - When I click on a "sync section" element with selector "[data-testid='preference-section-sync']" - - # Step 3: Click Custom Server tab - When I click on a "custom server tab" element with selector "[data-testid='custom-server-tab']" - - # Step 4: Verify Custom Server form is visible + # Step 3: Verify Custom Server form is visible Then I should see "server url input and client id input" elements with selectors: - | [data-testid='custom-server-url-input'] | - | [data-testid='custom-client-id-input'] | + | element description | selector | + | server url input | [data-testid='custom-server-url-input'] | + | client id input | [data-testid='custom-client-id-input'] | # Step 5: Trigger OAuth login # Note: oauth2-mock-server automatically redirects without showing login UI diff --git a/features/preference.feature b/features/preference.feature index aac5d709..f7721894 100644 --- a/features/preference.feature +++ b/features/preference.feature @@ -23,52 +23,57 @@ Feature: TidGi Preference When I click on an "add provider submit" element with selector "[data-testid='add-provider-submit-button']" # Step 5: Select the new provider and add a model When I click on "provider tab and add model button" elements with selectors: - | button[role='tab']:has-text('TestProvider') | - | [data-testid='add-new-model-button'] | + | element description | selector | + | provider tab TestProvider | button[role='tab']:has-text('TestProvider') | + | add model button | [data-testid='add-new-model-button'] | # Step 6: Add language model (will auto-fill as default language model) When I type "test-model" in "model name input" element with selector "[data-testid='new-model-name-input']" When I click on "save model button and add model button" elements with selectors: - | [data-testid='save-model-button'] | - | [data-testid='add-new-model-button'] | + | element description | selector | + | save model button | [data-testid='save-model-button'] | + | add model button | [data-testid='add-new-model-button'] | # Step 7: Add embedding model (will auto-fill as default embedding model) When I type "test-embedding-model" in "model name input" element with selector "[data-testid='new-model-name-input']" When I click on "embedding feature checkbox and save model button and add model button" elements with selectors: - | [data-testid='feature-checkbox-embedding'] | - | [data-testid='save-model-button'] | - | [data-testid='add-new-model-button'] | + | element description | selector | + | embedding feature checkbox | [data-testid='feature-checkbox-embedding'] | + | save model button | [data-testid='save-model-button'] | + | add model button | [data-testid='add-new-model-button'] | # Step 8: Add speech model (will auto-fill as default speech model) When I type "test-speech-model" in "model name input" element with selector "[data-testid='new-model-name-input']" # Uncheck language feature first (it's checked by default) When I click on "language feature checkbox and speech feature checkbox and save model button" elements with selectors: - | [data-testid='feature-checkbox-language'] | - | [data-testid='feature-checkbox-speech'] | - | [data-testid='save-model-button'] | + | element description | selector | + | language feature checkbox | [data-testid='feature-checkbox-language'] | + | speech feature checkbox | [data-testid='feature-checkbox-speech'] | + | save model button | [data-testid='save-model-button'] | # Step 9: Verify auto-fill worked by checking that autocomplete inputs have the correct selected values # MUI Autocomplete shows selected value in the input, we check by looking for the model name in the visible text - Then I should see "default language model value test-model and default embedding model value test-embedding-model and default speech model value test-speech-model" elements with selectors: - | text='test-model' | - | text='test-embedding-model' | - | text='test-speech-model' | - # Verify there are exactly 3 filled model selectors - Then I should see "first autocomplete input with test-model and second autocomplete input with test-embedding-model and third autocomplete input with test-speech-model" elements with selectors: - | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-model'])[1] | - | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-embedding-model'])[1] | - | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-speech-model'])[1] | + Then I should see "model values and autocomplete inputs" elements with selectors: + | element description | selector | + | default language model value test-model | text='test-model' | + | default embedding model value test-embedding-model | text='test-embedding-model' | + | default speech model value test-speech-model | text='test-speech-model' | + | first autocomplete input with test-model | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-model'])[1] | + | second autocomplete input with test-embedding-model | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-embedding-model'])[1] | + | third autocomplete input with test-speech-model | xpath=(//div[contains(@class,'MuiAutocomplete-root')]//input[@value='test-speech-model'])[1] | # Verify the autocomplete is not empty and negative case remain explicit Then I should not see a "empty first autocomplete placeholder" element with selector "xpath=(//label[contains(text(),'Preference.SelectModel')])[1]" Then I should not see a "test-model after test-embedding-model (wrong order)" element with selector "xpath=//input[@value='test-embedding-model']/following::input[@value='test-model']" # Step 10: Add ComfyUI provider with workflow path When I click on "add provider button and select from preset dropdown and comfyui preset option and add provider submit and provider tab and add model button" elements with selectors: - | [data-testid='add-new-provider-button'] | - | div[role='combobox'] | - | li:has-text('comfyui') | - | [data-testid='add-provider-submit-button'] | - | button[role='tab']:has-text('comfyui') | - | [data-testid='add-new-model-button'] | + | element description | selector | + | add provider button | [data-testid='add-new-provider-button'] | + | select from preset dropdown | div[role='combobox'] | + | comfyui preset option | li:has-text('comfyui') | + | add provider submit button | [data-testid='add-provider-submit-button'] | + | provider tab comfyui | button[role='tab']:has-text('comfyui') | + | add model button | [data-testid='add-new-model-button'] | When I type "test-flux" in "model name input" element with selector "[data-testid='new-model-name-input']" When I click on "language feature checkbox and imageGeneration feature checkbox" elements with selectors: - | [data-testid='feature-checkbox-language'] | - | [data-testid='feature-checkbox-imageGeneration'] | + | element description | selector | + | language feature checkbox | [data-testid='feature-checkbox-language'] | + | imageGeneration feature checkbox | [data-testid='feature-checkbox-imageGeneration'] | When I type "C:/test/mock/workflow.json" in "workflow path input" element with selector "[data-testid='workflow-path-input']" When I click on a "save model button" element with selector "[data-testid='save-model-button']" Then I should see a "test-flux model chip" element with selector "[data-testid='model-chip-test-flux']" diff --git a/features/stepDefinitions/ui.ts b/features/stepDefinitions/ui.ts index 74876d27..7411cd9a 100644 --- a/features/stepDefinitions/ui.ts +++ b/features/stepDefinitions/ui.ts @@ -38,17 +38,19 @@ Then('I should see {string} elements with selectors:', async function(this: Appl throw new Error('No current window is available'); } - const descriptions = elementDescriptions.split(' and ').map(d => d.trim()); const rows = dataTable.raw(); const errors: string[] = []; - if (descriptions.length !== rows.length) { - throw new Error(`Mismatch: ${descriptions.length} element descriptions but ${rows.length} selectors provided`); + // Expect two-column format with header: | element description | selector | + const hasHeader = rows[0]?.length === 2 && rows[0][0]?.toLowerCase().includes('description'); + const dataRows = hasHeader ? rows.slice(1) : rows; + + if (dataRows[0]?.length !== 2) { + throw new Error('Table must have exactly 2 columns: | element description | selector |'); } // Check all elements in parallel for better performance - await Promise.all(rows.map(async ([selector], index) => { - const elementComment = descriptions[index]; + await Promise.all(dataRows.map(async ([elementComment, selector]) => { try { await currentWindow.waitForSelector(selector, { timeout: 10000 }); const isVisible = await currentWindow.isVisible(selector); @@ -106,18 +108,19 @@ Then('I should not see {string} elements with selectors:', async function(this: throw new Error('No current window is available'); } - const descriptions = elementDescriptions.split(' and ').map(d => d.trim()); const rows = dataTable.raw(); const errors: string[] = []; - if (descriptions.length !== rows.length) { - throw new Error(`Mismatch: ${descriptions.length} element descriptions but ${rows.length} selectors provided`); + // Expect two-column format with header: | element description | selector | + const hasHeader = rows[0]?.length === 2 && rows[0][0]?.toLowerCase().includes('description'); + const dataRows = hasHeader ? rows.slice(1) : rows; + + if (dataRows[0]?.length !== 2) { + throw new Error('Table must have exactly 2 columns: | element description | selector |'); } // Check all elements - for (let index = 0; index < rows.length; index++) { - const [selector] = rows[index]; - const elementComment = descriptions[index]; + for (const [elementComment, selector] of dataRows) { try { const element = currentWindow.locator(selector).first(); const count = await element.count(); @@ -168,18 +171,19 @@ When('I click on {string} elements with selectors:', async function(this: Applic throw new Error('Window "current" is not available'); } - const descriptions = elementDescriptions.split(' and ').map(d => d.trim()); const rows = dataTable.raw(); const errors: string[] = []; - if (descriptions.length !== rows.length) { - throw new Error(`Mismatch: ${descriptions.length} element descriptions but ${rows.length} selectors provided`); + // Expect two-column format with header: | element description | selector | + const hasHeader = rows[0]?.length === 2 && rows[0][0]?.toLowerCase().includes('description'); + const dataRows = hasHeader ? rows.slice(1) : rows; + + if (dataRows[0]?.length !== 2) { + throw new Error('Table must have exactly 2 columns: | element description | selector |'); } // Click elements sequentially (not in parallel) to maintain order and avoid race conditions - for (let index = 0; index < rows.length; index++) { - const [selector] = rows[index]; - const elementComment = descriptions[index]; + for (const [elementComment, selector] of dataRows) { try { await targetWindow.waitForSelector(selector, { timeout: 10000 }); const isVisible = await targetWindow.isVisible(selector); diff --git a/features/subWiki.feature b/features/subWiki.feature index 8b61df7e..d780fd45 100644 --- a/features/subWiki.feature +++ b/features/subWiki.feature @@ -15,8 +15,9 @@ Feature: Sub-Wiki Functionality When I launch the TidGi application And I wait for the page to load completely Then I should see "page body and workspaces" elements with selectors: - | div[data-testid^='workspace-']:has-text('wiki') | - | div[data-testid^='workspace-']:has-text('SubWiki') | + | element description | selector | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | + | SubWiki workspace | div[data-testid^='workspace-']:has-text('SubWiki') | # Enable file system watch for testing (default is false in production) When I update workspace "wiki" settings: | property | value | @@ -54,8 +55,9 @@ Feature: Sub-Wiki Functionality When I launch the TidGi application And I wait for the page to load completely Then I should see "page body and workspaces" elements with selectors: - | div[data-testid^='workspace-']:has-text('wiki') | - | div[data-testid^='workspace-']:has-text('SubWikiPreload') | + | element description | selector | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | + | SubWikiPreload workspace | div[data-testid^='workspace-']:has-text('SubWikiPreload') | # Enable file system watch for testing (default is false in production) When I update workspace "wiki" settings: | property | value | @@ -86,8 +88,9 @@ Feature: Sub-Wiki Functionality When I launch the TidGi application And I wait for the page to load completely Then I should see "page body and workspaces" elements with selectors: - | div[data-testid^='workspace-']:has-text('wiki') | - | div[data-testid^='workspace-']:has-text('SubWikiTagTree') | + | element description | selector | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | + | SubWikiTagTree workspace | div[data-testid^='workspace-']:has-text('SubWikiTagTree') | # Enable file system watch for testing (default is false in production) When I update workspace "wiki" settings: | property | value | @@ -119,8 +122,9 @@ Feature: Sub-Wiki Functionality When I launch the TidGi application And I wait for the page to load completely Then I should see "page body and workspaces" elements with selectors: - | div[data-testid^='workspace-']:has-text('wiki') | - | div[data-testid^='workspace-']:has-text('SubWikiFilter') | + | element description | selector | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | + | SubWikiFilter workspace | div[data-testid^='workspace-']:has-text('SubWikiFilter') | # Enable file system watch for testing (default is false in production) When I update workspace "wiki" settings: | property | value | @@ -145,8 +149,9 @@ Feature: Sub-Wiki Functionality When I launch the TidGi application And I wait for the page to load completely Then I should see "page body and workspaces" elements with selectors: - | div[data-testid^='workspace-']:has-text('wiki') | - | div[data-testid^='workspace-']:has-text('SubWikiSettings') | + | element description | selector | + | wiki workspace | div[data-testid^='workspace-']:has-text('wiki') | + | SubWikiSettings workspace | div[data-testid^='workspace-']:has-text('SubWikiSettings') | # Open the edit workspace window using existing step When I open edit workspace window for workspace with name "SubWikiSettings" And I switch to "editWorkspace" window diff --git a/features/sync.feature b/features/sync.feature index e0ba1fa8..430ab2c8 100644 --- a/features/sync.feature +++ b/features/sync.feature @@ -25,14 +25,16 @@ Feature: Git Sync And I switch to "editWorkspace" window And I wait for the page to load completely When I click on "saveAndSyncOptions accordion and syncToCloud toggle" elements with selectors: - | [data-testid='preference-section-saveAndSyncOptions'] | - | [data-testid='synced-local-workspace-switch'] | + | element description | selector | + | saveAndSyncOptions accordion| [data-testid='preference-section-saveAndSyncOptions'] | + | syncToCloud toggle | [data-testid='synced-local-workspace-switch'] | And I wait for 1 seconds When I type in "git url input and github username input and github email input and github token input" elements with selectors: - | {tmpDir}/remote-repo-menu.git | label:has-text('Git仓库线上网址') + * input, label:has-text('Git Repo URL') + * input, input[aria-label='Git仓库线上网址'], input[aria-label='Git Repo URL'] | - | test-user | [data-testid='github-userName-input'] input | - | test@tidgi.test | [data-testid='github-email-input'] input | - | test-token | [data-testid='github-token-input'] input | + | element description | selector | + | git url input | label:has-text('Git仓库线上网址') + * input, label:has-text('Git Repo URL') + * input, input[aria-label='Git仓库线上网址'], input[aria-label='Git Repo URL'] | + | github username input | [data-testid='github-userName-input'] input | + | github email input | [data-testid='github-email-input'] input | + | github token input | [data-testid='github-token-input'] input | When I click on a "save workspace button" element with selector "[data-testid='edit-workspace-save-button']" # Wait for workspace to be saved (workspace.update triggers a restart which takes time) And I wait for 5 seconds diff --git a/features/talkWithAI.feature b/features/talkWithAI.feature index 68df57d3..967907cf 100644 --- a/features/talkWithAI.feature +++ b/features/talkWithAI.feature @@ -23,30 +23,34 @@ Feature: Talk with AI from Wiki Selection # Wait for agent workspace to be created and activate it to ensure React components are mounted Then I should see a "agent workspace button" element with selector "[data-testid='workspace-agent']" When I click on "agent workspace button and wiki workspace button" elements with selectors: - | [data-testid='workspace-agent'] | - | div[data-testid^='workspace-']:has-text('wiki') | + | element description | selector | + | agent workspace button | [data-testid='workspace-agent'] | + | wiki workspace button | div[data-testid^='workspace-']:has-text('wiki') | # Trigger "Talk with AI" - should create new split view When I send ask AI with selection message with text "Click button on top-right of this card to start edit." and workspace "wiki" Then I should see "split view container and wiki embed and chat input" elements with selectors: - | [data-testid='split-view-container'] | - | [data-testid='wiki-embed-view'] | - | [data-testid='agent-message-input'] | + | element description | selector | + | split view container | [data-testid='split-view-container'] | + | wiki embed | [data-testid='wiki-embed-view'] | + | chat input | [data-testid='agent-message-input'] | And I confirm the "main" window browser view is positioned within visible window bounds And I should see 2 messages in chat history # Part 2: Reuse active split view - messages should accumulate (not reset) When I send ask AI with selection message with text "How to edit?" and workspace "wiki" Then I should see "split view container with 4 messages" elements with selectors: - | [data-testid='split-view-container'] | + | element description | selector | + | split view container with 4 messages| [data-testid='split-view-container'] | # Should see 4 messages now (2 from part 1 + 2 new ones) - proves tab was reused And I should see 4 messages in chat history # Part 3: Create new tab when starting from regular chat When I click on a "agent workspace button" element with selector "[data-testid='workspace-agent']" When I click on "new tab button and search input and agent suggestion" elements with selectors: - | [data-tab-id='new-tab-button'] | - | .aa-Input | - | [data-autocomplete-source-id="agentsSource"] .aa-ItemWrapper | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | search input | .aa-Input | + | agent suggestion | [data-autocomplete-source-id="agentsSource"] .aa-ItemWrapper | When I send ask AI with selection message with text "First question" and workspace "wiki" Then I should see a "split view container" element with selector "[data-testid='split-view-container']" # Should see only 2 messages (new tab was created, not reused) @@ -55,9 +59,10 @@ Feature: Talk with AI from Wiki Selection # Part 4: Verify split view doesn't interfere with regular chat # Create another regular chat tab When I click on "new tab button and search input and agent suggestion" elements with selectors: - | [data-tab-id='new-tab-button'] | - | .aa-Input | - | [data-autocomplete-source-id="agentsSource"] .aa-ItemWrapper | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | search input | .aa-Input | + | agent suggestion | [data-autocomplete-source-id="agentsSource"] .aa-ItemWrapper | # Now in regular chat tab - split view and browser view should not be visible Then I should not see a "split view container" element with selector "[data-testid='split-view-container']" And I confirm the "main" window browser view is not positioned within visible window bounds diff --git a/features/tidgiMiniWindow.feature b/features/tidgiMiniWindow.feature index 9c97b3b5..9aa4ac7d 100644 --- a/features/tidgiMiniWindow.feature +++ b/features/tidgiMiniWindow.feature @@ -16,8 +16,9 @@ Feature: TidGi Mini Window And I confirm the "tidgiMiniWindow" window exists And I confirm the "tidgiMiniWindow" window not visible Then I should see "always on top toggle and workspace sync toggle" elements with selectors: - | [data-testid='tidgi-mini-window-always-on-top-switch'] | - | [data-testid='tidgi-mini-window-sync-workspace-switch'] | + | element description | selector | + | always on top toggle | [data-testid='tidgi-mini-window-always-on-top-switch'] | + | workspace sync toggle | [data-testid='tidgi-mini-window-sync-workspace-switch'] | Then I click on a "shortcut register button" element with selector "[data-testid='shortcut-register-button']" And I press the key combination "CommandOrControl+Shift+M" And I click on a "shortcut confirm button" element with selector "[data-testid='shortcut-confirm-button']" diff --git a/features/tidgiMiniWindowWorkspace.feature b/features/tidgiMiniWindowWorkspace.feature index de0e6eb9..02b3fc15 100644 --- a/features/tidgiMiniWindowWorkspace.feature +++ b/features/tidgiMiniWindowWorkspace.feature @@ -36,8 +36,9 @@ Feature: TidGi Mini Window Workspace Switching And I click on an "open preferences button" element with selector "#open-preferences-button" And I switch to "preferences" window When I click on "tidgi mini window section and disable sync workspace switch" elements with selectors: - | [data-testid='preference-section-tidgiMiniWindow'] | - | [data-testid='tidgi-mini-window-sync-workspace-switch'] | + | element description | selector | + | tidgi mini window section | [data-testid='preference-section-tidgiMiniWindow'] | + | disable sync workspace switch | [data-testid='tidgi-mini-window-sync-workspace-switch'] | # Enable sidebar to see workspace buttons And I click on a "Enable sidebar toggle switch" element with selector "[data-testid='sidebar-on-tidgi-mini-window-switch']" And I wait for 0.2 seconds @@ -79,12 +80,14 @@ Feature: TidGi Mini Window Workspace Switching Scenario: Enabling sync workspace automatically hides sidebar # Configure tidgi mini window with fixed workspace first When I click on "agent workspace button and open preferences button" elements with selectors: - | [data-testid='workspace-agent'] | - | #open-preferences-button | + | element description | selector | + | agent workspace button | [data-testid='workspace-agent']| + | open preferences button | #open-preferences-button | And I switch to "preferences" window When I click on "tidgi mini window section and disable sync workspace switch" elements with selectors: - | [data-testid='preference-section-tidgiMiniWindow'] | - | [data-testid='tidgi-mini-window-sync-workspace-switch'] | + | element description | selector | + | tidgi mini window section | [data-testid='preference-section-tidgiMiniWindow'] | + | disable sync workspace switch | [data-testid='tidgi-mini-window-sync-workspace-switch'] | And I should see a "sidebar toggle switch" element with selector "[data-testid='sidebar-on-tidgi-mini-window-switch']" # Enable sidebar to see it in mini window And I click on a "Enable sidebar toggle switch" element with selector "[data-testid='sidebar-on-tidgi-mini-window-switch']" @@ -103,8 +106,9 @@ Feature: TidGi Mini Window Workspace Switching When I click on a "Enable tidgi mini window sync workspace switch" element with selector "[data-testid='tidgi-mini-window-sync-workspace-switch']" # Verify sidebar option is now hidden And I should not see "sidebar toggle switch and fixed workspace select" elements with selectors: - | [data-testid='sidebar-on-tidgi-mini-window-switch'] | - | [data-testid='tidgi-mini-window-fixed-workspace-select'] | + | element description | selector | + | sidebar toggle switch | [data-testid='sidebar-on-tidgi-mini-window-switch'] | + | fixed workspace select | [data-testid='tidgi-mini-window-fixed-workspace-select'] | # Open tidgi mini window in sync mode - should sync to agent workspace When I press the key combination "CommandOrControl+Shift+M" And I confirm the "tidgiMiniWindow" window visible @@ -121,8 +125,9 @@ Feature: TidGi Mini Window Workspace Switching And I click on an "open preferences button" element with selector "#open-preferences-button" And I switch to "preferences" window When I click on "tidgi mini window section and disable sync workspace switch" elements with selectors: - | [data-testid='preference-section-tidgiMiniWindow'] | - | [data-testid='tidgi-mini-window-sync-workspace-switch'] | + | element description | selector | + | tidgi mini window section | [data-testid='preference-section-tidgiMiniWindow'] | + | disable sync workspace switch | [data-testid='tidgi-mini-window-sync-workspace-switch'] | # Enable sidebar to see workspace buttons And I click on a "Enable sidebar toggle switch" element with selector "[data-testid='sidebar-on-tidgi-mini-window-switch']" And I wait for 0.2 seconds @@ -140,5 +145,6 @@ Feature: TidGi Mini Window Workspace Switching And I wait for 0.2 seconds # Verify guide workspace is now active and agent workspace is no longer active And I should see "guide workspace button with active state and agent workspace button without active state" elements with selectors: - | [data-testid='workspace-guide'][data-active='true'] | - | [data-testid='workspace-agent'][data-active='false'] | \ No newline at end of file + | element description | selector | + | guide workspace button with active state| [data-testid='workspace-guide'][data-active='true'] | + | agent workspace button without active state| [data-testid='workspace-agent'][data-active='false'] | \ No newline at end of file diff --git a/features/vectorSearch.feature b/features/vectorSearch.feature index 949d103e..2dfee6ec 100644 --- a/features/vectorSearch.feature +++ b/features/vectorSearch.feature @@ -55,7 +55,8 @@ Feature: Vector Search - Embedding Generation and Semantic Search Then I should see 16 messages in chat history # Verify the last message contains vector search results And I should see "search result in last message" elements with selectors: - | [data-testid='message-bubble']:last-child:has-text('Tiddler: AI Agent Guide') | + | element description | selector | + | search result in last message| [data-testid='message-bubble']:last-child:has-text('Tiddler: AI Agent Guide') | @vectorSearch @mockOpenAI Scenario: UI workflow - Generate embeddings via preferences, then search @@ -69,17 +70,17 @@ Feature: Vector Search - Embedding Generation and Semantic Search | 根据向量搜索结果,在工作区 wiki 中找到以下相关内容:\n\n**Tiddler: Machine Learning Basics** (Similarity: 98.0%)\n这篇笔记介绍了机器学习的基本概念。 | false | | # Step 1: Create a test note via agent When I click on "new tab button and create default agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-default-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create default agent button| [data-testid='create-default-agent-button'] | And I should see a "message input box" element with selector "[data-testid='agent-message-input']" When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']" When I type "在 wiki 工作区创建一个名为 Machine Learning Basics 的笔记,内容是:机器学习是人工智能的一个分支,通过算法让计算机从数据中学习规律。" in "chat input" element with selector "[data-testid='agent-message-input']" And I press "Enter" key Then I should see 4 messages in chat history - # Step 2: Open preferences and manually generate embeddings via UI + # Step 2: Open preferences and navigate to Search section to generate embeddings When I click on a "settings button" element with selector "#open-preferences-button" When I switch to "preferences" window - # Navigate to Search section (which contains vector database settings) When I click on a "search section" element with selector "[data-testid='preference-section-search']" # Wait for workspace list to load # The Search.tsx renders workspace cards with name, status, and buttons @@ -90,12 +91,13 @@ Feature: Vector Search - Embedding Generation and Semantic Search # Verify generation completed with detailed status information # Should show: workspace name, embedding count, note count, last updated time and action buttons Then I should see "workspace name in status and embedding count status and embedding word and last updated label and update button after generation and delete button after generation" elements with selectors: - | *:has-text('wiki') | - | *:has-text('个笔记') | - | *:has-text('嵌入') | - | *:has-text('最后更新') | - | button:has-text('更新嵌入') | - | button:has-text('删除') | + | element description | selector | + | workspace name in status | *:has-text('wiki') | + | embedding count status | *:has-text('个笔记') | + | embedding word | *:has-text('嵌入') | + | last updated label | *:has-text('最后更新') | + | update button after generation | button:has-text('更新嵌入') | + | delete button after generation | button:has-text('删除') | # Close preferences When I close "preferences" window And I switch to "main" window @@ -127,8 +129,9 @@ Feature: Vector Search - Embedding Generation and Semantic Search | 根据向量搜索结果,在工作区 wiki 中找到以下相关内容:\n\n**Tiddler: AI Technology** (Similarity: 15.0%)\n低相似度结果。 | false | | # Step 1: Open agent chat interface When I click on "new tab button and create default agent button" elements with selectors: - | [data-tab-id='new-tab-button'] | - | [data-testid='create-default-agent-button'] | + | element description | selector | + | new tab button | [data-tab-id='new-tab-button'] | + | create default agent button| [data-testid='create-default-agent-button'] | And I should see a "message input box" element with selector "[data-testid='agent-message-input']" # Step 2: Create first note about AI When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']" @@ -152,8 +155,9 @@ Feature: Vector Search - Embedding Generation and Semantic Search Then I should see 16 messages in chat history # Verify the 16th message contains "no results found" with threshold info Then I should see "no results in 16th message and threshold 0.7 in 16th message" elements with selectors: - | [data-testid='message-bubble']:nth-child(16):has-text('未找到符合条件') | - | [data-testid='message-bubble']:nth-child(16):has-text('0.7') | + | element description | selector | + | no results in 16th message | [data-testid='message-bubble']:nth-child(16):has-text('未找到符合条件') | + | threshold 0.7 in 16th message| [data-testid='message-bubble']:nth-child(16):has-text('0.7') | # Step 6: Lower threshold and search again (should find low-similarity results) When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']" When I type "再次搜索天气预报,但这次把阈值降低到0.1" in "chat input" element with selector "[data-testid='agent-message-input']" @@ -161,5 +165,6 @@ Feature: Vector Search - Embedding Generation and Semantic Search Then I should see 20 messages in chat history # Verify the 20th message contains low-similarity result Then I should see "AI Technology and low similarity in 20th message" elements with selectors: - | [data-testid='message-bubble']:nth-child(20):has-text('Tiddler: AI Technology') | - | [data-testid='message-bubble']:nth-child(20):has-text('15') | + | element description | selector | + | AI Technology in 20th message | [data-testid='message-bubble']:nth-child(20):has-text('Tiddler: AI Technology') | + | low similarity in 20th message | [data-testid='message-bubble']:nth-child(20):has-text('15') | diff --git a/features/workspaceConfig.feature b/features/workspaceConfig.feature index f4bd65aa..cccf8f5f 100644 --- a/features/workspaceConfig.feature +++ b/features/workspaceConfig.feature @@ -28,7 +28,8 @@ Feature: Workspace Configuration Sync When I remove workspace "WikiRenamed" keeping files # Step 4: Verify workspace is removed but config file still exists Then I should not see "wiki workspace in sidebar" elements with selectors: - | div[data-testid^='workspace-']:has-text('WikiRenamed') | + | element description | selector | + | wiki workspace in sidebar| div[data-testid^='workspace-']:has-text('WikiRenamed') | Then file "wiki/tidgi.config.json" should exist in "wiki-test" # Step 5: Re-add the workspace by opening existing wiki # Clear previous log markers before waiting for new ones