mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
auto-update notifications on the status bar (#5361)
* auto-update notifications on the status bar Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * integrated with new and improved autoupdate code Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * lint Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * refactored to include AutoUpdateComponent in the statusBarItemsInjectable Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * refactor to use a registrator Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * fix lint, remove unused code Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * refactored for the simplified logic for injecting many instances PR Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * using the update syncBox injectables directly for status bar notifications Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * removed update broadcasting/listening, updated snapshots Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * fixing tests Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * fixed tests Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * cleanup after rebase to master Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * address review comments Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * fixed incorrect injectable id Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * address review comments Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Tweak code-style Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
1 parent
165bf57380
commit
3480b517c1
47 files changed
+1999
-792
No files matched your search
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* 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 { ApplicationUpdateStatusChannel, ApplicationUpdateStatusEventId } from "../../common/application-update/application-update-status-channel.injectable";
|
||||
import applicationUpdateStatusChannelInjectable from "../../common/application-update/application-update-status-channel.injectable";
|
||||
import showInfoNotificationInjectable from "../components/notifications/show-info-notification.injectable";
|
||||
import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
const applicationUpdateStatusListenerInjectable = getInjectable({
|
||||
id: "application-update-status-listener",
|
||||
|
||||
instantiate: (di): MessageChannelListener<ApplicationUpdateStatusChannel> => {
|
||||
const channel = di.inject(applicationUpdateStatusChannelInjectable);
|
||||
const showInfoNotification = di.inject(showInfoNotificationInjectable);
|
||||
|
||||
const eventHandlers: Record<ApplicationUpdateStatusEventId, { handle: (version?: string) => void }> = {
|
||||
"checking-for-updates": {
|
||||
handle: () => {
|
||||
showInfoNotification("Checking for updates...");
|
||||
},
|
||||
},
|
||||
|
||||
"no-updates-available": {
|
||||
handle: () => {
|
||||
showInfoNotification("No new updates available");
|
||||
},
|
||||
},
|
||||
|
||||
"download-for-update-started": {
|
||||
handle: (version) => {
|
||||
showInfoNotification(`Download for version ${version} started...`);
|
||||
},
|
||||
},
|
||||
|
||||
"download-for-update-failed": {
|
||||
handle: () => {
|
||||
showInfoNotification("Download of update failed");
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
channel,
|
||||
|
||||
handler: ({ eventId, version }) => {
|
||||
eventHandlers[eventId].handle(version);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default applicationUpdateStatusListenerInjectable;
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { observer } from "mobx-react";
|
||||
import assert from "assert";
|
||||
import React, { useState } from "react";
|
||||
import { Spinner } from "../spinner";
|
||||
import type { ProgressOfUpdateDownload } from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import progressOfUpdateDownloadInjectable from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import type { DiscoveredUpdateVersion } from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
|
||||
import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
|
||||
import type { UpdateIsBeingDownloaded } from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
import updateIsBeingDownloadedInjectable from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
import type { UpdatesAreBeingDiscovered } from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||
import updatesAreBeingDiscoveredInjectable from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||
import { now as reactiveDateNow } from "mobx-utils";
|
||||
|
||||
interface Dependencies {
|
||||
progressOfUpdateDownload: ProgressOfUpdateDownload;
|
||||
discoveredVersionState: DiscoveredUpdateVersion;
|
||||
downloadingUpdateState: UpdateIsBeingDownloaded;
|
||||
checkingForUpdatesState: UpdatesAreBeingDiscovered;
|
||||
}
|
||||
|
||||
interface EndNoteProps {
|
||||
version?: string;
|
||||
note: (version: string) => JSX.Element;
|
||||
}
|
||||
|
||||
const EndNote = observer(({ version, note }: EndNoteProps) => {
|
||||
const [start] = useState(Date.now());
|
||||
|
||||
if (start + 5000 <= reactiveDateNow()) {
|
||||
return idle();
|
||||
}
|
||||
|
||||
return note(version ?? "");
|
||||
});
|
||||
|
||||
const checking = () => (
|
||||
<>
|
||||
<Spinner/>
|
||||
<div data-testid="app-update-checking">Checking for updates...</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const available = (version: string) => <div data-testid="app-update-available">{`${version ?? "Update"} is available`}</div>;
|
||||
|
||||
const notAvailable = () => <div data-testid="app-update-not-available">No new updates available</div>;
|
||||
|
||||
const downloading = (version: string) => {
|
||||
return (
|
||||
<>
|
||||
<div data-testid="app-update-downloading">{`Downloading version ${version}...`}</div>
|
||||
<Spinner/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const downloadFailed = (errMsg: string) => <div data-testid="app-update-download-failed">{errMsg}</div>;
|
||||
|
||||
const idle = () => <div data-testid="app-update-idle"></div>;
|
||||
|
||||
|
||||
export const NonInjectedAutoUpdateComponent = observer(({
|
||||
progressOfUpdateDownload,
|
||||
discoveredVersionState,
|
||||
downloadingUpdateState,
|
||||
checkingForUpdatesState,
|
||||
}: Dependencies) => {
|
||||
const discoveredVersion = discoveredVersionState.value.get();
|
||||
|
||||
const { failed } = progressOfUpdateDownload.value.get();
|
||||
|
||||
if (downloadingUpdateState.value.get()) {
|
||||
|
||||
assert(discoveredVersion);
|
||||
|
||||
return downloading(discoveredVersion.version);
|
||||
}
|
||||
|
||||
if (checkingForUpdatesState.value.get()) {
|
||||
return checking();
|
||||
}
|
||||
|
||||
if ( discoveredVersion) {
|
||||
return <EndNote note={available} version={discoveredVersion.version} />;
|
||||
}
|
||||
|
||||
if ( failed ) {
|
||||
return <EndNote note={downloadFailed} version={failed} />;
|
||||
}
|
||||
|
||||
return <EndNote note={notAvailable} />;
|
||||
});
|
||||
|
||||
export const AutoUpdateComponent = withInjectables<Dependencies>(NonInjectedAutoUpdateComponent, {
|
||||
getProps: (di, props) => ({
|
||||
progressOfUpdateDownload: di.inject(progressOfUpdateDownloadInjectable),
|
||||
discoveredVersionState: di.inject(discoveredUpdateVersionInjectable),
|
||||
downloadingUpdateState: di.inject(updateIsBeingDownloadedInjectable),
|
||||
checkingForUpdatesState: di.inject(updatesAreBeingDiscoveredInjectable),
|
||||
...props,
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import { AutoUpdateComponent } from "./auto-update-component";
|
||||
import { statusBarItemInjectionToken } from "./status-bar-item-injection-token";
|
||||
|
||||
const autoUpdateStatusBarItemInjectable = getInjectable({
|
||||
id: "auto-update-status-bar-item",
|
||||
|
||||
instantiate: () => ({
|
||||
component: AutoUpdateComponent,
|
||||
position: "left" as const,
|
||||
visible: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: statusBarItemInjectionToken,
|
||||
});
|
||||
|
||||
export default autoUpdateStatusBarItemInjectable;
|
||||
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import React from "react";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import type {
|
||||
StatusBarItemProps,
|
||||
StatusBarRegistration,
|
||||
} from "./status-bar-registration";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
|
||||
export interface RegisteredStatusBarItems {
|
||||
right: React.ComponentType<StatusBarItemProps>[];
|
||||
left: React.ComponentType<StatusBarItemProps>[];
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
registrations: IComputedValue<StatusBarRegistration[]>;
|
||||
}
|
||||
|
||||
function getRegisteredStatusBarItems({ registrations }: Dependencies): IComputedValue<RegisteredStatusBarItems> {
|
||||
return computed(() => {
|
||||
const res: RegisteredStatusBarItems = {
|
||||
left: [],
|
||||
right: [],
|
||||
};
|
||||
|
||||
for (const registration of registrations.get()) {
|
||||
if (!registration || typeof registration !== "object") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (registration.item) {
|
||||
const { item } = registration;
|
||||
|
||||
// default for old API is "right"
|
||||
res.right.push(
|
||||
() => (
|
||||
<>
|
||||
{
|
||||
typeof item === "function"
|
||||
? item()
|
||||
: item
|
||||
}
|
||||
</>
|
||||
),
|
||||
);
|
||||
} else if (registration.components) {
|
||||
const { position = "right", Item } = registration.components;
|
||||
|
||||
if (position !== "left" && position !== "right") {
|
||||
throw new TypeError("StatusBarRegistration.components.position must be either 'right' or 'left'");
|
||||
}
|
||||
|
||||
res[position].push(Item);
|
||||
}
|
||||
}
|
||||
|
||||
// This is done so that the first ones registered are closest to the corner
|
||||
res.right.reverse();
|
||||
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
const registeredStatusBarItemsInjectable = getInjectable({
|
||||
id: "registered-status-bar-items",
|
||||
|
||||
instantiate: (di) => getRegisteredStatusBarItems({
|
||||
registrations: di.inject(statusBarItemsInjectable),
|
||||
}),
|
||||
|
||||
});
|
||||
|
||||
export default registeredStatusBarItemsInjectable;
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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";
|
||||
import type React from "react";
|
||||
|
||||
export interface StatusBarItem {
|
||||
component: React.ComponentType<any>;
|
||||
position: "left" | "right";
|
||||
visible: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
export const statusBarItemInjectionToken = getInjectionToken<StatusBarItem>({
|
||||
id: "status-bar-item",
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import { extensionRegistratorInjectionToken } from "../../../extensions/extension-loader/extension-registrator-injection-token";
|
||||
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import type { StatusBarItem } from "./status-bar-item-injection-token";
|
||||
import { statusBarItemInjectionToken } from "./status-bar-item-injection-token";
|
||||
import type { StatusBarRegistration } from "./status-bar-registration";
|
||||
import React from "react";
|
||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
|
||||
const statusBarItemRegistratorInjectable = getInjectable({
|
||||
id: "status-bar-item-registrator",
|
||||
|
||||
instantiate: (di) => (extension) => {
|
||||
const rendererExtension = extension as LensRendererExtension;
|
||||
const getRandomId = di.inject(getRandomIdInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return rendererExtension.statusBarItems.flatMap(
|
||||
toItemInjectableFor(rendererExtension, getRandomId, logger),
|
||||
);
|
||||
},
|
||||
|
||||
injectionToken: extensionRegistratorInjectionToken,
|
||||
});
|
||||
|
||||
export default statusBarItemRegistratorInjectable;
|
||||
|
||||
const toItemInjectableFor = (extension: LensRendererExtension, getRandomId: () => string, logger: Logger) => {
|
||||
return (registration: StatusBarRegistration): Injectable<StatusBarItem, StatusBarItem, void>[] => {
|
||||
const id = `${getRandomId()}-status-bar-item-for-extension-${extension.sanitizedExtensionId}`;
|
||||
let component: React.ComponentType;
|
||||
let position: "left" | "right";
|
||||
|
||||
if (registration?.item) {
|
||||
const { item } = registration;
|
||||
|
||||
position = "right";
|
||||
component =
|
||||
() => (
|
||||
<>
|
||||
{
|
||||
typeof item === "function"
|
||||
? item()
|
||||
: item
|
||||
}
|
||||
</>
|
||||
);
|
||||
} else if (registration?.components) {
|
||||
const { position: pos = "right", Item } = registration.components;
|
||||
|
||||
if (pos !== "left" && pos !== "right") {
|
||||
throw new TypeError("StatusBarRegistration.components.position must be either 'right' or 'left'");
|
||||
}
|
||||
|
||||
position = pos;
|
||||
component = Item;
|
||||
} else {
|
||||
logger.warn("StatusBarRegistration must have valid item or components field");
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return [getInjectable({
|
||||
id,
|
||||
|
||||
instantiate: () => ({
|
||||
component,
|
||||
position,
|
||||
visible: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: statusBarItemInjectionToken,
|
||||
})];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
|
||||
|
||||
const statusBarItemsInjectable = getInjectable({
|
||||
id: "status-bar-items",
|
||||
|
||||
instantiate: (di) => {
|
||||
const extensions = di.inject(rendererExtensionsInjectable);
|
||||
|
||||
return computed(() =>
|
||||
extensions.get().flatMap((ext) => ext.statusBarItems),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default statusBarItemsInjectable;
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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 { IComputedValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import type { StatusBarItemProps } from "./status-bar-registration";
|
||||
import type { StatusBarItem } from "./status-bar-item-injection-token";
|
||||
import { statusBarItemInjectionToken } from "./status-bar-item-injection-token";
|
||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
|
||||
export interface StatusBarItems {
|
||||
right: React.ComponentType<StatusBarItemProps>[];
|
||||
left: React.ComponentType<StatusBarItemProps>[];
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
registrations: IComputedValue<StatusBarItem[]>;
|
||||
}
|
||||
|
||||
function getStatusBarItems({ registrations }: Dependencies): IComputedValue<StatusBarItems> {
|
||||
return computed(() => {
|
||||
const res: StatusBarItems = {
|
||||
left: [],
|
||||
right: [],
|
||||
};
|
||||
|
||||
for (const registration of registrations.get()) {
|
||||
const { position = "right", component, visible } = registration;
|
||||
|
||||
if (!visible.get()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res[position].push(component);
|
||||
}
|
||||
|
||||
// This is done so that the first ones registered are closest to the corner
|
||||
res.right.reverse();
|
||||
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
const statusBarItemsInjectable = getInjectable({
|
||||
id: "status-bar-items",
|
||||
|
||||
instantiate: (di) => {
|
||||
const computedInjectMany = di.inject(
|
||||
computedInjectManyInjectable,
|
||||
);
|
||||
|
||||
return getStatusBarItems({
|
||||
registrations: computedInjectMany(statusBarItemInjectionToken),
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default statusBarItemsInjectable;
|
||||
@@ -5,18 +5,16 @@
|
||||
|
||||
import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import { StatusBar } from "./status-bar";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import type { DiRender } from "../test-utils/renderFor";
|
||||
import { renderFor } from "../test-utils/renderFor";
|
||||
import type { IObservableArray } from "mobx";
|
||||
import { computed, observable } from "mobx";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type { StatusBarItems } from "./status-bar-items.injectable";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
import type { StatusBarRegistration } from "./status-bar-registration";
|
||||
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
|
||||
import type { ApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||
|
||||
class SomeTestExtension extends LensRendererExtension {
|
||||
constructor(statusBarItems: IObservableArray<any>) {
|
||||
@@ -35,21 +33,29 @@ class SomeTestExtension extends LensRendererExtension {
|
||||
}
|
||||
|
||||
describe("<StatusBar />", () => {
|
||||
let render: DiRender;
|
||||
let di: DiContainer;
|
||||
let statusBarItems: IObservableArray<any>;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
statusBarItems = observable.array([]);
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
render = renderFor(di);
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.unoverride(getRandomIdInjectable);
|
||||
rendererDi.permitSideEffects(getRandomIdInjectable);
|
||||
});
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(new SomeTestExtension(statusBarItems));
|
||||
|
||||
di = applicationBuilder.dis.rendererDi;
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(rendererExtensionsInjectable, () => computed(() => [new SomeTestExtension(statusBarItems)]));
|
||||
});
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
const { container } = render(<StatusBar />);
|
||||
it("renders w/o errors", async () => {
|
||||
const { container } = await applicationBuilder.render();
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
@@ -62,26 +68,27 @@ describe("<StatusBar />", () => {
|
||||
[],
|
||||
[{}],
|
||||
{},
|
||||
])("renders w/o errors when registrations are not type compliant (%p)", val => {
|
||||
])("renders w/o errors when registrations are not type compliant (%p)", async val => {
|
||||
statusBarItems.replace([val]);
|
||||
|
||||
expect(() => render(<StatusBar />)).not.toThrow();
|
||||
await expect(applicationBuilder.render()).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders items [{item: React.ReactNode}] (4.0.0-rc.1)", () => {
|
||||
it("renders items [{item: React.ReactNode}] (4.0.0-rc.1)", async () => {
|
||||
const testId = "testId";
|
||||
const text = "heee";
|
||||
|
||||
di.override(statusBarItemsInjectable, () => computed(() => [
|
||||
{ item: <span data-testid={testId} >{text}</span> },
|
||||
] as StatusBarRegistration[]));
|
||||
di.override(statusBarItemsInjectable, () => computed(() => ({
|
||||
right: [ () => <span data-testid={testId} >{text}</span> ],
|
||||
left: [],
|
||||
}) as StatusBarItems));
|
||||
|
||||
const { getByTestId } = render(<StatusBar />);
|
||||
const { getByTestId } = await applicationBuilder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
|
||||
it("renders items [{item: () => React.ReactNode}] (4.0.0-rc.1+)", () => {
|
||||
it("renders items [{item: () => React.ReactNode}] (4.0.0-rc.1+)", async () => {
|
||||
const testId = "testId";
|
||||
const text = "heee";
|
||||
|
||||
@@ -89,13 +96,13 @@ describe("<StatusBar />", () => {
|
||||
item: () => <span data-testid={testId} >{text}</span>,
|
||||
}]);
|
||||
|
||||
const { getByTestId } = render(<StatusBar />);
|
||||
const { getByTestId } = await applicationBuilder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
|
||||
|
||||
it("sort positioned items properly", () => {
|
||||
it("sort positioned items properly", async () => {
|
||||
statusBarItems.replace([
|
||||
{
|
||||
components: {
|
||||
@@ -122,7 +129,7 @@ describe("<StatusBar />", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const { getAllByTestId } = render(<StatusBar />);
|
||||
const { getAllByTestId } = await applicationBuilder.render();
|
||||
const elems = getAllByTestId("sortedElem");
|
||||
const positions = elems.map(elem => elem.textContent);
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ import styles from "./status-bar.module.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { RegisteredStatusBarItems } from "./registered-status-bar-items.injectable";
|
||||
import registeredStatusBarItemsInjectable from "./registered-status-bar-items.injectable";
|
||||
import type { StatusBarItems } from "./status-bar-items.injectable";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
export interface StatusBarProps {}
|
||||
|
||||
interface Dependencies {
|
||||
items: IComputedValue<RegisteredStatusBarItems>;
|
||||
items: IComputedValue<StatusBarItems>;
|
||||
}
|
||||
|
||||
const NonInjectedStatusBar = observer(({ items }: Dependencies & StatusBarProps) => {
|
||||
@@ -23,14 +23,14 @@ const NonInjectedStatusBar = observer(({ items }: Dependencies & StatusBarProps)
|
||||
|
||||
return (
|
||||
<div className={styles.StatusBar}>
|
||||
<div className={styles.leftSide}>
|
||||
<div className={styles.leftSide} data-testid="status-bar-left">
|
||||
{left.map((Item, index) => (
|
||||
<div className={styles.item} key={index}>
|
||||
<Item />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={styles.rightSide}>
|
||||
<div className={styles.rightSide} data-testid="status-bar-right">
|
||||
{right.map((Item, index) => (
|
||||
<div className={styles.item} key={index}>
|
||||
<Item />
|
||||
@@ -44,7 +44,7 @@ const NonInjectedStatusBar = observer(({ items }: Dependencies & StatusBarProps)
|
||||
|
||||
export const StatusBar = withInjectables<Dependencies, StatusBarProps>(NonInjectedStatusBar, {
|
||||
getProps: (di, props) => ({
|
||||
items: di.inject(registeredStatusBarItemsInjectable),
|
||||
items: di.inject(statusBarItemsInjectable),
|
||||
...props,
|
||||
}),
|
||||
});
|
||||
@@ -17,8 +17,10 @@ export class TestExtension extends LensRendererExtension {}
|
||||
|
||||
export type FakeExtensionData = SetRequired<Partial<LensRendererExtension>, "id" | "name">;
|
||||
|
||||
export const getRendererExtensionFakeFor = (builder: ApplicationBuilder) => (
|
||||
function getRendererExtensionFake({ id, name, ...rest }: FakeExtensionData) {
|
||||
export type GetRendererExtensionFake = (fakeExtensionData: FakeExtensionData) => TestExtension;
|
||||
|
||||
export const getRendererExtensionFakeFor = (builder: ApplicationBuilder): GetRendererExtensionFake => (
|
||||
function getRendererExtensionFake({ id, name, ...rest }) {
|
||||
const instance = new TestExtension({
|
||||
id,
|
||||
absolutePath: "irrelevant",
|
||||
|
||||
Reference in new issue
Block a user