@ryupold/vode 1.8.4 → 1.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +13 -0
- package/.github/workflows/tests.yml +17 -0
- package/README.md +55 -5
- package/dist/vode.cjs.min.js +2 -2
- package/dist/vode.d.ts +5 -0
- package/dist/vode.es5.min.js +4 -4
- package/dist/vode.js +100 -20
- package/dist/vode.min.js +1 -1
- package/dist/vode.min.mjs +1 -1
- package/dist/vode.mjs +100 -20
- package/package.json +4 -3
- package/src/merge-style.ts +4 -1
- package/src/vode.ts +110 -26
- package/test/helper.ts +168 -0
- package/test/index.ts +82 -0
- package/test/mocks.ts +111 -0
- package/test/tests-app.ts +226 -0
- package/test/tests-children.ts +69 -0
- package/test/tests-createPatch.ts +28 -0
- package/test/tests-createState.ts +43 -0
- package/test/tests-defuse.ts +74 -0
- package/test/tests-hydrate.ts +68 -0
- package/test/tests-memo.ts +119 -0
- package/test/tests-mergeClass.ts +63 -0
- package/test/tests-mergeProps.ts +43 -0
- package/test/tests-mergeStyle.ts +39 -0
- package/test/tests-mount-unmount.ts +1140 -0
- package/test/tests-props.ts +34 -0
- package/test/tests-state-context.ts +106 -0
- package/test/tests-tag.ts +33 -0
- package/test/tests-vode.ts +27 -0
- package/tsconfig.test.json +18 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { props, DIV, SPAN } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"props(): on vode with props returns props object": () => {
|
|
6
|
+
expect(props([DIV, { class: "foo" }, "hello"]))
|
|
7
|
+
.toEqual({ class: "foo" });
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
"props(): on just-tag vode returns undefined": () => {
|
|
11
|
+
expect(props([DIV])).toEqual(undefined);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"props(): on text vode returns undefined": () => {
|
|
15
|
+
expect(props("hello")).toEqual(undefined);
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"props(): on vode where second element is an array (child) returns undefined": () => {
|
|
19
|
+
expect(props([DIV, [SPAN]] as any)).toEqual(undefined);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"props(): on vode where second element is null returns undefined": () => {
|
|
23
|
+
expect(props([DIV, null as any, "hi"])).toEqual(undefined);
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"props(): on falsy input returns undefined": () => {
|
|
27
|
+
expect(props(null as any)).toEqual(undefined);
|
|
28
|
+
expect(props(undefined as any)).toEqual(undefined);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
"props(): on vode with length 1 returns undefined": () => {
|
|
32
|
+
expect(props([DIV] as any)).toEqual(undefined);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { context } from "../src/state-context";
|
|
3
|
+
import { createState } from "../src/vode";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
"StateContext.state: returns the state reference": () => {
|
|
7
|
+
const state = createState({ x: 10 });
|
|
8
|
+
const ctx = context(state);
|
|
9
|
+
|
|
10
|
+
expect((ctx).state === state)
|
|
11
|
+
.toEqual(true);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"StateContext.get() returns whole state": () => {
|
|
15
|
+
const state = createState({ a: 1, b: 2 });
|
|
16
|
+
const ctx = context(state);
|
|
17
|
+
|
|
18
|
+
expect(ctx.get())
|
|
19
|
+
.toEqual({ a: 1, b: 2 });
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
"StateContext.get(): deep nested": () => {
|
|
24
|
+
const state = createState({ a: { b: { c: 42 } } });
|
|
25
|
+
const ctx = context(state);
|
|
26
|
+
|
|
27
|
+
expect(ctx.a.b.c.get())
|
|
28
|
+
.toEqual(42);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
"StateContext.get(): missing nested path returns undefined": () => {
|
|
32
|
+
const state = createState({ a: {} });
|
|
33
|
+
const ctx = context(state);
|
|
34
|
+
|
|
35
|
+
expect((ctx.a as any).b.get())
|
|
36
|
+
.toEqual(undefined);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
"StateContext.put(): silently mutates state": () => {
|
|
40
|
+
const state = createState({ a: { b: 1 } });
|
|
41
|
+
const ctx = context(state);
|
|
42
|
+
ctx.a.b.put(2);
|
|
43
|
+
|
|
44
|
+
expect(state.a.b)
|
|
45
|
+
.toEqual(2);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
"StateContext.put() on nested object replaces the sub-object": () => {
|
|
49
|
+
const state = createState({ a: { b: { x: 1, y: 2 } } });
|
|
50
|
+
const ctx = context(state);
|
|
51
|
+
ctx.a.b.put({ y: 99 });
|
|
52
|
+
|
|
53
|
+
expect(state.a.b)
|
|
54
|
+
.toEqual({ y: 99 });
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
"StateContext.put() at root level with empty keys": () => {
|
|
58
|
+
const state = createState({ a: 1, b: 2 });
|
|
59
|
+
const ctx = context(state);
|
|
60
|
+
ctx.put({ b: undefined });
|
|
61
|
+
|
|
62
|
+
expect(state)
|
|
63
|
+
.toEqual({ a: 1 });
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
"StateContext.patch(): calls state.patch with proper deep partial": () => {
|
|
67
|
+
const state = createState({ a: { b: 1 } });
|
|
68
|
+
const ctx = context(state);
|
|
69
|
+
ctx.a.b.patch(2);
|
|
70
|
+
|
|
71
|
+
const patches = (state as any).patch.initialPatches;
|
|
72
|
+
|
|
73
|
+
expect(patches.length)
|
|
74
|
+
.toEqual(1);
|
|
75
|
+
expect(patches[0])
|
|
76
|
+
.toEqual({ a: { b: 2 } });
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
"StateContext.patch(): async wraps in array": () => {
|
|
80
|
+
const state = createState({ a: { b: 1 } });
|
|
81
|
+
const ctx = context(state);
|
|
82
|
+
ctx.a.b.patch(2, true);
|
|
83
|
+
|
|
84
|
+
const patches = (state as any).patch.initialPatches;
|
|
85
|
+
|
|
86
|
+
expect(patches.length)
|
|
87
|
+
.toEqual(1);
|
|
88
|
+
expect(Array.isArray(patches[0]))
|
|
89
|
+
.toEqual(true);
|
|
90
|
+
expect(patches[0][0])
|
|
91
|
+
.toEqual({ a: { b: 2 } });
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
"StateContext.patch() on nested deep path three levels": () => {
|
|
95
|
+
const state = createState({ x: { y: { z: 0 } } });
|
|
96
|
+
const ctx = context(state);
|
|
97
|
+
ctx.x.y.z.patch(100);
|
|
98
|
+
|
|
99
|
+
const patches = (state as any).patch.initialPatches;
|
|
100
|
+
|
|
101
|
+
expect(patches.length)
|
|
102
|
+
.toEqual(1);
|
|
103
|
+
expect(patches[0])
|
|
104
|
+
.toEqual({ x: { y: { z: 100 } } });
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { tag, DIV, SPAN } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"tag(): on a vode returns the tag name": () => {
|
|
6
|
+
expect(tag([DIV]))
|
|
7
|
+
.toEqual("div");
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
"tag(): on a vode with props and children": () => {
|
|
11
|
+
expect(tag([DIV, { class: "foo" }, [SPAN, "hi"]]))
|
|
12
|
+
.toEqual("div");
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"tag(): on a text vode (string) returns #text": () => {
|
|
16
|
+
expect(tag("hello"))
|
|
17
|
+
.toEqual("#text");
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
"tag(): on falsy values returns undefined": () => {
|
|
21
|
+
expect(tag(null)).toEqual(undefined);
|
|
22
|
+
expect(tag(undefined)).toEqual(undefined);
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
"tag(): on no-vode values returns undefined": () => {
|
|
26
|
+
expect(tag(0)).toEqual(undefined);
|
|
27
|
+
expect(tag(true)).toEqual(undefined);
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"tag(): on empty array returns undefined": () => {
|
|
31
|
+
expect(tag([])).toEqual(undefined);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { vode, DIV, Vode, SPAN, STRONG } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"vode(): passing an already constructed vode returns it": () => {
|
|
6
|
+
const testVode: Vode = [DIV, { class: 'test' }, "hello world"];
|
|
7
|
+
|
|
8
|
+
expect(vode(testVode)).toEqual(testVode);
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
"vode(): constructing a vode from parts": () => {
|
|
12
|
+
expect(
|
|
13
|
+
vode(DIV, { class: 'test' },
|
|
14
|
+
[SPAN, "hello"],
|
|
15
|
+
[STRONG, { style: 'color: green' }, "world"])
|
|
16
|
+
).toEqual(
|
|
17
|
+
[DIV, { class: 'test' },
|
|
18
|
+
[SPAN, "hello"],
|
|
19
|
+
[STRONG, { style: 'color: green' }, "world"]]
|
|
20
|
+
);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
"vode(): passing an invalid tag fails": () => {
|
|
24
|
+
const err = expect(() => vode(null as any)).toFail();
|
|
25
|
+
expect(err.message).toEqual("first argument to vode() must be a tag name or a vode");
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "test/",
|
|
5
|
+
"declaration": false,
|
|
6
|
+
"declarationMap": false,
|
|
7
|
+
"sourceMap": false,
|
|
8
|
+
"declarationDir": null,
|
|
9
|
+
"composite": false,
|
|
10
|
+
"noEmit": true
|
|
11
|
+
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"index.ts",
|
|
15
|
+
"src/**/*",
|
|
16
|
+
"test/**/*"
|
|
17
|
+
]
|
|
18
|
+
}
|