Skip to content

Conversation

@doubledare704
Copy link
Contributor

@doubledare704 doubledare704 commented Sep 14, 2025

feat(testing): add selective action stubbing support

  • Add support for include/exclude options in stubActions parameter
  • Allow stubbing only specific actions or excluding specific actions from stubbing
  • Maintain backward compatibility with boolean stubActions values
  • Add comprehensive tests for all selective stubbing scenarios
  • Update documentation with examples and usage patterns

Closes #2970

Summary by CodeRabbit

  • New Features

    • Selective stubbing of store actions: stub by explicit action list, by predicate function, or enable/disable globally.
  • Documentation

    • Added detailed guides (EN/ZH) with examples, tips, and usage patterns for selective action stubbing.
  • Tests

    • Added comprehensive tests covering array-based, predicate-based, empty/edge cases, and global stubbing behaviors.

@netlify
Copy link

netlify bot commented Sep 14, 2025

Deploy Preview for pinia-official ready!

Name Link
🔨 Latest commit d29f221
🔍 Latest deploy log https://app.netlify.com/projects/pinia-official/deploys/6908d2534157810008b9b86e
😎 Deploy Preview https://deploy-preview-3040--pinia-official.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 14, 2025

Walkthrough

Adds selective action stubbing to the testing utilities: stubActions now accepts boolean | string[] | (actionName: string, store: any) => boolean. Documentation (EN/CN) and tests updated; a shouldStubAction helper was introduced and used in createTestingPinia to decide per-action stubbing.

Changes

Cohort / File(s) Summary
Documentation - Selective Action Stubbing
packages/docs/cookbook/testing.md, packages/docs/zh/cookbook/testing.md
New documentation sections showing array-based and predicate-based stubActions usage, examples, tips about empty arrays and evaluation timing, and guidance for manual action mocking.
Implementation - Type & Logic
packages/testing/src/testing.ts
TestingOptions.stubActions type changed to boolean | string[] | ((actionName: string, store: any) => boolean). Added exported shouldStubAction helper and updated createTestingPinia to call it for per-action stubbing decisions.
Tests - Selective Stubbing Scenarios
packages/testing/src/testing.spec.ts
Added actions decrement() and setValue(newValue: number) to test stores. New test suite covers array-based stubbing, empty-array behavior, non-existent action names, predicate-based stubbing (including receipt of store instance), global stubbing flags, and plugin interactions.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant CT as createTestingPinia
    participant JS as shouldStubAction
    participant S as Store

    Dev->>CT: call createTestingPinia({ stubActions: config })
    CT->>CT: iterate store actions
    CT->>JS: shouldStubAction(actionName, store, config)
    alt config is array
        JS->>JS: check actionName in array
    else config is function
        JS->>JS: call predicate(actionName, store)
    else config is boolean
        JS->>JS: return boolean
    end
    JS-->>CT: return boolean
    alt true
        CT->>S: replace action with stub (mock)
    else false
        CT->>S: leave action as spyable/real
    end
    CT-->>Dev: return testing pinia with configured actions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to: shouldStubAction edge cases (empty array vs false), type signature changes in TestingOptions, and test assertions covering predicate invocation and plugin interactions.

"I nibble through code, soft and sly,
Stubbing just carrots I choose to try.
A hop, a patch, one action spared,
Tests snug as burrows, neatly prepared.
🐇✨"

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: add selective action stubbing support' directly and accurately describes the main objective of the changeset. It clearly identifies the primary feature being added—selective action stubbing—which is the central theme across all modified files including the documentation, tests, and implementation changes.
Linked Issues check ✅ Passed The pull request successfully addresses the primary objectives from issue #2970. The implementation extends stubActions to support selective stubbing through array-based and predicate function approaches (rather than include/exclude object format mentioned in the issue), maintains backward compatibility with boolean values, includes comprehensive test coverage for various stubbing scenarios, and provides documentation examples. While the implementation approach differs slightly from the proposed include/exclude object structure, it achieves the core goal of selective action stubbing.
Out of Scope Changes check ✅ Passed The changes remain focused and in-scope with the linked issue objectives. Documentation updates provide usage examples for selective stubbing, tests comprehensively validate the feature's behavior, and the implementation correctly extends the testing utilities. The addition of new test actions (decrement and setValue) and the helper function shouldStubAction are all directly necessary to support and validate the selective action stubbing feature.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d8630d and d29f221.

📒 Files selected for processing (2)
  • packages/docs/cookbook/testing.md (1 hunks)
  • packages/docs/zh/cookbook/testing.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/docs/zh/cookbook/testing.md
  • packages/docs/cookbook/testing.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@doubledare704 doubledare704 changed the title style: fix formatting with prettier feat: add selective action stubbing support Sep 14, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
packages/docs/zh/cookbook/testing.md (1)

