UNPKG

@joist/di

Version:

Dependency Injection for Vanilla JS classes

284 lines (283 loc) • 13.2 kB
import { __esDecorate, __runInitializers } from "tslib"; import { assert } from "chai"; import { inject } from "../inject.js"; import { injectable } from "../injectable.js"; import { DOMInjector } from "./dom-injector.js"; it("should allow services to be injected into custom element", () => { class Foo { } let MyElement = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var MyElement = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); MyElement = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } foo = inject(Foo); }; return MyElement = _classThis; })(); customElements.define("injectable-1", MyElement); const el = new MyElement(); assert.instanceOf(el.foo(), Foo); }); it("should allow services to be injected into custom elements that has been extended", () => { class Foo { } class MyBaseElement extends HTMLElement { } let MyElement = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = MyBaseElement; var MyElement = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); MyElement = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } foo = inject(Foo); }; return MyElement = _classThis; })(); customElements.define("injectable-2", MyElement); const el = new MyElement(); assert.instanceOf(el.foo(), Foo); }); it("should handle parent HTML Injectors", async () => { let A = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; var A = class { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); A = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } }; return A = _classThis; })(); let B = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; var B = class { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); B = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } a = inject(A); }; return B = _classThis; })(); class AltA { } let Parent = (() => { let _classDecorators = [injectable({ providers: [ [B, { use: B }], [A, { use: AltA }], ], })]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Parent = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Parent = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } }; return Parent = _classThis; })(); let Child = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Child = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Child = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } b = inject(B); }; return Child = _classThis; })(); customElements.define("injectable-parent-1", Parent); customElements.define("injectable-child-1", Child); const el = document.createElement("div"); el.innerHTML = ` <injectable-parent-1> <injectable-child-1></injectable-child-1> </injectable-parent-1> `; document.body.append(el); const child = el.querySelector("injectable-child-1"); assert.instanceOf(child?.b().a(), AltA); el.remove(); }); it("should handle changing contexts", async () => { class A { } class AltA { } let Ctx1 = (() => { let _classDecorators = [injectable({ providers: [[A, { use: A }]], })]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Ctx1 = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Ctx1 = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } }; return Ctx1 = _classThis; })(); let Ctx2 = (() => { let _classDecorators = [injectable({ providers: [[A, { use: AltA }]], })]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Ctx2 = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Ctx2 = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } }; return Ctx2 = _classThis; })(); let Child = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Child = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Child = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } a = inject(A); }; return Child = _classThis; })(); customElements.define("ctx-1", Ctx1); customElements.define("ctx-2", Ctx2); customElements.define("ctx-child", Child); const el = document.createElement("div"); el.innerHTML = ` <div> <ctx-1> <ctx-child></ctx-child> </ctx-1> <ctx-2></ctx-2> </div> `; document.body.append(el); const ctx2 = el.querySelector("ctx-2"); let child = el.querySelector("ctx-child"); assert.instanceOf(child?.a(), A); child.remove(); ctx2?.append(child); child = el.querySelector("ctx-child"); assert.instanceOf(child?.a(), AltA); }); it("should provide the same context in disconnectedCallback as connectedCallback", async () => { class A { } class AltA { } const app = new DOMInjector({ providers: [[A, { use: AltA }]], }); app.attach(document.body); let Example = (() => { let _classDecorators = [injectable()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = HTMLElement; var Example = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Example = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } #ctx = inject(A); connected = null; disconnected = null; connectedCallback() { this.connected = this.#ctx(); } disconnectedCallback() { this.disconnected = this.#ctx(); } }; return Example = _classThis; })(); customElements.define("ctx-3", Example); const el = document.createElement("ctx-3"); document.body.append(el); assert.instanceOf(el.connected, AltA); el.remove(); assert.instanceOf(el.disconnected, AltA); assert.equal(el.connected, el.disconnected); app.detach(); }); //# sourceMappingURL=injectable-el.test.js.map