Testing code without a render function

I was writing some utility functions using SolidJS primitives and ran into the issue that memos don't update. This is the minimal vitest where I could reproduce the issue:
test('memo', () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
expect(memo()).eq(true)
})
})
test('memo', () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
expect(memo()).eq(true)
})
})
Am I missing something?
7 Replies
Michael P. Jung
Michael P. JungOP3y ago
When copying the code straight from https://github.com/solidjs/solid/blob/main/packages/solid/test/signals.memo.spec.ts I end up with the tests failing as well.
GitHub
solid/signals.memo.spec.ts at main · solidjs/solid
A declarative, efficient, and flexible JavaScript library for building user interfaces. - solid/signals.memo.spec.ts at main · solidjs/solid
bigmistqke
bigmistqke3y ago
My guess is it's running on node, so it thinks it's on the server, so it's running in SSR-mode, and solid disables reactivity in SSR for performance reasons. U could import straight from solid-js/web
Michael P. Jung
Michael P. JungOP3y ago
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
Michael P. Jung
Michael P. JungOP3y ago
I created my own tick helper for that:
export function tick(f: () => void): Promise<undefined> {
return new Promise((resolve, reject) => {
try {
createEffect(f)
resolve(undefined)
} catch (e) {
reject(e)
}
})
}
export function tick(f: () => void): Promise<undefined> {
return new Promise((resolve, reject) => {
try {
createEffect(f)
resolve(undefined)
} catch (e) {
reject(e)
}
})
}
Now my test looks like that which is acceptable:
test('memo', async () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
await tick(() => {
expect(memo()).eq(true)
})
})
})
test('memo', async () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
await tick(() => {
expect(memo()).eq(true)
})
})
})
bigmistqke
bigmistqke3y ago
Aaaa yes yes I had the same issue the other day I used queueMicrotask then for it Have seen it in other test-codebases too
Michael P. Jung
Michael P. JungOP3y ago
Is there maybe a builtin method for that? Is there maybe even a better way? It feels like it should be part of solid to begin with. Oh, nice... queueMicrotask does the trick. I could get rid of the callback in the tick function:
export function tick(): Promise<undefined> {
return new Promise((resolve) => {
queueMicrotask(resolve as VoidFunction)
})
}
test('memo', async () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
await tick()
expect(memo()).eq(true)
})
})
export function tick(): Promise<undefined> {
return new Promise((resolve) => {
queueMicrotask(resolve as VoidFunction)
})
}
test('memo', async () => {
createRoot(() => {
const [signal, setSignal] = createSignal(false)
const memo = createMemo(() => signal())
expect(memo()).eq(false)
setSignal(true)
await tick()
expect(memo()).eq(true)
})
})
Alex Lohr
Alex Lohr3y ago
Maybe that's a worthwhile addition to @solidjs/testing-library. I like it.

Did you find this page helpful?