176-239: 新增“选择性 action 存根”章节内容与实现一致。建议补充对 $reset 的特殊说明。

实现中 $resetstubReset 控制,stubActions(含 include/exclude)不会影响 $reset。为避免读者误解,建议在本节加一句明确说明。

应用此编辑(在提示块后增加一行):

 ::: tip
 如果同时提供了 `include` 和 `exclude`,`include` 优先。如果两者都没有提供或两个数组都为空,所有 action 都将被存根(等同于 `stubActions: true`)。
 :::
+> 注意:内置方法 `$reset` 不受 `stubActions`(包括 include/exclude)影响,请使用 `stubReset` 选项控制其是否存根。
packages/docs/cookbook/testing.md (1)

169-232: Selective stubbing docs match behavior. Add a short note about $reset being controlled via stubReset.

Code excludes $reset from stubActions handling and wires it via stubReset. A one-liner will prevent confusion.

Apply after the tip block:

 ::: tip
 If both `include` and `exclude` are provided, `include` takes precedence. If neither is provided or both arrays are empty, all actions will be stubbed (equivalent to `stubActions: true`).
 :::
+> Note: the built-in `$reset` is not affected by `stubActions` (including `include`/`exclude`). Use the `stubReset` option to control it.
packages/testing/src/testing.ts (2)

32-39: Clarify TSDoc to fully specify precedence and defaults for include/exclude.

Docs are correct but can be more explicit (matches implementation and user docs).

-   * not being executed. When set to an object with `include` or `exclude` arrays,
-   * only the specified actions will be stubbed or excluded from stubbing.
-   * Defaults to true. NOTE: when providing `createSpy()`,
+   * not being executed.
+   * When set to an object, you can pass `include` and/or `exclude` arrays for per‑action control:
+   * - if `include` is non‑empty, only listed actions are stubbed
+   * - else if `exclude` is non‑empty, all actions except those are stubbed
+   * - if both are omitted or empty, all actions are stubbed (equivalent to `true`)
+   * Defaults to `true`. NOTE: when providing `createSpy()`,

145-162: Logic is correct; small perf/readability tweak by precomputing sets.

Precompute include/exclude Sets once per store to avoid repeated array scans and tighten the branching.

-    Object.keys(options.actions).forEach((action) => {
-      if (action === '$reset') return
-
-      let shouldStub: boolean
-      if (typeof stubActions === 'boolean') {
-        shouldStub = stubActions
-      } else {
-        // Handle include/exclude logic
-        const { include, exclude } = stubActions
-        if (include && include.length > 0) {
-          shouldStub = include.includes(action)
-        } else if (exclude && exclude.length > 0) {
-          shouldStub = !exclude.includes(action)
-        } else {
-          // If both include and exclude are empty or undefined, default to true
-          shouldStub = true
-        }
-      }
-
-      store[action] = shouldStub ? createSpy() : createSpy(store[action])
-    })
+    const includeSet =
+      typeof stubActions === 'object' && stubActions.include?.length
+        ? new Set(stubActions.include)
+        : undefined
+    const excludeSet =
+      typeof stubActions === 'object' && stubActions.exclude?.length
+        ? new Set(stubActions.exclude)
+        : undefined
+
+    Object.keys(options.actions).forEach((action) => {
+      if (action === '$reset') return
+
+      const shouldStub =
+        typeof stubActions === 'boolean'
+          ? stubActions
+          : includeSet
+            ? includeSet.has(action)
+            : excludeSet
+              ? !excludeSet.has(action)
+              : true
+
+      store[action] = shouldStub ? createSpy() : createSpy(store[action])
+    })
packages/testing/src/testing.spec.ts (1)

412-594: Comprehensive coverage of include/exclude semantics; add one setup‑store case.

All primary paths are covered (include, exclude, empty arrays, precedence, booleans, unknown names). To guarantee parity for setup stores too, add one test exercising stubActions with a setup store’s actions.

Example to append:

it('applies selective stubbing to setup stores', () => {
  setActivePinia(
    createTestingPinia({
      stubActions: { include: ['increment'] },
      createSpy: vi.fn,
    })
  )
  const useSetup = defineStore('s', () => {
    const n = ref(0)
    function increment() { n.value++ }
    function decrement() { n.value-- }
    return { n, increment, decrement }
  })

  const s = useSetup()
  s.increment()
  expect(s.n).toBe(0)
  s.decrement()
  expect(s.n).toBe(-1)
})
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57bec95 and e40f969.

📒 Files selected for processing (5)
  • packages/docs/cookbook/testing.md (1 hunks)
  • packages/docs/zh/cookbook/testing.md (1 hunks)
  • packages/online-playground/package.json (1 hunks)
  • packages/testing/src/testing.spec.ts (2 hunks)
  • packages/testing/src/testing.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/testing/src/testing.spec.ts (1)
