@excom/neutron 0.1.0
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/.rush/temp/chunked-rush-logs/neutron.apply-exports.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/neutron.build_package-metas.chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/all.log +1 -0
- package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/state.json +3 -0
- package/.rush/temp/operation/build_package-metas/all.log +1 -0
- package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_package-metas/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +3 -0
- package/config/rig.json +6 -0
- package/index.ts +9 -0
- package/package.json +45 -0
- package/rush-logs/neutron.apply-exports.cache.log +1 -0
- package/rush-logs/neutron.apply-exports.log +1 -0
- package/rush-logs/neutron.build_package-metas.cache.log +1 -0
- package/rush-logs/neutron.build_package-metas.log +1 -0
- package/src/command.ts +102 -0
- package/src/common-element.ts +377 -0
- package/src/constants.ts +101 -0
- package/src/devtools-hook.ts +93 -0
- package/src/lifecycle-configs.ts +304 -0
- package/src/neutron-element.ts +72 -0
- package/src/neutron-error.ts +6 -0
- package/src/neutron-internal.ts +550 -0
- package/src/neutron.ts +36 -0
- package/src/types/effect.types.ts +104 -0
- package/src/types/element.types.ts +263 -0
- package/src/types/index.ts +4 -0
- package/src/types/new.types.ts +159 -0
- package/src/types/shared.types.ts +25 -0
- package/src/utils/effect.ts +357 -0
- package/src/utils/element.ts +382 -0
- package/src/utils/index.ts +2 -0
- package/support/docs/COMMANDS.md +58 -0
- package/support/docs/COMPOSE.md +32 -0
- package/support/docs/DEBUG.md +11 -0
- package/support/docs/DEFINE.md +20 -0
- package/support/docs/EFFECTS.md +49 -0
- package/support/docs/EVENTS.md +57 -0
- package/support/docs/LIFECYCLES.md +69 -0
- package/support/docs/METHODS.md +49 -0
- package/support/docs/PROMISE_PROPS.md +29 -0
- package/support/docs/PROPS.md +64 -0
- package/support/docs/PROP_REACTIONS.md +35 -0
- package/support/docs/PROVISION.md +31 -0
- package/support/docs/README.md +118 -0
- package/support/docs/RECOMPOSE.md +70 -0
- package/support/docs/TYPESCRIPT.md +51 -0
- package/support/docs-sections.json +42 -0
- package/support/package-meta.json +129 -0
- package/support/tests/commands.test.ts +330 -0
- package/support/tests/common-element.test.ts +342 -0
- package/support/tests/devtools-hook.test.ts +209 -0
- package/support/tests/devtools-renderer.test.ts +125 -0
- package/support/tests/effects.test.ts +253 -0
- package/support/tests/element-config.test.ts +331 -0
- package/support/tests/entry.test.ts +68 -0
- package/support/tests/lifecycles.test.ts +489 -0
- package/support/tests/loop-guard.test.ts +162 -0
- package/support/tests/neutron.test.ts +1286 -0
- package/support/tests/recompose.test.ts +129 -0
- package/support/tests/utils.test.ts +75 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Neutron } from "../../src/neutron";
|
|
2
|
+
import {
|
|
3
|
+
describe,
|
|
4
|
+
expect,
|
|
5
|
+
it,
|
|
6
|
+
vi,
|
|
7
|
+
} from "@excom/heft-rig/node_modules/vitest";
|
|
8
|
+
import { wait } from "@excom/heft-rig/profiles/default/config/test-utils";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* "Recomposition": an app author imports a package's raw builder (the
|
|
12
|
+
* element source file, not the `index.ts` that calls `.define()`), edits its
|
|
13
|
+
* lifecycles / methods / config, and only then registers it.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// What a package's raw source file would export.
|
|
17
|
+
const onConnectedOriginal = vi.fn(() => ({ isReady: true }));
|
|
18
|
+
const onTickSetOriginal = vi.fn(() => ({ emit: ["tick"] }));
|
|
19
|
+
const makeRaw = (tag: string) =>
|
|
20
|
+
Neutron({
|
|
21
|
+
tag,
|
|
22
|
+
props: { isReady: Boolean, tickCount: Number },
|
|
23
|
+
events: { tick: { prefixWithTag: true } },
|
|
24
|
+
})
|
|
25
|
+
.onConnected(onConnectedOriginal)
|
|
26
|
+
.onPropSet("tickCount", onTickSetOriginal)
|
|
27
|
+
.defineMethods({
|
|
28
|
+
bump: ({ tickCount }) => ({ tickCount: (tickCount ?? 0) + 1 }),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("Neutron: recomposition before define()", () => {
|
|
32
|
+
it("removes and replaces lifecycles by handler reference", async () => {
|
|
33
|
+
const Raw = makeRaw("recompose-a");
|
|
34
|
+
// registry shape the docs describe: [propNames, handler] pairs
|
|
35
|
+
expect(Raw.builtConfig.lifecycles.connected).toEqual([
|
|
36
|
+
[[], onConnectedOriginal],
|
|
37
|
+
]);
|
|
38
|
+
expect(Raw.builtConfig.lifecycles.propSet).toEqual([
|
|
39
|
+
[["tickCount"], onTickSetOriginal],
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
const onConnectedReplacement = vi.fn(() => ({ isReady: false }));
|
|
43
|
+
Raw.offConnected(onConnectedOriginal)
|
|
44
|
+
.onConnected(onConnectedReplacement)
|
|
45
|
+
.offPropSet("tickCount", onTickSetOriginal);
|
|
46
|
+
expect(Raw.builtConfig.lifecycles.connected).toEqual([
|
|
47
|
+
[[], onConnectedReplacement],
|
|
48
|
+
]);
|
|
49
|
+
expect(Raw.builtConfig.lifecycles.propSet).toEqual([]);
|
|
50
|
+
|
|
51
|
+
Raw.define();
|
|
52
|
+
const el = document.createElement("recompose-a") as any;
|
|
53
|
+
document.body.append(el);
|
|
54
|
+
await wait(1);
|
|
55
|
+
expect(onConnectedOriginal).not.toHaveBeenCalled();
|
|
56
|
+
expect(onConnectedReplacement).toHaveBeenCalledTimes(1);
|
|
57
|
+
expect(el.hasAttribute("is-ready")).toBe(false);
|
|
58
|
+
|
|
59
|
+
const tickListener = vi.fn();
|
|
60
|
+
el.addEventListener("recompose-a-tick", tickListener);
|
|
61
|
+
el.bump();
|
|
62
|
+
await wait(1);
|
|
63
|
+
expect(el.getAttribute("tick-count")).toBe("1");
|
|
64
|
+
expect(onTickSetOriginal).not.toHaveBeenCalled();
|
|
65
|
+
expect(tickListener).not.toHaveBeenCalled();
|
|
66
|
+
el.remove();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("adds lifecycles, methods, and (via compose) props", async () => {
|
|
70
|
+
const Raw = makeRaw("recompose-b");
|
|
71
|
+
const Recomposed = Neutron.compose([
|
|
72
|
+
Raw,
|
|
73
|
+
Neutron({ tag: "recompose-b", props: { extraLabel: String } }),
|
|
74
|
+
])
|
|
75
|
+
.onPropSet("tickCount", () => ({ extraLabel: "ticked" }))
|
|
76
|
+
.defineMethods({
|
|
77
|
+
reset: () => ({ tickCount: null, extraLabel: null }),
|
|
78
|
+
});
|
|
79
|
+
Recomposed.define();
|
|
80
|
+
|
|
81
|
+
const el = document.createElement("recompose-b") as any;
|
|
82
|
+
document.body.append(el);
|
|
83
|
+
await wait(1);
|
|
84
|
+
// original lifecycles survive alongside the additions
|
|
85
|
+
expect(el.hasAttribute("is-ready")).toBe(true);
|
|
86
|
+
el.bump();
|
|
87
|
+
await wait(1);
|
|
88
|
+
expect(el.getAttribute("tick-count")).toBe("1");
|
|
89
|
+
expect(el.getAttribute("extra-label")).toBe("ticked");
|
|
90
|
+
el.reset();
|
|
91
|
+
await wait(1);
|
|
92
|
+
expect(el.hasAttribute("tick-count")).toBe(false);
|
|
93
|
+
expect(el.hasAttribute("extra-label")).toBe(false);
|
|
94
|
+
// compose deep-clones: the raw builder is untouched
|
|
95
|
+
expect(Raw.builtConfig.props.extraLabel).toBeUndefined();
|
|
96
|
+
expect(Raw.builtConfig.methods.map(([name]) => name)).toEqual(["bump"]);
|
|
97
|
+
el.remove();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("registers under another tag but keeps the configured event prefix", async () => {
|
|
101
|
+
const Raw = makeRaw("recompose-c");
|
|
102
|
+
Raw.define("recompose-c-custom");
|
|
103
|
+
expect(customElements.get("recompose-c")).toBeUndefined();
|
|
104
|
+
|
|
105
|
+
const el = document.createElement("recompose-c-custom") as any;
|
|
106
|
+
document.body.append(el);
|
|
107
|
+
await wait(1);
|
|
108
|
+
const tickListener = vi.fn();
|
|
109
|
+
el.addEventListener("recompose-c-tick", tickListener);
|
|
110
|
+
el.bump();
|
|
111
|
+
await wait(1);
|
|
112
|
+
expect(tickListener).toHaveBeenCalledTimes(1);
|
|
113
|
+
el.remove();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("ignores edits made after define()", async () => {
|
|
117
|
+
const Raw = makeRaw("recompose-d");
|
|
118
|
+
Raw.define();
|
|
119
|
+
const late = vi.fn(() => ({ isReady: false }));
|
|
120
|
+
Raw.onConnected(late);
|
|
121
|
+
|
|
122
|
+
const el = document.createElement("recompose-d") as any;
|
|
123
|
+
document.body.append(el);
|
|
124
|
+
await wait(1);
|
|
125
|
+
expect(late).not.toHaveBeenCalled();
|
|
126
|
+
expect(el.hasAttribute("is-ready")).toBe(true);
|
|
127
|
+
el.remove();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as utils from "../../src/utils";
|
|
2
|
+
import { describe, expect, it } from "@excom/heft-rig/node_modules/vitest";
|
|
3
|
+
|
|
4
|
+
describe("utils", () => {
|
|
5
|
+
it("isBuiltInElement", () => {
|
|
6
|
+
const el = document.createElement("div");
|
|
7
|
+
expect(utils.isBuiltInElement(el)).to.be.true;
|
|
8
|
+
const el2 = document.createElement("c-e");
|
|
9
|
+
expect(utils.isBuiltInElement(el2)).to.be.false;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("effector", () => {
|
|
13
|
+
const div = document.createElement("div");
|
|
14
|
+
const mutateDiv = utils
|
|
15
|
+
.effector((_, param) => ({
|
|
16
|
+
textContent: "Hello World",
|
|
17
|
+
style: { color: "red" },
|
|
18
|
+
returns: "YES",
|
|
19
|
+
title: param,
|
|
20
|
+
}))
|
|
21
|
+
.bind(div);
|
|
22
|
+
expect(mutateDiv("NEW_TITLE")).to.equal("YES");
|
|
23
|
+
expect(div.textContent).to.equal("Hello World");
|
|
24
|
+
expect(div.style.color).to.equal("red");
|
|
25
|
+
expect(div.title).to.equal("NEW_TITLE");
|
|
26
|
+
|
|
27
|
+
const mutateDiv2 = utils
|
|
28
|
+
.effector(() => [
|
|
29
|
+
{ autofocus: true },
|
|
30
|
+
{
|
|
31
|
+
textContent: "Hello!",
|
|
32
|
+
style: { color: "blue" },
|
|
33
|
+
returns: "PERHAPS",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "my-id",
|
|
37
|
+
},
|
|
38
|
+
{ id: "other-id" },
|
|
39
|
+
{
|
|
40
|
+
title: "my-title",
|
|
41
|
+
},
|
|
42
|
+
])
|
|
43
|
+
.bind(div);
|
|
44
|
+
expect(mutateDiv2()).to.equal("PERHAPS");
|
|
45
|
+
expect(div.autofocus).to.be.true;
|
|
46
|
+
expect(div.textContent).to.equal("Hello!");
|
|
47
|
+
expect(div.style.color).to.equal("blue");
|
|
48
|
+
expect(div.id).to.equal("other-id");
|
|
49
|
+
expect(div.title).to.equal("my-title");
|
|
50
|
+
const mutateDiv3 = utils
|
|
51
|
+
.effector(() => [
|
|
52
|
+
{
|
|
53
|
+
textContent: "World!",
|
|
54
|
+
style: { color: "green" },
|
|
55
|
+
returns: "NO",
|
|
56
|
+
},
|
|
57
|
+
{ autofocus: false },
|
|
58
|
+
{
|
|
59
|
+
title: "z-title",
|
|
60
|
+
},
|
|
61
|
+
{ id: "y-id" },
|
|
62
|
+
{
|
|
63
|
+
id: "x-id",
|
|
64
|
+
},
|
|
65
|
+
])
|
|
66
|
+
.bind(div);
|
|
67
|
+
|
|
68
|
+
expect(mutateDiv3()).to.equal("NO");
|
|
69
|
+
expect(div.autofocus).to.be.false;
|
|
70
|
+
expect(div.textContent).to.equal("World!");
|
|
71
|
+
expect(div.style.color).to.equal("green");
|
|
72
|
+
expect(div.id).to.equal("x-id");
|
|
73
|
+
expect(div.title).to.equal("z-title");
|
|
74
|
+
});
|
|
75
|
+
});
|