feat: tauri mocking#92
Conversation
e5d9145 to
0087da0
Compare
Greptile OverviewGreptile SummaryThis PR implements comprehensive mocking infrastructure for Tauri by migrating from Key Changes:
Issues Found:
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| packages/tauri-service/src/mock.ts | Updated references from @vitest/spy to @wdio/native-spy for mocking |
| packages/tauri-plugin/guest-js/index.ts | Migrated from @vitest/spy to @wdio/native-spy, restructured type declarations |
| packages/bundler/src/plugins.ts | Added browserGlobalsPlugin for window global replacements, potential issue with nested window references |
| packages/bundler/src/cli/commands.ts | Implemented browserBuildCommand with config validation and error handling |
| packages/bundler/src/cli/analyzer.ts | Added browser-specific plugin spec builders for TypeScript, externals, and globals |
| packages/tauri-plugin/wdio-bundler.config.ts | New bundler config for browser builds with globals and externals configuration |
Sequence Diagram
sequenceDiagram
participant Test as Test Suite
participant TauriService as @wdio/tauri-service
participant Browser as Browser Context
participant GuestJS as guest-js (bundled)
participant NativeSpy as @wdio/native-spy
participant TauriAPI as Tauri Core API
Note over Test,TauriAPI: Mocking Flow
Test->>TauriService: createMock('command_name')
TauriService->>NativeSpy: fn() - create mock function
TauriService->>Browser: execute setup script
Browser->>GuestJS: Check window.__native_spy__
GuestJS->>NativeSpy: Access bundled spy.fn()
NativeSpy-->>GuestJS: Return mock function
GuestJS->>Browser: Store in window.__wdio_mocks__['command_name']
GuestJS->>TauriAPI: Wrap invoke() with interception
Browser-->>TauriService: Mock created
Note over Test,TauriAPI: Command Execution with Mock
Test->>Browser: Invoke Tauri command
Browser->>TauriAPI: invoke('command_name', args)
TauriAPI->>GuestJS: Intercepted by wrapped invoke
GuestJS->>Browser: Check window.__wdio_mocks__['command_name']
Browser-->>GuestJS: Return mock function
GuestJS->>NativeSpy: Call mock(args)
NativeSpy-->>GuestJS: Return mocked value
GuestJS-->>Browser: Return result
Browser-->>Test: Mocked response
Note over Test,TauriAPI: Mock State Synchronization
Test->>TauriService: mock.update()
TauriService->>Browser: execute state extraction
Browser->>GuestJS: Access mock.calls, mock.results
GuestJS-->>Browser: Serialize state
Browser-->>TauriService: Return mock state
TauriService->>TauriService: Update local mock object
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
1560fae to
1d58788
Compare
| # This is needed by the E2E app's build process (for bundling) | ||
| - name: 🏗️ Build Tauri Plugin JavaScript | ||
| run: pnpm exec turbo run build:js --filter=@wdio/tauri-plugin | ||
| run: pnpm exec turbo run build:guest-js --filter=@wdio/tauri-plugin |
Check failure
Code scanning / CodeQL
Artifact poisoning Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
General approach: ensure that downloaded artifacts cannot override existing repository files used by the subsequent pnpm exec turbo ... command, and treat artifact content as untrusted. This is typically done by (1) extracting artifacts into a dedicated directory (often under ${{ runner.temp }}), and (2) only copying or using specific expected files from there, ideally with simple validation.
In this repository, the vulnerable flow is: _ci-build-tauri-e2e-app.reusable.yml calls ./.github/workflows/actions/download-archive with path: wdio-desktop-mobile-build, which is likely inside the working directory and may collide with source files. A targeted mitigation within the provided snippets is to change the path so that artifacts are downloaded/extracted into a temp directory under ${{ runner.temp }}, which is less likely to contain source or executable scripts, and then explicitly copy only the needed content from that temp folder into wdio-desktop-mobile-build (or another controlled location) before running pnpm. Since we must keep functional behavior, we keep the final location name the same but add an explicit copy step from the temp directory to the working directory, after download and before pnpm install. This ensures artifacts do not directly overwrite repo-managed files; instead, they populate a dedicated target directory that the workflow explicitly manages.
Concretely:
- In
.github/workflows/_ci-build-tauri-e2e-app.reusable.yml:- Change the
pathinput passed todownload-archivefromwdio-desktop-mobile-buildto${{ runner.temp }}/wdio-desktop-mobile-build. - Immediately after the download step, add a shell step that:
- Clears the workspace
wdio-desktop-mobile-builddirectory (if present). - Recreates it and copies the contents from
${{ runner.temp }}/wdio-desktop-mobile-buildintowdio-desktop-mobile-build.
- Clears the workspace
- Change the
- No changes to
.github/workflows/actions/download-archive/action.ymlare strictly required by the given snippets; we only adjust how it is used.
This keeps the downstream steps (pnpm install, pnpm exec turbo ...) working with the expected directory name while avoiding direct artifact extraction into the repository workspace.
| @@ -147,11 +147,31 @@ | ||
| uses: ./.github/workflows/actions/download-archive | ||
| with: | ||
| name: wdio-desktop-mobile | ||
| path: wdio-desktop-mobile-build | ||
| path: ${{ runner.temp }}/wdio-desktop-mobile-build | ||
| filename: artifact.zip | ||
| cache_key_prefix: wdio-desktop-build | ||
| exact_cache_key: ${{ inputs.cache_key || github.run_id && format('{0}-{1}-{2}-{3}{4}', 'Linux', 'wdio-desktop-build', 'wdio-desktop-mobile', github.run_id, github.run_attempt > 1 && format('-rerun{0}', github.run_attempt) || '') || '' }} | ||
|
|
||
| # Safely copy artifact contents into the workspace directory | ||
| - name: 📂 Prepare Package Build Directory | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| TEMP_SRC="${{ runner.temp }}/wdio-desktop-mobile-build" | ||
| DEST="wdio-desktop-mobile-build" | ||
|
|
||
| # Ensure destination directory is clean and controlled | ||
| if [ -d "$DEST" ]; then | ||
| rm -rf "$DEST" | ||
| fi | ||
| mkdir -p "$DEST" | ||
|
|
||
| if [ -d "$TEMP_SRC" ]; then | ||
| cp -R "$TEMP_SRC"/. "$DEST"/ | ||
| else | ||
| echo "::warning::Expected artifact directory '$TEMP_SRC' not found; continuing without copied artifacts" | ||
| fi | ||
|
|
||
| # Display build information if available | ||
| - name: 📊 Show Build Information | ||
| if: inputs.build_id != '' && inputs.artifact_size != '' |
Ensuring the Tauri service mocking is functionally complete and has feature parity with the Electron service