packages/testing/src/testing.ts (1)
  • createTestingPinia (95-186)
🔇 Additional comments (2)
packages/testing/src/testing.spec.ts (1)

27-44: Good focused fixture store for multi-action scenarios.

Covers a representative mix (mutating counters and value).

packages/docs/cookbook/testing.md (1)

169-232: AI summary incorrect — no duplicate found

Search shows a single occurrence at packages/docs/cookbook/testing.md:169; no action required.

@github-project-automation github-project-automation bot moved this to 🆕 Triaging in Pinia Roadmap Nov 1, 2025
@posva posva moved this from 🆕 Triaging to 📋 Backlog in Pinia Roadmap Nov 1, 2025
@posva posva moved this from 📋 Backlog to 🧑‍💻 In progress in Pinia Roadmap Nov 3, 2025
feat(testing): add selective action stubbing support

- Add support for include/exclude options in stubActions parameter
- Allow stubbing only specific actions or excluding specific actions from stubbing
- Maintain backward compatibility with boolean stubActions values
- Add comprehensive tests for all selective stubbing scenarios
- Update documentation with examples and usage patterns
- Fix workspace naming conflict in online-playground package

Closes vuejs#2970
@posva posva force-pushed the feature/issue-2970-selective-action-stubbing branch from 0d9ca09 to 6d8630d Compare November 3, 2025 15:58
Copy link
Member

@posva posva left a comment

Choose a reason for hiding this comment

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

Thanks! I adapted the API a bit

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 3, 2025

Open in StackBlitz

npm i https://pkg.pr.new/@pinia/nuxt@3040
npm i https://pkg.pr.new/pinia@3040
npm i https://pkg.pr.new/@pinia/testing@3040

commit: d29f221

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e40f969 and 6d8630d.

📒 Files selected for processing (4)
  • packages/docs/cookbook/testing.md (1 hunks)
  • packages/docs/zh/cookbook/testing.md (1 hunks)
  • packages/testing/src/testing.spec.ts (4 hunks)
  • packages/testing/src/testing.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/docs/zh/cookbook/testing.md
  • packages/docs/cookbook/testing.md
🧰 Additional context used
🧬 Code graph analysis (2)
packages/testing/src/testing.ts (2)
packages/testing/src/index.ts (1)
  • TestingOptions (5-5)
packages/pinia/src/types.ts (1)
  • StoreGeneric (484-489)
packages/testing/src/testing.spec.ts (1)
packages/testing/src/testing.ts (1)
  • createTestingPinia (103-180)

Comment on lines +43 to +46
stubActions?:
| boolean
| string[]
| ((actionName: string, store: any) => boolean)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Include/exclude object config is unsupported, so the new API fails.

Issue #2970 (and this PR’s description) call for stubActions to accept an object like { include, exclude }, but the current change only allows boolean | string[] | predicate. Passing the documented object either hits a TS error or falls through to the return false branch in shouldStubAction, meaning nothing gets stubbed. The flagship feature of this PR is therefore broken. Please extend the type to cover the object shape and update shouldStubAction to honor the include/exclude rules (e.g. include list acts as an allow-list, exclude removes items from the stub set, with tests covering both).

Also applies to: 273-285

🤖 Prompt for AI Agents
In packages/testing/src/testing.ts around lines 43-46 (and similarly update
lines 273-285), the stubActions type and shouldStubAction logic don't support
the documented { include, exclude } object shape; extend the stubActions union
type to also accept an object like { include?: string[]; exclude?: string[] }
and update shouldStubAction to handle that shape: if include is provided treat
it as an allow-list (only names in include may be stubbed), then apply exclude
to remove any names from that set; preserve existing boolean, string[] and
predicate behavior; add/adjust unit tests to cover include-only, exclude-only,
and combined include+exclude scenarios to ensure correct behavior.

@codecov
Copy link

codecov bot commented Nov 3, 2025

Codecov Report

❌ Patch coverage is 97.88732% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.63%. Comparing base (126e031) to head (d29f221).
⚠️ Report is 1 commits behind head on v3.

Files with missing lines Patch % Lines
packages/testing/src/testing.ts 82.35% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##               v3    #3040      +/-   ##
==========================================
+ Coverage   91.01%   91.63%   +0.62%     
==========================================
  Files          17       17              
  Lines        1402     1543     +141     
  Branches      211      227      +16     
==========================================
+ Hits         1276     1414     +138     
- Misses        125      127       +2     
- Partials        1        2       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@posva posva merged commit cff409e into vuejs:v3 Nov 3, 2025
9 checks passed
@github-project-automation github-project-automation bot moved this from 🧑‍💻 In progress to ✅ Done in Pinia Roadmap Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Allow stubbing specific actions only

2 participants