TidGi-Desktop/features/talkWithAI.feature
lin onetwo a931058f17
chore: upgrade Electron 39->41 + forge 7.10->7.11 + fix native ABI (#692)
* chore: upgrade Electron 39->41, forge 7.10->7.11, fix native ABI and preload naming

- electron: 39.2.3 -> 41.1.1
- @electron-forge/*: 7.10.2 -> 7.11.1
- better-sqlite3: 12.4.5 -> 12.8.0 (rebuild against Electron 41 ABI 145)
- electron-unhandled: 5.0.0 -> 4.0.1 (v5 uses top-level await, breaks CJS main build)
- vite.preload.config.ts: emit preload.js (not index.js) to avoid collision with main
- viteEntry.ts: getPreloadPath() -> preload.js, renderer path unchanged
- package.json main: .vite/build/main.js (matches forge lib output)
- package.json: strip UTF-8 BOM that broke Volta manifest parsing

* fix: resolve AbortSignal realm mismatch in Electron 41 for streaming tests

In Electron 41, ELECTRON_RUN_AS_NODE mode uses Chromium-based fetch which
requires Blink's AbortSignal. Node.js AbortSignal fails the instanceof check.

Fixes:
- vitest.config.ts: set features/** to node environment via environmentMatchGlobs
  so HTTP-only tests use Node.js fetch (not Chromium fetch)
- setup-vitest.ts: guard all document/window access behind typeof document check
  so setup is safe in both jsdom and node environments
- callProviderAPI.ts: no change needed (signal issue is env-specific)

* ci: increase test timeout to 60min, fix find -o with xargs rm

- timeout-minutes: 25 -> 60 (packaging ~22min + unit tests ~1min + e2e needed)
- fix 'find ... -o ... | xargs rm' -> 'find ... \( -o \) ... -exec rm -rf {} +'
  (the unparenthesized -o with xargs caused 'rm: invalid option -- o' in CI)

* fix: copy tiddlywiki/core-server to packaged output

TiddlyWiki 5.4.0-prerelease introduced core-server/ directory which contains
commander.js (module-type: global). Without it, \.Commander is undefined
when load-modules.js startup runs \.Commander.initCommands(), crashing the
wiki worker with 'Cannot read properties of undefined (reading initCommands)'.

core-server is loaded by boot.js via loadPluginFolder(\.boot.coreServerPath),
which silently returns null when the directory is missing, so the error was
non-obvious and only manifested when actually starting a wiki workspace.

* perf: only screenshot on failure, revert timeout to 25min

AfterStep was capturing a screenshot after every step (~1191 of 1446 steps).
Each screenshot requires IPC round-trip: getFirstWebContentsView  capturePage
 serialize PNG  transfer buffer  fs.writeFile. On CI this costs ~200-400ms
per step, totaling ~6 minutes of pure screenshot overhead.

Now screenshots are only taken for FAILED steps, saving ~6 minutes on CI.
This brings the total test time well within the 25-minute budget.

* fix: flaky tests + merge scenarios to save 8 Electron launches

- crossWindowSync: wait for tiddler to be saved to disk via watch-fs before opening second window
- tidgiMiniWindowWorkspace: add retry backoff to 'should not see elements' step
- tidgiMiniWindow: add explicit window switch after addTiddler
- Merge 5 filesystemPlugin scenarios into 1 (save 4 launches)
- Merge 2 defaultWiki scenarios into 1 (save 1 launch)
- Merge 2 preference scenarios into 1 (save 1 launch)
- Merge smoke + logging into 1 (save 1 launch)
- Merge 2 tiddler scenarios into 1 (save 1 launch)
- Total: 65  57 scenarios (8 fewer Electron launches)

* fix: address CI failures - use IPC for mini window toggle, split talkWithAI clicks

- tidgiMiniWindow: use direct IPC toggle instead of keyboard shortcut after addTiddler
  to avoid race condition between TW syncer and keyboard event dispatch
- talkWithAI: split multi-click step into individual clicks so each gets its own
  25s timeout budget on CI

* fix: await showWindow() in openTidgiMiniWindow to prevent race condition

The two showWindow() calls were using void (fire-and-forget), meaning
toggleTidgiMiniWindow returned before the window was actually shown.
On CI/Xvfb, the test checked isVisible() before show() completed.

* perf: merge scenarios + split CI steps for faster E2E

- Merge 3 defaultWiki scenarios into 1 (save 2 app launches)
- Merge 2 scheduledTask scenarios into 1 (save 1 app launch)
- Split CI test step into unit/prepare/e2e for visibility
- Add pnpm store cache to CI
- Fix viteEntry.ts: remove UTF-8 BOM, update stale JSDoc comment
- Set E2E timeout to 22min (was 25min in single step)

* fix: address Copilot review - main window lookup and comment clarity

- tidgiMiniWindow.ts: use index.html URL pattern to find main window
  (consistent with other step defs, avoids matching preferences window)
- ui.ts: clarify networkidle timeout comment

* fix: use IPC toggle for tidgiMiniWindow sync scenario to avoid flaky keyboard shortcut on CI

---------

Co-authored-by: CI Auto <cidevel@tiddlygit.local>
2026-04-02 21:45:47 +08:00

168 lines
12 KiB
Gherkin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Feature: Talk with AI from Wiki Selection
As a user
I want to select text in wiki and talk with AI about it
So that I can get AI-powered explanations in a split view
Background:
Given I add test ai settings
@talkWithAI @mockOpenAI
Scenario: Talk with AI - complete workflow
Given I have started the mock OpenAI server
| response | stream |
| | false |
| | false |
| 访 | false |
| | false |
# Launch application after mock server is ready
Then I launch the TidGi application
And I wait for the page to load completely
And I should see a "page body" element with selector "body"
# Part 1: Create new split view from wiki selection
When I click on a "wiki workspace button" element with selector "div[data-testid^='workspace-']:has-text('wiki')"
# 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:
| 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:
| 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:
| 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:
| 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)
And I should see 2 messages in chat history
# Part 4: Verify split view doesn't interfere with regular chat
# Create another regular chat tab (split into individual clicks for CI reliability)
When I click on a "new tab button" element with selector "[data-tab-id='new-tab-button']"
And I click on a "search input" element with selector ".aa-Input"
And I click on an "agent suggestion" element with selector "[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
# Switch to wiki workspace - browser view should exist for wiki
When I click on a "wiki workspace button" element with selector "div[data-testid^='workspace-']:has-text('wiki')"
And I wait for 1 seconds for "browser view repositioning after workspace switch"
Then I confirm the "main" window browser view is positioned within visible window bounds
@agent @mockOpenAI
Scenario: Wiki tiddler attachment with rendered content
# Start mock server and launch app (not in Background for this feature)
Given I have started the mock OpenAI server
| response | stream |
| wiki | false |
Then I launch the TidGi application
And I wait for the page to load completely
And I should see a "page body" element with selector "body"
# First, navigate to wiki workspace and create a test tiddler with wikitext content
When I click on a "default wiki workspace button" element with selector "div[data-testid^='workspace-']:has-text('wiki')"
Then the browser view should be loaded and visible
And I wait for "SSE backend ready" log marker "[test-id-SSE_READY]"
# Create a new tiddler with wikitext syntax
When I execute TiddlyWiki code in browser view: "$tw.wiki.addTiddler(new $tw.Tiddler({title: 'TestAttachmentTiddler', text: '!!WikiTestHeader\\n\\nThis is a test with WikiTestContentMarker123', type: 'text/vnd.tiddlywiki'}))"
# Navigate to agent workspace and create agent
When I click on "agent workspace button and create default agent button" elements with selectors:
| element description | selector |
| agent workspace button | [data-testid='workspace-agent'] |
| 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']"
# Click attachment button to open autocomplete
When I click on a "attach button" element with selector "[data-testid='agent-attach-button']"
# Autocomplete should open showing image option + tiddler options
And I should see a "attachment autocomplete input" element with selector "[data-testid='attachment-autocomplete-input']"
And I should see a "attachment listbox" element with selector "[data-testid='attachment-listbox']"
# Click on our test tiddler option
When I click on a "test tiddler option" element with selector "[data-testid='attachment-option-tiddler-TestAttachmentTiddler']"
# Verify the chip is displayed
Then I should see a "wiki tiddler chip" element with selector "[data-testid='wiki-tiddler-chip-0']"
# Type message and send
When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']"
When I type "" in "chat input" element with selector "[data-testid='agent-message-input']"
And I press "Enter" key
# Verify the mock server received the rendered content (wikitext converted to plain text)
Then the last AI request user message should contain "WikiTestContentMarker123"
And the last AI request user message should contain "Wiki Entry from"
And the last AI request user message should contain "TestAttachmentTiddler"
# Verify wikitext was converted to plain text (!! becomes "Header", not raw !!)
And the last AI request user message should contain "WikiTestHeader"
And the last AI request user message should not contain "!!"
@agent @mockOpenAI @streamingStatus @imageUpload
Scenario: Image upload streaming status and history verification
# Start mock server and launch app
Given I have started the mock OpenAI server
| response | stream |
| Received image and text | false |
| Received second message | false |
Then I launch the TidGi application
And I wait for the page to load completely
And I should see a "page body" element with selector "body"
# Navigate to agent workspace and open agent chat
When I click on an "agent workspace button" element with selector "[data-testid='workspace-agent']"
When I click on a "new tab button" element with selector "[data-tab-id='new-tab-button']"
And I should see a "search interface" element with selector ".aa-Autocomplete"
When I click on a "search input box" element with selector ".aa-Input"
And I should see an "autocomplete panel" element with selector ".aa-Panel"
When I click on an "agent suggestion" element with selector '[data-autocomplete-source-id="agentsSource"] .aa-ItemWrapper'
And I should see a "message input box" element with selector "[data-testid='agent-message-input']"
# Click attachment button to open autocomplete
When I click on a "attach button" element with selector "[data-testid='agent-attach-button']"
# Wait for autocomplete to open
And I should see a "attachment autocomplete input" element with selector "[data-testid='attachment-autocomplete-input']"
# Register Playwright filechooser intercept BEFORE clicking Add Image so the
# native OS dialog never appears; the chooser is resolved directly with the file.
When I prepare to select file "template/wiki/files/TiddlyWikiIconBlack.png" for file chooser
# Click on "Add Image" option — triggers fileInput.click() which fires filechooser
When I click on a "add image option" element with selector "[data-testid='attachment-option-image-AddImage']"
# Verify image preview appears
Then I should see an "attachment preview" element with selector "[data-testid='attachment-preview']"
# Send message with image
When I click on a "message input textarea" element with selector "[data-testid='agent-message-input']"
When I type "Describe this image" in "chat input" element with selector "[data-testid='agent-message-input']"
And I press "Enter" key
Then I should see 2 messages in chat history
# Verify image appears in chat history
And I should see a "message image attachment" element with selector "[data-testid='message-image-attachment']"
# Verify send button returned to normal after first message
And I should see a "send button icon" element with selector "[data-testid='send-icon']"
And I should not see a "cancel button icon" element with selector "[data-testid='cancel-icon']"
# Send second message to check history includes image
When I type "Continue" 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
# Verify send button is still normal after second message
And I should see a "send button icon" element with selector "[data-testid='send-icon']"
And I should not see a "cancel button icon" element with selector "[data-testid='cancel-icon']"