Skip to content

feat: tauri mocking#92

Closed
goosewobbler wants to merge 7 commits intomainfrom
feat/enable-tauri-mocking
Closed

feat: tauri mocking#92
goosewobbler wants to merge 7 commits intomainfrom
feat/enable-tauri-mocking

Conversation

@goosewobbler
Copy link
Copy Markdown
Contributor

@goosewobbler goosewobbler commented Jan 24, 2026

Ensuring the Tauri service mocking is functionally complete and has feature parity with the Electron service

@goosewobbler goosewobbler linked an issue Jan 24, 2026 that may be closed by this pull request
@goosewobbler goosewobbler force-pushed the feat/enable-tauri-mocking branch 6 times, most recently from e5d9145 to 0087da0 Compare January 25, 2026 15:06
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jan 28, 2026

Greptile Overview

Greptile Summary

This PR implements comprehensive mocking infrastructure for Tauri by migrating from @vitest/spy to a new @wdio/native-spy package and extending the bundler to support browser-mode builds. The changes ensure feature parity between Tauri and Electron service mocking capabilities.

Key Changes:

  • Migrated from @vitest/spy to @wdio/native-spy across tauri-plugin and tauri-service packages
  • Added browser build mode to @wdio/bundler with new build:browser command supporting ESM-only output, global replacements, and custom externals
  • Created browserGlobalsPlugin to replace package imports with window globals for runtime access
  • Refactored tauri-plugin build pipeline to use wdio-bundler instead of esbuild for consistency
  • Split type generation into separate build step (dist-types directory)
  • Re-enabled mocking E2E tests that were previously excluded

Issues Found:

  • Logic error in browserGlobalsPlugin causing nested window.window. references (line 155 in plugins.ts)

Confidence Score: 4/5

  • Safe to merge after fixing the browserGlobalsPlugin logic error
  • The implementation is well-structured with comprehensive browser build support and proper migration from vitest to native-spy. One critical logic bug prevents a perfect score - the nested window reference will cause runtime errors when the bundled code tries to access window.window.__native_spy__
  • packages/bundler/src/plugins.ts requires immediate fix for the nested window reference bug

Important Files Changed

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
Loading

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread packages/bundler/src/plugins.ts Outdated
goosewobbler and others added 3 commits February 3, 2026 02:26
@goosewobbler goosewobbler force-pushed the feat/enable-tauri-mocking branch from 1560fae to 1d58788 Compare February 3, 2026 02:26
# 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

Potential artifact poisoning in
pnpm exec turbo run build:guest-js --filter=@wdio/tauri-plugin
, which may be controlled by an external user (
workflow_dispatch
).
Potential artifact poisoning in
pnpm exec turbo run build:guest-js --filter=@wdio/tauri-plugin
, which may be controlled by an external user (
workflow_dispatch
).

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 path input passed to download-archive from wdio-desktop-mobile-build to ${{ runner.temp }}/wdio-desktop-mobile-build.
    • Immediately after the download step, add a shell step that:
      • Clears the workspace wdio-desktop-mobile-build directory (if present).
      • Recreates it and copies the contents from ${{ runner.temp }}/wdio-desktop-mobile-build into wdio-desktop-mobile-build.
  • No changes to .github/workflows/actions/download-archive/action.yml are 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.


Suggested changeset 1
.github/workflows/_ci-build-tauri-e2e-app.reusable.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/_ci-build-tauri-e2e-app.reusable.yml b/.github/workflows/_ci-build-tauri-e2e-app.reusable.yml
--- a/.github/workflows/_ci-build-tauri-e2e-app.reusable.yml
+++ b/.github/workflows/_ci-build-tauri-e2e-app.reusable.yml
@@ -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 != ''
EOF
@@ -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 != ''
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tauri Service - Mocking

2 participants