]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
feat(testing): allow overriding computed in tests
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 31 Mar 2022 17:41:14 +0000 (19:41 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 31 Mar 2022 17:41:14 +0000 (19:41 +0200)
Close #945

packages/testing/src/testing.spec.ts
packages/testing/src/testing.ts

index d828ae6cebc4d85f48cd2aa3f0125f1f9b288bdf..b46ec82e659307ec68501a75c03868b0783d92bc 100644 (file)
@@ -199,4 +199,29 @@ describe('Testing', () => {
       b: { n: 0 },
     })
   })
+
+  it('allows overriding computed properties', () => {
+    const useStore = defineStore('lol', {
+      state: () => ({ n: 0 }),
+      getters: {
+        double: (state) => state.n * 2,
+      },
+    })
+    const pinia = createTestingPinia()
+    const store = useStore(pinia)
+
+    store.n++
+    expect(store.double).toBe(2)
+    // once the getter is overridden, it stays
+    store.double = 3
+    expect(store.double).toBe(3)
+    store.n++
+    expect(store.double).toBe(3)
+    // it can be set to undefined again to reset
+    // @ts-expect-error
+    store.double = undefined
+    expect(store.double).toBe(4)
+    store.n++
+    expect(store.double).toBe(6)
+  })
 })
index 0eb594cd2bcac56ce93ed4ebda866c8cc6954253..adc86d55900a46348a30eec8b254d5a672019585 100644 (file)
@@ -1,4 +1,14 @@
-import { App, createApp, isReactive, isRef, isVue2, set } from 'vue-demi'
+import {
+  App,
+  createApp,
+  customRef,
+  isReactive,
+  isRef,
+  isVue2,
+  set,
+  toRaw,
+} from 'vue-demi'
+import type { ComputedRef, WritableComputedRef } from 'vue-demi'
 import {
   Pinia,
   PiniaPlugin,
@@ -6,6 +16,7 @@ import {
   createPinia,
   StateTree,
   _DeepPartial,
+  PiniaPluginContext,
 } from 'pinia'
 
 export interface TestingOptions {
@@ -94,6 +105,9 @@ export function createTestingPinia({
     }
   })
 
+  // allow computed to be manually overridden
+  pinia._p.push(WritableComputed)
+
   plugins.forEach((plugin) => pinia.use(plugin))
 
   const createSpy =
@@ -175,3 +189,31 @@ function isPlainObject(
     typeof o.toJSON !== 'function'
   )
 }
+
+function isComputed<T>(
+  v: ComputedRef<T> | WritableComputedRef<T> | unknown
+): v is ComputedRef<T> | WritableComputedRef<T> {
+  return !!v && isRef(v) && 'effect' in v
+}
+
+function WritableComputed({ store }: PiniaPluginContext) {
+  const rawStore = toRaw(store)
+  for (const key in rawStore) {
+    const value = rawStore[key]
+    if (isComputed(value)) {
+      rawStore[key] = customRef((track, trigger) => {
+        let internalValue: any
+        return {
+          get: () => {
+            track()
+            return internalValue !== undefined ? internalValue : value.value
+          },
+          set: (newValue) => {
+            internalValue = newValue
+            trigger()
+          },
+        }
+      })
+    }
+  }
+}