@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,43 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { createState, app, DIV } from "../index";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"createState(): throws when state is not an object": () => {
|
|
6
|
+
const err = expect(() => createState(null as any)).toFail();
|
|
7
|
+
expect(err.message)
|
|
8
|
+
.toEqual("createState() must be called with a state object");
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
"createState(): adds patch function to state": () => {
|
|
12
|
+
const state = createState({ x: 1 });
|
|
13
|
+
expect(typeof (state as any).patch).toEqual("function");
|
|
14
|
+
expect((state)).toEqual({ x: 1, patch: (state as any).patch });
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
"createState(): patch is non-enumerable": () => {
|
|
18
|
+
const state = createState({ x: 1 });
|
|
19
|
+
expect(Object.keys(state)).toEqual(["x"]);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"createState(): app picks up queued patches": () => {
|
|
23
|
+
const state: any = createState({ count: 0 });
|
|
24
|
+
state.patch({ count: 1 });
|
|
25
|
+
state.patch({ count: 2 });
|
|
26
|
+
const root = document.createElement("div");
|
|
27
|
+
const container = document.createElement("div");
|
|
28
|
+
root.appendChild(container);
|
|
29
|
+
app(container, state, () => [DIV]);
|
|
30
|
+
|
|
31
|
+
expect(state.count)
|
|
32
|
+
.toEqual(2);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"createState(): already-patchable state is kept as-is": () => {
|
|
36
|
+
const existingPatch = (action: any) => { };
|
|
37
|
+
const state: any = { value: 5, patch: existingPatch };
|
|
38
|
+
const result = createState(state);
|
|
39
|
+
|
|
40
|
+
expect(result.patch === existingPatch)
|
|
41
|
+
.toEqual(true);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { app, DIV, defuse } from "../index";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"defuse(): on a container without _vode is a no-op": () => {
|
|
6
|
+
const container = document.createElement("div");
|
|
7
|
+
|
|
8
|
+
expect(() => defuse(container as any))
|
|
9
|
+
.toSucceed();
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
"defuse(): removes _vode from container": () => {
|
|
13
|
+
const root = document.createElement("div");
|
|
14
|
+
const container = document.createElement("div");
|
|
15
|
+
root.appendChild(container);
|
|
16
|
+
app(container, {}, () => [DIV]);
|
|
17
|
+
expect(typeof (container as any)._vode).toEqual("object");
|
|
18
|
+
defuse(container as any);
|
|
19
|
+
|
|
20
|
+
expect((container as any)._vode)
|
|
21
|
+
.toEqual(undefined);
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
"defuse(): removes patch function from state": () => {
|
|
25
|
+
const root = document.createElement("div");
|
|
26
|
+
const container = document.createElement("div");
|
|
27
|
+
root.appendChild(container);
|
|
28
|
+
const state: any = {};
|
|
29
|
+
app(container, state, () => [DIV]);
|
|
30
|
+
expect(typeof state.patch).toEqual("function");
|
|
31
|
+
defuse(container as any);
|
|
32
|
+
|
|
33
|
+
expect(state.patch)
|
|
34
|
+
.toEqual(undefined);
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
"defuse(): disables renderSync and renderAsync": () => {
|
|
38
|
+
const root = document.createElement("div");
|
|
39
|
+
const container = document.createElement("div");
|
|
40
|
+
root.appendChild(container);
|
|
41
|
+
app(container, {}, () => [DIV]);
|
|
42
|
+
defuse(container as any);
|
|
43
|
+
|
|
44
|
+
expect((container as any)._vode)
|
|
45
|
+
.toEqual(undefined);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
"defuse(): clears event listeners from rendered elements": () => {
|
|
49
|
+
const root = document.createElement("div");
|
|
50
|
+
const container = document.createElement("div");
|
|
51
|
+
root.appendChild(container);
|
|
52
|
+
app(container, {}, () => [DIV, { onclick: () => ({}) }] as any);
|
|
53
|
+
const node = (container as any)._vode.vode.node;
|
|
54
|
+
expect(typeof node.onclick).toEqual("function");
|
|
55
|
+
defuse(container as any);
|
|
56
|
+
|
|
57
|
+
expect(node.onclick)
|
|
58
|
+
.toEqual(null);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
"defuse(): recurses into child containers": () => {
|
|
62
|
+
const root = document.createElement("div");
|
|
63
|
+
const outer = document.createElement("div");
|
|
64
|
+
const inner = document.createElement("div");
|
|
65
|
+
root.appendChild(outer);
|
|
66
|
+
outer.appendChild(inner);
|
|
67
|
+
const state: any = {};
|
|
68
|
+
app(inner, state, () => [DIV]);
|
|
69
|
+
defuse(outer as any);
|
|
70
|
+
|
|
71
|
+
expect(state.patch)
|
|
72
|
+
.toEqual(undefined);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { hydrate, DIV, SPAN, P } from "../index";
|
|
3
|
+
import { MockElement, MockText } from "./mocks";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
"hydrate(): text node returns its text content": () => {
|
|
7
|
+
const text = new MockText("hello world");
|
|
8
|
+
|
|
9
|
+
expect(hydrate(text as any))
|
|
10
|
+
.toMatch("hello world");
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
"hydrate(): empty element returns a vode": () => {
|
|
14
|
+
const el = new MockElement("div");
|
|
15
|
+
const result = hydrate(el as any);
|
|
16
|
+
|
|
17
|
+
expect(result)
|
|
18
|
+
.toMatch([DIV]);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
"hydrate(): element with children returns full vode tree": () => {
|
|
22
|
+
const parent = new MockElement("div");
|
|
23
|
+
const child = new MockElement("span");
|
|
24
|
+
parent.appendChild(child);
|
|
25
|
+
|
|
26
|
+
expect(hydrate(parent as any))
|
|
27
|
+
.toMatch([DIV, [SPAN]]);
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"hydrate(): element with text child": () => {
|
|
31
|
+
const parent = new MockElement("p");
|
|
32
|
+
const text = new MockText("hello");
|
|
33
|
+
parent.appendChild(text);
|
|
34
|
+
|
|
35
|
+
expect(hydrate(parent as any))
|
|
36
|
+
.toMatch([P, "hello"]);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
"hydrate(): element with attributes reads them into props": () => {
|
|
40
|
+
const el = new MockElement("div");
|
|
41
|
+
el.setAttribute("class", "foo");
|
|
42
|
+
el.setAttribute("id", "bar");
|
|
43
|
+
|
|
44
|
+
expect(hydrate(el as any))
|
|
45
|
+
.toMatch([DIV, { class: "foo", id: "bar" }]);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
"hydrate(): unknown node type returns undefined": () => {
|
|
49
|
+
const frag = { nodeType: 999 } as any;
|
|
50
|
+
|
|
51
|
+
expect(hydrate(frag))
|
|
52
|
+
.toEqual(undefined);
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
"hydrate(): empty text node returns undefined": () => {
|
|
56
|
+
const text = new MockText(" ");
|
|
57
|
+
|
|
58
|
+
expect(hydrate(text as any))
|
|
59
|
+
.toEqual(undefined);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
"hydrate(): only element and text nodes are supported": () => {
|
|
63
|
+
const comment = { nodeType: Node.COMMENT_NODE } as any;
|
|
64
|
+
|
|
65
|
+
expect(hydrate(comment))
|
|
66
|
+
.toEqual(undefined);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { memo, DIV, app, createState, SPAN } from "../index";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"memo(): returns the given function": () => {
|
|
6
|
+
const fn = (s: any) => [DIV];
|
|
7
|
+
const result = memo([1, 2], fn);
|
|
8
|
+
expect(result === fn).toEqual(true);
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
"memo(): throws when compare is not an array": () => {
|
|
12
|
+
const err = expect(() => memo(null as any, (s: any) => [DIV]))
|
|
13
|
+
.toFail();
|
|
14
|
+
expect(err.message)
|
|
15
|
+
.toEqual("first argument to memo() must be an array of values to compare");
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"memo(): throws when componentOrProps is not a function": () => {
|
|
19
|
+
const err = expect(() => memo([1], null as any))
|
|
20
|
+
.toFail();
|
|
21
|
+
expect(err.message)
|
|
22
|
+
.toEqual("second argument to memo() must be a function that returns a vode or props object");
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
"memo(): integration with app prevents re-render when deps match": () => {
|
|
26
|
+
const state = createState({ count: 12 });
|
|
27
|
+
const root = document.createElement("div");
|
|
28
|
+
const container = document.createElement("div");
|
|
29
|
+
root.appendChild(container);
|
|
30
|
+
|
|
31
|
+
let callCount = 0;
|
|
32
|
+
app<typeof state>(container, state, (s) => [DIV, memo(
|
|
33
|
+
[s.count],
|
|
34
|
+
(s) => {
|
|
35
|
+
callCount++;
|
|
36
|
+
return [DIV, [SPAN, `${s.count}`]];
|
|
37
|
+
}
|
|
38
|
+
)]);
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
expect(callCount).toEqual(1);
|
|
42
|
+
|
|
43
|
+
state.patch({ count: 12 }); //same value, should not re-render
|
|
44
|
+
expect(callCount).toEqual(1);
|
|
45
|
+
state.patch({ count: 13 }); //different value, should re-render
|
|
46
|
+
expect(callCount).toEqual(2);
|
|
47
|
+
expect(container).toMatch(
|
|
48
|
+
[DIV,
|
|
49
|
+
[DIV,
|
|
50
|
+
[SPAN, "13"]
|
|
51
|
+
]
|
|
52
|
+
]
|
|
53
|
+
);
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
"memo(): works also with props factory": () => {
|
|
57
|
+
const state = createState({ count: 12, prefix: "Count is: " });
|
|
58
|
+
const root = document.createElement("div");
|
|
59
|
+
const container = document.createElement("div");
|
|
60
|
+
root.appendChild(container);
|
|
61
|
+
|
|
62
|
+
let callCount = 0;
|
|
63
|
+
app<typeof state>(container, state, (s) => [DIV,
|
|
64
|
+
[DIV,
|
|
65
|
+
memo(
|
|
66
|
+
[s.count],
|
|
67
|
+
(s) => {
|
|
68
|
+
callCount++;
|
|
69
|
+
return {
|
|
70
|
+
class: {
|
|
71
|
+
low: s.count < 10,
|
|
72
|
+
high: s.count >= 10,
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
[SPAN, `${s.prefix}${s.count}`]
|
|
78
|
+
],
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
expect(callCount).toEqual(1);
|
|
83
|
+
state.patch({ count: 12 });
|
|
84
|
+
expect(callCount).toEqual(1); // unchanged count should not cause re-render
|
|
85
|
+
state.patch({ count: 13 });
|
|
86
|
+
expect(callCount).toEqual(2);
|
|
87
|
+
state.patch({ prefix: "count: " });
|
|
88
|
+
expect(callCount).toEqual(3);
|
|
89
|
+
expect(container).toMatch(
|
|
90
|
+
[DIV,
|
|
91
|
+
[DIV, { class: { low: false, high: true } },
|
|
92
|
+
[SPAN, "count: 13"]
|
|
93
|
+
]
|
|
94
|
+
]
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
"memo(): can be a nested component function": () => {
|
|
99
|
+
const state = createState({ count: 12 });
|
|
100
|
+
const root = document.createElement("div");
|
|
101
|
+
const container = document.createElement("div");
|
|
102
|
+
root.appendChild(container);
|
|
103
|
+
|
|
104
|
+
let callCount = 0;
|
|
105
|
+
app<typeof state>(container, state, (s) => [DIV,
|
|
106
|
+
() => memo(
|
|
107
|
+
[s.count],
|
|
108
|
+
(s) => {
|
|
109
|
+
callCount++;
|
|
110
|
+
return [DIV, [SPAN, `${s.count}`]];
|
|
111
|
+
}
|
|
112
|
+
)]);
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
expect(callCount).toEqual(1);
|
|
116
|
+
state.patch({ count: 12 }); //same value, should not re-render
|
|
117
|
+
expect(callCount).toEqual(1);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mergeClass } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"mergeClass(): no args returns null": () => {
|
|
6
|
+
expect(mergeClass()).toEqual(null);
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
"mergeClass(): single string returns it": () => {
|
|
10
|
+
expect(mergeClass("foo")).toEqual("foo");
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
"mergeClass(): two strings are joined and deduplicated": () => {
|
|
14
|
+
expect(mergeClass("foo", "bar")).toEqual("foo bar");
|
|
15
|
+
expect(mergeClass("foo bar", "bar baz")).toEqual("foo bar baz");
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"mergeClass(): string and array": () => {
|
|
19
|
+
expect(mergeClass("foo", ["bar", "baz"])).toEqual("bar baz foo");
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"mergeClass(): array and string": () => {
|
|
23
|
+
expect(mergeClass(["foo", "bar"], "baz")).toEqual("foo bar baz");
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"mergeClass(): two arrays": () => {
|
|
27
|
+
expect(mergeClass(["foo", "bar"], ["baz", "qux"])).toEqual("foo bar baz qux");
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"mergeClass(): two string arrays with duplicates": () => {
|
|
31
|
+
expect(mergeClass(["foo", "bar"], ["bar", "baz"])).toEqual("foo bar baz");
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
"mergeClass(): string and object": () => {
|
|
35
|
+
expect(mergeClass("foo", { bar: true, baz: false })).toEqual({ foo: true, bar: true, baz: false });
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
"mergeClass(): object and string": () => {
|
|
39
|
+
expect(mergeClass({ foo: true, bar: false }, "baz")).toEqual({ foo: true, bar: false, baz: true });
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
"mergeClass(): two objects": () => {
|
|
43
|
+
expect(mergeClass({ foo: true, bar: true }, { bar: false, baz: true })).toEqual({ foo: true, bar: false, baz: true });
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
"mergeClass(): object and array": () => {
|
|
47
|
+
expect(mergeClass({ foo: true }, ["bar", "baz"])).toEqual({ foo: true, 0: "bar", 1: "baz" });
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
"mergeClass(): array and object": () => {
|
|
51
|
+
expect(mergeClass(["foo", "bar"], { baz: true, qux: false })).toEqual({ 0: "foo", 1: "bar", baz: true, qux: false });
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
"mergeClass(): falsy entries are skipped": () => {
|
|
55
|
+
expect(mergeClass("foo", null, "bar")).toEqual("foo bar");
|
|
56
|
+
expect(mergeClass(null, "foo", undefined, "bar")).toEqual("foo bar");
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
"mergeClass(): multiple args (3+)": () => {
|
|
60
|
+
expect(mergeClass("a", "b", "c")).toEqual("a b c");
|
|
61
|
+
expect(mergeClass("x", null, ["y", "z"], "w")).toEqual("y z x w");
|
|
62
|
+
}
|
|
63
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mergeProps, Props } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"mergeProps(): no args returns undefined": () => {
|
|
6
|
+
expect(mergeProps()).toEqual(undefined);
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
"mergeProps(): single arg returned as-is": () => {
|
|
10
|
+
const p = { class: "foo" };
|
|
11
|
+
expect(mergeProps(p) === p).toEqual(true);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"mergeProps(): two plain objects merged": () => {
|
|
15
|
+
expect(mergeProps({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"mergeProps(): right overwrites left for simple keys": () => {
|
|
19
|
+
expect(mergeProps({ a: 1, b: "x" }, { b: 2 })).toEqual({ a: 1, b: 2 });
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"mergeProps(): class merged via mergeClass": () => {
|
|
23
|
+
expect(mergeProps({ class: "foo" }, { class: "bar" })).toEqual({ class: "foo bar" });
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"mergeProps(): style merged via mergeStyle (strings)": () => {
|
|
27
|
+
const result = mergeProps({ style: "color: red" }, { style: "font-size: 14px" }) as Props;
|
|
28
|
+
expect((<string>result.style!).includes("color: red")).toEqual(true);
|
|
29
|
+
expect((<string>result.style!).includes("font-size: 14px")).toEqual(true);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
"mergeProps(): null and undefined entries skipped": () => {
|
|
33
|
+
expect(mergeProps({ a: 1 }, null, { b: 2 }, undefined)).toEqual({ a: 1, b: 2 });
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
"mergeProps(): multiple args (3+)": () => {
|
|
37
|
+
expect(mergeProps({ a: 1 }, { b: 2 }, { c: 3 })).toEqual({ a: 1, b: 2, c: 3 });
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"mergeProps(): first arg null returns defined from later args": () => {
|
|
41
|
+
expect(mergeProps(null, { a: 1 })).toEqual({ a: 1 });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { mergeStyle } from "../index";
|
|
2
|
+
import { expect } from "./helper";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
"mergeStyle(): no args returns empty string": () => {
|
|
6
|
+
expect(mergeStyle()).toEqual("");
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
"mergeStyle(): object style sets properties, returns cssText": () => {
|
|
10
|
+
const result = mergeStyle({ color: "red", fontSize: "14px" });
|
|
11
|
+
expect(typeof result).toEqual("string");
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"mergeStyle(): single string starts with semicolon": () => {
|
|
15
|
+
expect(mergeStyle("color: red")).toEqual(";color: red");
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"mergeStyle(): two strings are concatenated": () => {
|
|
19
|
+
expect(mergeStyle("color: red", "font-size: 14px")).toEqual(";color: red;font-size: 14px");
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"mergeStyle(): object then string": () => {
|
|
23
|
+
const result = mergeStyle({ color: "red" }, "font-size: 14px") as string;
|
|
24
|
+
expect(result.indexOf("font-size: 14px") > 0).toEqual(true);
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
"mergeStyle(): null and undefined entries are skipped": () => {
|
|
28
|
+
expect(mergeStyle(null, "color: red", undefined)).toEqual(";color: red");
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
"mergeStyle(): multiple objects and strings alternate": () => {
|
|
32
|
+
const result = mergeStyle(
|
|
33
|
+
{ color: "red" },
|
|
34
|
+
"font-size: 14px",
|
|
35
|
+
{ background: "blue" }
|
|
36
|
+
) as string;
|
|
37
|
+
expect(result.includes("font-size: 14px")).toEqual(true);
|
|
38
|
+
}
|
|
39
|
+
};
|