mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
chore: Introduce competition for InitializableState
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
82fdcf69c0
commit
72a01cdc17
@ -5,11 +5,14 @@
|
||||
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "@k8slens/run-many";
|
||||
import { runManyFor } from "@k8slens/run-many";
|
||||
import type { DiContainer, Injectable, InjectionToken } from "@ogre-tools/injectable";
|
||||
import { createContainer, getInjectionToken } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import type { InitializableState } from "./create";
|
||||
import { createInitializableState } from "./create";
|
||||
import type { ImplInitializableInjectionTokensArgs, Initializable, InitializableState } from "./create";
|
||||
import { getInjectablesForInitializable, getInitializable, createInitializableState } from "./create";
|
||||
|
||||
describe("InitializableState tests", () => {
|
||||
let di: DiContainer;
|
||||
@ -75,3 +78,72 @@ describe("InitializableState tests", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("InitializableTokens technical tests", () => {
|
||||
let di: DiContainer;
|
||||
let initializableToken: Initializable<number>;
|
||||
let phase: InjectionToken<Runnable<void>, void>;
|
||||
|
||||
beforeEach(() => {
|
||||
di = createContainer("irrelevant");
|
||||
|
||||
initializableToken = getInitializable("some-root-id");
|
||||
phase = getInjectionToken({ id: "some-runnable-phase" });
|
||||
});
|
||||
|
||||
it("throws given attempting to inject the state token", () => {
|
||||
expect(() => di.inject(initializableToken.stateToken)).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Tried to inject non-registered injectable "irrelevant" -> "some-root-id-state-token"."`,
|
||||
);
|
||||
});
|
||||
|
||||
describe("given some implementation for initializableToken is registered", () => {
|
||||
let mockInit: AsyncFnMock<ImplInitializableInjectionTokensArgs<number>["init"]>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockInit = asyncFn();
|
||||
|
||||
const { initializationInjectable, stateInjectable } = getInjectablesForInitializable({
|
||||
init: mockInit,
|
||||
phase,
|
||||
token: initializableToken,
|
||||
});
|
||||
|
||||
di.register(initializationInjectable, stateInjectable);
|
||||
});
|
||||
|
||||
it("throws given attempting to inject the state token", () => {
|
||||
expect(() => di.inject(initializableToken.stateToken)).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Tried to inject "some-root-id" before initialization was complete"`,
|
||||
);
|
||||
});
|
||||
|
||||
describe("given the phase is started to be run", () => {
|
||||
let runManyPromise: Promise<void>;
|
||||
|
||||
beforeEach(() => {
|
||||
runManyPromise = runManyFor(di)(phase)();
|
||||
});
|
||||
|
||||
it("throws given attempting to inject the state token", () => {
|
||||
expect(() => di.inject(initializableToken.stateToken)).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Tried to inject "some-root-id" before initialization was complete"`,
|
||||
);
|
||||
});
|
||||
|
||||
describe("when initialization is complete", () => {
|
||||
beforeEach(async () => {
|
||||
await mockInit.resolve(10);
|
||||
});
|
||||
|
||||
it("initializes the state", () => {
|
||||
expect(di.inject(initializableToken.stateToken)).toBe(10);
|
||||
});
|
||||
|
||||
it("allows the runMany to complete", async () => {
|
||||
await runManyPromise;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { Runnable } from "@k8slens/run-many";
|
||||
import type { DiContainerForInjection, Injectable, InjectionToken } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { getInjectionToken, getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
|
||||
export interface CreateInitializableStateArgs<T> {
|
||||
id: string;
|
||||
@ -21,6 +23,67 @@ type InitializableStateValue<T> =
|
||||
| { set: false }
|
||||
| { set: true; value: T } ;
|
||||
|
||||
export interface Initializable<T> {
|
||||
readonly rootId: string;
|
||||
readonly stateToken: InjectionToken<T, void>;
|
||||
}
|
||||
|
||||
export const getInitializable = <T>(rootId: string): Initializable<T> => ({
|
||||
rootId,
|
||||
stateToken: getInjectionToken<T>({
|
||||
id: `${rootId}-state-token`,
|
||||
}),
|
||||
});
|
||||
|
||||
type InitState<T> = { set: true; value: T } | { set: false };
|
||||
|
||||
export interface ImplInitializableInjectionTokensArgs<T> {
|
||||
token: Initializable<T>;
|
||||
init: (di: DiContainerForInjection) => T | Promise<T>;
|
||||
phase: InjectionToken<Runnable<void>, void>;
|
||||
runAfter?: Runnable<void>["runAfter"];
|
||||
}
|
||||
|
||||
export const getInjectablesForInitializable = <T>({
|
||||
init,
|
||||
phase,
|
||||
token: {
|
||||
rootId,
|
||||
stateToken,
|
||||
},
|
||||
runAfter,
|
||||
}: ImplInitializableInjectionTokensArgs<T>) => {
|
||||
let state: InitState<T> = { set: false };
|
||||
|
||||
const stateInjectable = getInjectable({
|
||||
id: `${rootId}-state`,
|
||||
instantiate: () => {
|
||||
assert(state.set, `Tried to inject "${rootId}" before initialization was complete`);
|
||||
|
||||
return state.value;
|
||||
},
|
||||
injectionToken: stateToken,
|
||||
});
|
||||
const initializationInjectable = getInjectable({
|
||||
id: `${rootId}-initialization`,
|
||||
instantiate: (di) => ({
|
||||
run: async () => {
|
||||
state = {
|
||||
set: true,
|
||||
value: await init(di),
|
||||
};
|
||||
},
|
||||
runAfter,
|
||||
}),
|
||||
injectionToken: phase,
|
||||
});
|
||||
|
||||
return {
|
||||
stateInjectable,
|
||||
initializationInjectable,
|
||||
};
|
||||
};
|
||||
|
||||
export function createInitializableState<T>(args: CreateInitializableStateArgs<T>): Injectable<InitializableState<T>, unknown, void> {
|
||||
const { id, init, injectionToken } = args;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user