Skip to content

Commit f4db826

Browse files
committed
feat(testing): allow overriding computed in tests
Close #945
1 parent 9b7a472 commit f4db826

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

packages/testing/src/testing.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,29 @@ describe('Testing', () => {
199199
b: { n: 0 },
200200
})
201201
})
202+
203+
it('allows overriding computed properties', () => {
204+
const useStore = defineStore('lol', {
205+
state: () => ({ n: 0 }),
206+
getters: {
207+
double: (state) => state.n * 2,
208+
},
209+
})
210+
const pinia = createTestingPinia()
211+
const store = useStore(pinia)
212+
213+
store.n++
214+
expect(store.double).toBe(2)
215+
// once the getter is overridden, it stays
216+
store.double = 3
217+
expect(store.double).toBe(3)
218+
store.n++
219+
expect(store.double).toBe(3)
220+
// it can be set to undefined again to reset
221+
// @ts-expect-error
222+
store.double = undefined
223+
expect(store.double).toBe(4)
224+
store.n++
225+
expect(store.double).toBe(6)
226+
})
202227
})

packages/testing/src/testing.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
1-
import { App, createApp, isReactive, isRef, isVue2, set } from 'vue-demi'
1+
import {
2+
App,
3+
createApp,
4+
customRef,
5+
isReactive,
6+
isRef,
7+
isVue2,
8+
set,
9+
toRaw,
10+
} from 'vue-demi'
11+
import type { ComputedRef, WritableComputedRef } from 'vue-demi'
212
import {
313
Pinia,
414
PiniaPlugin,
515
setActivePinia,
616
createPinia,
717
StateTree,
818
_DeepPartial,
19+
PiniaPluginContext,
920
} from 'pinia'
1021

1122
export interface TestingOptions {
@@ -94,6 +105,9 @@ export function createTestingPinia({
94105
}
95106
})
96107

108+
// allow computed to be manually overridden
109+
pinia._p.push(WritableComputed)
110+
97111
plugins.forEach((plugin) => pinia.use(plugin))
98112

99113
const createSpy =
@@ -175,3 +189,31 @@ function isPlainObject(
175189
typeof o.toJSON !== 'function'
176190
)
177191
}
192+
193+
function isComputed<T>(
194+
v: ComputedRef<T> | WritableComputedRef<T> | unknown
195+
): v is ComputedRef<T> | WritableComputedRef<T> {
196+
return !!v && isRef(v) && 'effect' in v
197+
}
198+
199+
function WritableComputed({ store }: PiniaPluginContext) {
200+
const rawStore = toRaw(store)
201+
for (const key in rawStore) {
202+
const value = rawStore[key]
203+
if (isComputed(value)) {
204+
rawStore[key] = customRef((track, trigger) => {
205+
let internalValue: any
206+
return {
207+
get: () => {
208+
track()
209+
return internalValue !== undefined ? internalValue : value.value
210+
},
211+
set: (newValue) => {
212+
internalValue = newValue
213+
trigger()
214+
},
215+
}
216+
})
217+
}
218+
}
219+
}

0 commit comments

Comments
 (0)