1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Synchronize initial values of sync boxes when window starts

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-05-20 12:38:52 +03:00
parent 9a733883f6
commit f3e41954c5
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
11 changed files with 213 additions and 37 deletions

View File

@ -13,7 +13,7 @@ export type ApplicationUpdateStatusEventId =
| "download-for-update-failed";
export interface ApplicationUpdateStatusChannelMessage { eventId: ApplicationUpdateStatusEventId; version?: string }
export type ApplicationUpdateStatusChannel = Channel<ApplicationUpdateStatusChannelMessage>;
export type ApplicationUpdateStatusChannel = Channel<ApplicationUpdateStatusChannelMessage, never>;
const applicationUpdateStatusChannelInjectable = getInjectable({
id: "application-update-status-channel",

View File

@ -5,6 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import createSyncBoxInjectable from "../../sync-box/create-sync-box.injectable";
import type { UpdateChannel } from "../update-channels";
import { syncBoxInjectionToken } from "../../sync-box/sync-box-injection-token";
const discoveredUpdateVersionInjectable = getInjectable({
id: "discovered-update-version",
@ -16,6 +17,8 @@ const discoveredUpdateVersionInjectable = getInjectable({
"discovered-update-version",
);
},
injectionToken: syncBoxInjectionToken,
});
export default discoveredUpdateVersionInjectable;

View File

@ -4,6 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import createSyncBoxInjectable from "../../sync-box/create-sync-box.injectable";
import { syncBoxInjectionToken } from "../../sync-box/sync-box-injection-token";
const progressOfUpdateDownloadInjectable = getInjectable({
id: "progress-of-update-download-state",
@ -13,6 +14,8 @@ const progressOfUpdateDownloadInjectable = getInjectable({
return createSyncBox<number>("progress-of-update-download");
},
injectionToken: syncBoxInjectionToken,
});
export default progressOfUpdateDownloadInjectable;

View File

@ -4,6 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import createSyncBoxInjectable from "../../sync-box/create-sync-box.injectable";
import { syncBoxInjectionToken } from "../../sync-box/sync-box-injection-token";
const updateIsBeingDownloadedInjectable = getInjectable({
id: "update-is-being-downloaded",
@ -13,6 +14,8 @@ const updateIsBeingDownloadedInjectable = getInjectable({
return createSyncBox<boolean>("update-is-being-downloaded");
},
injectionToken: syncBoxInjectionToken,
});
export default updateIsBeingDownloadedInjectable;

View File

@ -4,6 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import createSyncBoxInjectable from "../../sync-box/create-sync-box.injectable";
import { syncBoxInjectionToken } from "../../sync-box/sync-box-injection-token";
const updatesAreBeingDiscoveredInjectable = getInjectable({
id: "updates-are-being-discovered",
@ -13,6 +14,8 @@ const updatesAreBeingDiscoveredInjectable = getInjectable({
return createSyncBox<boolean>("updates-are-being-discovered");
},
injectionToken: syncBoxInjectionToken,
});
export default updatesAreBeingDiscoveredInjectable;

View File

@ -3,11 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx";
import { computed } from "mobx";
import syncBoxChannelInjectable from "./sync-box-channel.injectable";
import { sendToAgnosticChannelInjectionToken } from "../channel/send-to-agnostic-channel-injection-token";
import syncBoxStateInjectable from "./sync-box-state.injectable";
import type { SyncBox } from "./sync-box-injection-token";
const createSyncBoxInjectable = getInjectable({
id: "create-sync-box",
@ -37,8 +37,3 @@ const createSyncBoxInjectable = getInjectable({
export default createSyncBoxInjectable;
export interface SyncBox<TValue> {
id: string;
value: IComputedValue<TValue>;
set: (value: TValue) => void;
}

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { Channel } from "../channel/channel-injection-token";
import { channelInjectionToken } from "../channel/channel-injection-token";
export type SyncBoxInitialValueChannel = Channel<never, { id: string; value: unknown }[]>;
const syncBoxInitialValueChannelInjectable = getInjectable({
id: "sync-box-initial-value-channel",
instantiate: (): SyncBoxInitialValueChannel => ({
id: "sync-box-initial-value-channel",
}),
injectionToken: channelInjectionToken,
});
export default syncBoxInitialValueChannelInjectable;

View File

@ -0,0 +1,16 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx";
export interface SyncBox<TValue> {
id: string;
value: IComputedValue<TValue>;
set: (value: TValue) => void;
}
export const syncBoxInjectionToken = getInjectionToken<SyncBox<any>>({
id: "sync-box",
});

View File

@ -6,47 +6,99 @@ import { getInjectable } from "@ogre-tools/injectable";
import { observe, runInAction } from "mobx";
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import type { SyncBox } from "./create-sync-box.injectable";
import createSyncBoxInjectable from "./create-sync-box.injectable";
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
import { flushPromises } from "../test-utils/flush-promises";
import type { SyncBox } from "./sync-box-injection-token";
describe("sync-box", () => {
let syncBoxInMain: SyncBox<string>;
let syncBoxInRenderer: SyncBox<string>;
let applicationBuilder: ApplicationBuilder;
beforeEach(() => {
applicationBuilder = getApplicationBuilder();
const someInjectable = getInjectable({
id: "some-injectable",
instantiate: (di) => {
const createSyncBox = di.inject(createSyncBoxInjectable);
return createSyncBox<string>("some-state");
},
});
applicationBuilder.dis.mainDi.register(someInjectable);
applicationBuilder.dis.rendererDi.register(someInjectable);
syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable);
syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable);
});
describe("when application starts", () => {
beforeEach(() => {
describe("given application is started, when value is set in main", () => {
let valueInMain: string;
let syncBoxInMain: SyncBox<string>;
beforeEach(async () => {
syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable);
// await applicationBuilder.start();
observe(syncBoxInMain.value, ({ newValue }) => {
valueInMain = newValue as string;
}, true);
runInAction(() => {
syncBoxInMain.set("some-value-from-main");
});
});
it("", () => {
it("knows value in main", () => {
expect(valueInMain).toBe("some-value-from-main");
});
describe("when window starts", () => {
it("", () => {
let valueInRenderer: string;
let syncBoxInRenderer: SyncBox<string>;
beforeEach(() => {
// applicationBuilder.
syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable);
observe(syncBoxInRenderer.value, ({ newValue }) => {
valueInRenderer = newValue as string;
}, true);
});
it("does not have the initial value yet", () => {
expect(valueInRenderer).toBe(undefined);
});
describe("when getting initial value resolves", () => {
beforeEach(async () => {
await flushPromises();
});
it("has value in renderer", () => {
expect(valueInRenderer).toBe("some-value-from-main");
});
describe("when value is set from renderer", () => {
beforeEach(() => {
runInAction(() => {
syncBoxInRenderer.set("some-value-from-renderer");
});
});
it("has value in main", () => {
expect(valueInMain).toBe("some-value-from-renderer");
});
it("has value in renderer", () => {
expect(valueInRenderer).toBe("some-value-from-renderer");
});
});
});
describe("when value is set from renderer before getting initial value from main resolves", () => {
beforeEach(() => {
runInAction(() => {
syncBoxInRenderer.set("some-value-from-renderer");
});
});
it("has value in main", () => {
expect(valueInMain).toBe("some-value-from-renderer");
});
it("has value in renderer", () => {
expect(valueInRenderer).toBe("some-value-from-renderer");
});
});
});
});
@ -54,16 +106,15 @@ describe("sync-box", () => {
describe("when application starts with a window", () => {
let valueInRenderer: string;
let valueInMain: string;
let syncBoxInMain: SyncBox<string>;
let syncBoxInRenderer: SyncBox<string>;
beforeEach(async () => {
syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable);
syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable);
await applicationBuilder.render();
const applicationWindow = applicationBuilder.dis.mainDi.inject(
applicationWindowInjectable,
);
await applicationWindow.show();
observe(syncBoxInRenderer.value, ({ newValue }) => {
valueInRenderer = newValue as string;
}, true);
@ -73,11 +124,11 @@ describe("sync-box", () => {
}, true);
});
it("does not know default value in main", () => {
it("does not know initial value in main", () => {
expect(valueInMain).toBeUndefined();
});
it("does not know default value in renderer", () => {
it("does not know initial value in renderer", () => {
expect(valueInRenderer).toBeUndefined();
});
@ -114,3 +165,13 @@ describe("sync-box", () => {
});
});
});
const someInjectable = getInjectable({
id: "some-injectable",
instantiate: (di) => {
const createSyncBox = di.inject(createSyncBoxInjectable);
return createSyncBox<string>("some-state");
},
});

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { channelListenerInjectionToken } from "../../common/channel/channel-listener-injection-token";
import syncBoxInitialValueChannelInjectable from "../../common/sync-box/sync-box-initial-value-channel.injectable";
import { syncBoxInjectionToken } from "../../common/sync-box/sync-box-injection-token";
const syncBoxInitialValueChannelListenerInjectable = getInjectable({
id: "sync-box-initial-value-channel-listener",
instantiate: (di) => {
const channel = di.inject(syncBoxInitialValueChannelInjectable);
const syncBoxes = di.injectMany(syncBoxInjectionToken);
return {
channel,
handler: () =>
syncBoxes.map((box) => ({
id: box.id,
value: box.value.get(),
})),
};
},
injectionToken: channelListenerInjectionToken,
});
export default syncBoxInitialValueChannelListenerInjectable;

View File

@ -0,0 +1,40 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
import { syncBoxInjectionToken } from "../../common/sync-box/sync-box-injection-token";
import getValueFromChannelInjectable from "../channel/get-value-from-channel.injectable";
import syncBoxInitialValueChannelInjectable from "../../common/sync-box/sync-box-initial-value-channel.injectable";
import assert from "assert";
const provideInitialValuesForSyncBoxesInjectable = getInjectable({
id: "provide-initial-values-for-sync-boxes",
instantiate: (di) => {
const syncBoxes = di.injectMany(syncBoxInjectionToken);
const getValueFromChannel = di.inject(getValueFromChannelInjectable);
const syncBoxInitialValueChannel = di.inject(syncBoxInitialValueChannelInjectable);
return {
run: async () => {
const initialValues = await getValueFromChannel(syncBoxInitialValueChannel);
assert(initialValues);
initialValues.forEach(({ id, value }) => {
const targetBox = syncBoxes.find(box => box.id === id);
if (targetBox) {
targetBox.set(value);
}
});
},
};
},
injectionToken: beforeFrameStartsInjectionToken,
});
export default provideInitialValuesForSyncBoxesInjectable;