Skip to content

Commit 1c33f91

Browse files
authored
Merge pull request #40 from omfj/omfj/port-tests
Port tests from different signal implementations
2 parents 6240b44 + bc7a16b commit 1c33f91

File tree

4 files changed

+793
-1
lines changed

4 files changed

+793
-1
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@
4646
"volta": {
4747
"node": "22.0.0",
4848
"pnpm": "9.0.6"
49-
}
49+
},
50+
"packageManager": "pnpm@9.0.6"
5051
}

tests/Signal/ported/preact.test.ts

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {describe, it, expect, vi} from 'vitest';
2+
import {Signal} from '../../../src';
3+
4+
describe('Ported - Preact', () => {
5+
// https://github.com/preactjs/signals/blob/main/packages/core/test/signal.test.tsx#L1078
6+
it('should not leak errors raised by dependencies', () => {
7+
const a = new Signal.State(0);
8+
const b = new Signal.Computed(() => {
9+
a.get();
10+
throw new Error('error');
11+
});
12+
const c = new Signal.Computed(() => {
13+
try {
14+
b.get();
15+
} catch {
16+
return 'ok';
17+
}
18+
});
19+
expect(c.get()).to.equal('ok');
20+
a.set(1);
21+
expect(c.get()).to.equal('ok');
22+
});
23+
24+
// https://github.com/preactjs/signals/blob/main/packages/core/test/signal.test.tsx#L914
25+
it('should return updated value', () => {
26+
const a = new Signal.State('a');
27+
const b = new Signal.State('b');
28+
29+
const c = new Signal.Computed(() => a.get() + b.get());
30+
expect(c.get()).to.equal('ab');
31+
32+
a.set('aa');
33+
expect(c.get()).to.equal('aab');
34+
});
35+
36+
// https://github.com/preactjs/signals/blob/main/packages/core/test/signal.test.tsx#L925
37+
it('should be lazily computed on demand', () => {
38+
const a = new Signal.State('a');
39+
const b = new Signal.State('b');
40+
const spy = vi.fn(() => a.get() + b.get());
41+
const c = new Signal.Computed(spy);
42+
expect(spy).not.toHaveBeenCalled();
43+
c.get();
44+
expect(spy).toHaveBeenCalledOnce();
45+
a.set('x');
46+
b.set('y');
47+
expect(spy).toHaveBeenCalledOnce();
48+
c.get();
49+
expect(spy).toHaveBeenCalledTimes(2);
50+
});
51+
52+
// https://github.com/preactjs/signals/blob/main/packages/core/test/signal.test.tsx#L940
53+
it('should be computed only when a dependency has changed at some point', () => {
54+
const a = new Signal.State('a');
55+
const spy = vi.fn(() => {
56+
return a.get();
57+
});
58+
const c = new Signal.Computed(spy);
59+
c.get();
60+
expect(spy).toHaveBeenCalledOnce();
61+
a.set('a');
62+
c.get();
63+
expect(spy).toHaveBeenCalledOnce();
64+
});
65+
66+
// https://github.com/preactjs/signals/blob/main/packages/core/test/signal.test.tsx#L1693
67+
it('should support lazy branches', () => {
68+
const a = new Signal.State(0);
69+
const b = new Signal.Computed(() => a.get());
70+
const c = new Signal.Computed(() => (a.get() > 0 ? a.get() : b.get()));
71+
72+
expect(c.get()).to.equal(0);
73+
a.set(1);
74+
expect(c.get()).to.equal(1);
75+
76+
a.set(0);
77+
expect(c.get()).to.equal(0);
78+
});
79+
});

tests/Signal/ported/vue.test.ts

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {describe, it, expect, vi} from 'vitest';
2+
import {Signal} from '../../../src';
3+
4+
describe('Ported - Vue', () => {
5+
// https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts#L32
6+
it('should return updated value', () => {
7+
const s = new Signal.State<{foo?: number}>({});
8+
const c = new Signal.Computed(() => s.get().foo);
9+
10+
expect(c.get()).toBe(undefined);
11+
s.set({foo: 1});
12+
expect(c.get()).toBe(1);
13+
});
14+
15+
// https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts#L54
16+
it('should compute lazily', () => {
17+
const s = new Signal.State<{foo?: number}>({});
18+
const getter = vi.fn(() => s.get().foo);
19+
const c = new Signal.Computed(getter);
20+
21+
// lazy
22+
expect(getter).not.toHaveBeenCalled();
23+
24+
expect(c.get()).toBe(undefined);
25+
expect(getter).toHaveBeenCalledTimes(1);
26+
27+
// should not compute again
28+
c.get();
29+
expect(getter).toHaveBeenCalledTimes(1);
30+
31+
// should not compute until needed
32+
s.set({foo: 1});
33+
expect(getter).toHaveBeenCalledTimes(1);
34+
35+
// now it should compute
36+
expect(c.get()).toBe(1);
37+
expect(getter).toHaveBeenCalledTimes(2);
38+
39+
// should not compute again
40+
c.get();
41+
expect(getter).toHaveBeenCalledTimes(2);
42+
});
43+
44+
// https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts#L488
45+
it('should work when chained(ref+computed)', () => {
46+
const v = new Signal.State(0);
47+
const c1 = new Signal.Computed(() => {
48+
if (v.get() === 0) {
49+
v.set(1);
50+
}
51+
return 'foo';
52+
});
53+
const c2 = new Signal.Computed(() => v.get() + c1.get());
54+
expect(c2.get()).toBe('0foo');
55+
expect(c2.get()).toBe('0foo'); // ! In vue it recomputes and becomes '1foo'
56+
});
57+
58+
// https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts#L925
59+
it('should be recomputed without being affected by side effects', () => {
60+
const v = new Signal.State(0);
61+
const c1 = new Signal.Computed(() => {
62+
v.set(1);
63+
return 0;
64+
});
65+
const c2 = new Signal.Computed(() => {
66+
return v.get() + ',' + c1.get();
67+
});
68+
69+
expect(c2.get()).toBe('0,0');
70+
v.set(1);
71+
expect(c2.get()).toBe('0,0'); // ! In vue it recomputes and becomes '1,0'
72+
});
73+
});

0 commit comments

Comments
 (0)