mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-04-07 14:21:26 -07:00
* 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>
168 lines
12 KiB
Gherkin
168 lines
12 KiB
Gherkin
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']"
|