Skip to content

Commit b332226

Browse files
committed
Add ConditionStore
1 parent 23a5643 commit b332226

File tree

3 files changed

+121
-4
lines changed

3 files changed

+121
-4
lines changed

src/ConditionStore.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,40 @@
1-
export default ConditionStore {}
1+
export type UnsubscribeFunction = () => void;
2+
3+
export default class ConditionStore {
4+
value: boolean;
5+
listeners: Array<() => void> = [];
6+
7+
constructor(initialValue?: boolean) {
8+
this.value = Boolean(initialValue);
9+
}
10+
11+
set() {
12+
if(this.value !== true) {
13+
this.value = true;
14+
this.notify();
15+
}
16+
}
17+
18+
clear() {
19+
if(this.value !== false) {
20+
this.value = false;
21+
this.notify();
22+
}
23+
}
24+
25+
getSnapshot() {
26+
return this.value;
27+
}
28+
29+
subscribe(listener: () => void): UnsubscribeFunction {
30+
this.listeners = [...this.listeners, listener];
31+
32+
return () => {
33+
this.listeners = this.listeners.filter(l => l !== listener);
34+
}
35+
}
36+
37+
private notify() {
38+
this.listeners.forEach(listener => listener());
39+
}
40+
}
Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,82 @@
1+
import ConditionStore from "ConditionStore";
2+
13
describe('#ConditionStore', () => {
2-
it('xxx', () => {
3-
});
4+
it('stores initial values', () => {
5+
const store1 = new ConditionStore(false);
6+
expect(store1.getSnapshot()).toBe(false);
7+
8+
const store2 = new ConditionStore(true);
9+
expect(store2.getSnapshot()).toBe(true);
410
});
11+
12+
it('updates value on `set`', () => {
13+
const store = new ConditionStore(false);
14+
store.set();
15+
expect(store.getSnapshot()).toBe(true);
16+
});
17+
18+
it('updates value on `clear`', () => {
19+
const store = new ConditionStore(true);
20+
store.clear();
21+
expect(store.getSnapshot()).toBe(false);
22+
});
23+
24+
it('notifies listeners on `set` or `clear`', () => {
25+
const listener = jest.fn();
26+
27+
const store = new ConditionStore(false);
28+
store.subscribe(listener);
29+
expect(listener.mock.calls.length).toBe(0);
30+
31+
store.set();
32+
expect(listener.mock.calls.length).toBe(1);
33+
34+
store.clear();
35+
expect(listener.mock.calls.length).toBe(2);
36+
});
37+
38+
it('does not notify listeners that have been unsubscribed', () => {
39+
const listener1 = jest.fn();
40+
const listener2 = jest.fn();
41+
42+
const store = new ConditionStore(false);
43+
const unsubscribeListener1 = store.subscribe(listener1);
44+
const unsubscribeListener2 = store.subscribe(listener2);
45+
expect(listener1.mock.calls.length).toBe(0);
46+
expect(listener2.mock.calls.length).toBe(0);
47+
48+
store.set();
49+
expect(listener1.mock.calls.length).toBe(1);
50+
expect(listener2.mock.calls.length).toBe(1);
51+
52+
unsubscribeListener2();
53+
54+
store.clear();
55+
expect(listener1.mock.calls.length).toBe(2);
56+
expect(listener2.mock.calls.length).toBe(1);
57+
58+
unsubscribeListener1();
59+
60+
store.set();
61+
expect(listener1.mock.calls.length).toBe(2);
62+
expect(listener2.mock.calls.length).toBe(1);
63+
});
64+
65+
it('notifies listeners on `set` or `clear` only if value changes', () => {
66+
const listener = jest.fn();
67+
68+
const store = new ConditionStore(false);
69+
store.subscribe(listener);
70+
expect(listener.mock.calls.length).toBe(0);
71+
72+
store.set();
73+
expect(listener.mock.calls.length).toBe(1);
74+
store.set();
75+
expect(listener.mock.calls.length).toBe(1);
76+
77+
store.clear();
78+
expect(listener.mock.calls.length).toBe(2);
79+
store.clear();
80+
expect(listener.mock.calls.length).toBe(2);
81+
});
82+
});

src/__tests__/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
// import { PropsWithChildren } from 'react';
44

55
describe('#react-conditional-fallback', () => {
6-
it('xxx', async () => {
6+
xit('xxx', async () => {
77
});
88
});

0 commit comments

Comments
 (0)