mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix stale UI state in extension preferences
Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
4e15279894
commit
e2e0fd3860
@ -2155,6 +2155,165 @@ exports[`preferences - navigation to extension specific preferences given in pre
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`preferences - navigation to extension specific preferences given in preferences, when rendered when extension with specific preferences is enabled when navigating to extension preferences using navigation when extension is disabled renders 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="StatusBar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leftSide"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="rightSide"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="SettingLayout showNavigation Preferences"
|
||||||
|
data-testid="extension-preferences-page"
|
||||||
|
>
|
||||||
|
<nav
|
||||||
|
class="sidebarRegion"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="sidebar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Tabs flex column"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="header"
|
||||||
|
>
|
||||||
|
Preferences
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Tab flex gaps align-center"
|
||||||
|
data-testid="tab-link-for-application"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
App
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Tab flex gaps align-center"
|
||||||
|
data-testid="tab-link-for-proxy"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
Proxy
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Tab flex gaps align-center"
|
||||||
|
data-testid="tab-link-for-kubernetes"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
Kubernetes
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Tab flex gaps align-center"
|
||||||
|
data-testid="tab-link-for-editor"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
Editor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Tab flex gaps align-center"
|
||||||
|
data-testid="tab-link-for-terminal"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
Terminal
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div
|
||||||
|
class="contentRegion"
|
||||||
|
id="ScrollSpyRoot"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="content"
|
||||||
|
>
|
||||||
|
<section
|
||||||
|
id="extensions"
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
|
||||||
|
preferences
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
class="flex items-center"
|
||||||
|
data-testid="error-for-extension-not-being-present"
|
||||||
|
>
|
||||||
|
No extension found
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="toolsRegion"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="fixed top-[60px]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="close-preferences"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-label="Close"
|
||||||
|
class="closeButton"
|
||||||
|
role="button"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="Icon icon material focusable"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="icon"
|
||||||
|
data-icon-name="close"
|
||||||
|
>
|
||||||
|
close
|
||||||
|
</span>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class="esc"
|
||||||
|
>
|
||||||
|
ESC
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Notifications flex column align-flex-end"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`preferences - navigation to extension specific preferences when navigating to extension specific tab renders 1`] = `
|
exports[`preferences - navigation to extension specific preferences when navigating to extension specific tab renders 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -7,12 +7,13 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
|||||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import "@testing-library/jest-dom/extend-expect";
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
import type { FakeExtensionData, TestExtension } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||||
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||||
import type { DiContainer } from "@ogre-tools/injectable";
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting";
|
||||||
import extensionPreferencesRouteInjectable from "../../common/front-end-routing/routes/preferences/extension/extension-preferences-route.injectable";
|
import extensionPreferencesRouteInjectable from "../../common/front-end-routing/routes/preferences/extension/extension-preferences-route.injectable";
|
||||||
|
|
||||||
|
|
||||||
describe("preferences - navigation to extension specific preferences", () => {
|
describe("preferences - navigation to extension specific preferences", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
|
|
||||||
@ -98,9 +99,14 @@ describe("preferences - navigation to extension specific preferences", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("when extension with specific preferences is enabled", () => {
|
describe("when extension with specific preferences is enabled", () => {
|
||||||
|
let testExtension: TestExtension;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||||
const testExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems);
|
|
||||||
|
testExtension = getRendererExtensionFake(
|
||||||
|
extensionStubWithExtensionSpecificPreferenceItems,
|
||||||
|
);
|
||||||
|
|
||||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||||
});
|
});
|
||||||
@ -159,6 +165,26 @@ describe("preferences - navigation to extension specific preferences", () => {
|
|||||||
|
|
||||||
expect(actual).toHaveClass("active");
|
expect(actual).toHaveClass("active");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when extension is disabled", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
applicationBuilder.extensions.renderer.disable(testExtension);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(rendered.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the error message about extension not being present", () => {
|
||||||
|
expect(rendered.getByTestId("error-for-extension-not-being-present")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when extension is enabled again, does not show the error message anymore", () => {
|
||||||
|
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||||
|
|
||||||
|
expect(rendered.queryByTestId("error-for-extension-not-being-present")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
|
import type { IComputedValue } from "mobx";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { RegisteredAppPreference } from "./app-preferences/app-preference-registration";
|
import type { RegisteredAppPreference } from "./app-preferences/app-preference-registration";
|
||||||
@ -12,44 +13,50 @@ import { ExtensionSettings } from "./extension-settings";
|
|||||||
import { Preferences } from "./preferences";
|
import { Preferences } from "./preferences";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
preferenceItems: RegisteredAppPreference[];
|
model: IComputedValue<{
|
||||||
extensionName?: string;
|
preferenceItems: RegisteredAppPreference[];
|
||||||
|
extensionName?: string;
|
||||||
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedExtensions = ({ preferenceItems, extensionName }: Dependencies) => (
|
const NonInjectedExtensions = ({ model }: Dependencies) => {
|
||||||
<Preferences data-testid="extension-preferences-page">
|
const { extensionName, preferenceItems } = model.get();
|
||||||
<section id="extensions">
|
|
||||||
<h2>
|
return (
|
||||||
{extensionName}
|
<Preferences data-testid="extension-preferences-page">
|
||||||
{" "}
|
<section id="extensions">
|
||||||
preferences
|
<h2>
|
||||||
</h2>
|
{extensionName}
|
||||||
{!extensionName && (
|
{" "}
|
||||||
<div className="flex items-center">No extension found</div>
|
preferences
|
||||||
)}
|
</h2>
|
||||||
{preferenceItems.map((preferenceItem, index) => (
|
{!extensionName && (
|
||||||
<ExtensionSettings
|
<div
|
||||||
key={`${preferenceItem.id}-${index}`}
|
className="flex items-center"
|
||||||
setting={preferenceItem}
|
data-testid="error-for-extension-not-being-present"
|
||||||
size="small"
|
>
|
||||||
data-testid={`extension-preference-item-for-${preferenceItem.id}`}
|
No extension found
|
||||||
/>
|
</div>
|
||||||
))}
|
)}
|
||||||
</section>
|
{preferenceItems.map((preferenceItem, index) => (
|
||||||
</Preferences>
|
<ExtensionSettings
|
||||||
);
|
key={`${preferenceItem.id}-${index}`}
|
||||||
|
setting={preferenceItem}
|
||||||
|
size="small"
|
||||||
|
data-testid={`extension-preference-item-for-${preferenceItem.id}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</section>
|
||||||
|
</Preferences>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Extensions = withInjectables<Dependencies>(
|
export const Extensions = withInjectables<Dependencies>(
|
||||||
observer(NonInjectedExtensions),
|
observer(NonInjectedExtensions),
|
||||||
|
|
||||||
{
|
{
|
||||||
getProps: (di) => {
|
getProps: (di) => ({
|
||||||
const { preferenceItems, extensionName } = di.inject(extensionPreferencesModelInjectable).get();
|
model: di.inject(extensionPreferencesModelInjectable),
|
||||||
|
}),
|
||||||
return {
|
|
||||||
preferenceItems,
|
|
||||||
extensionName,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import type { PreferenceNavigationItem } from "./preference-navigation-items.inj
|
|||||||
import { Icon } from "../../icon";
|
import { Icon } from "../../icon";
|
||||||
import { PreferencesNavigationTab } from "./preference-navigation-tab";
|
import { PreferencesNavigationTab } from "./preference-navigation-tab";
|
||||||
import preferenceNavigationItemsForGroupInjectable from "./preference-navigation-items-for-group.injectable";
|
import preferenceNavigationItemsForGroupInjectable from "./preference-navigation-items-for-group.injectable";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
navigationItems: IComputedValue<PreferenceNavigationItem[]>;
|
navigationItems: IComputedValue<PreferenceNavigationItem[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NonInjectedExtensionsNavGroup(props: Dependencies) {
|
const NonInjectedExtensionsNavGroup = observer((props: Dependencies) => {
|
||||||
if (!props.navigationItems.get().length) {
|
if (!props.navigationItems.get().length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -42,7 +43,7 @@ function NonInjectedExtensionsNavGroup(props: Dependencies) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export const ExtensionsNavGroup = withInjectables<Dependencies>(
|
export const ExtensionsNavGroup = withInjectables<Dependencies>(
|
||||||
NonInjectedExtensionsNavGroup,
|
NonInjectedExtensionsNavGroup,
|
||||||
|
|||||||
@ -8,12 +8,13 @@ import type { IComputedValue } from "mobx";
|
|||||||
import type { PreferenceNavigationItem } from "./preference-navigation-items.injectable";
|
import type { PreferenceNavigationItem } from "./preference-navigation-items.injectable";
|
||||||
import { PreferencesNavigationTab } from "./preference-navigation-tab";
|
import { PreferencesNavigationTab } from "./preference-navigation-tab";
|
||||||
import preferenceNavigationItemsForGroupInjectable from "./preference-navigation-items-for-group.injectable";
|
import preferenceNavigationItemsForGroupInjectable from "./preference-navigation-items-for-group.injectable";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
navigationItems: IComputedValue<PreferenceNavigationItem[]>;
|
navigationItems: IComputedValue<PreferenceNavigationItem[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NonInjectedGeneralNavGroup(props: Dependencies) {
|
const NonInjectedGeneralNavGroup = observer((props: Dependencies) => {
|
||||||
if (!props.navigationItems.get().length) {
|
if (!props.navigationItems.get().length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -31,7 +32,7 @@ function NonInjectedGeneralNavGroup(props: Dependencies) {
|
|||||||
))}
|
))}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export const GeneralNavGroup = withInjectables<Dependencies>(
|
export const GeneralNavGroup = withInjectables<Dependencies>(
|
||||||
NonInjectedGeneralNavGroup,
|
NonInjectedGeneralNavGroup,
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import { pipeline } from "@ogre-tools/fp";
|
import { pipeline } from "@ogre-tools/fp";
|
||||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||||
|
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||||
import { filter, orderBy } from "lodash/fp";
|
import { filter, orderBy } from "lodash/fp";
|
||||||
import type { IComputedValue } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
@ -26,14 +27,18 @@ export interface PreferenceNavigationItem {
|
|||||||
const preferenceNavigationItemsInjectable = getInjectable({
|
const preferenceNavigationItemsInjectable = getInjectable({
|
||||||
id: "preference-navigation-items",
|
id: "preference-navigation-items",
|
||||||
|
|
||||||
instantiate: (di) =>
|
instantiate: (di) => {
|
||||||
computed((): PreferenceNavigationItem[] =>
|
const computedInjectMany = di.inject(computedInjectManyInjectable);
|
||||||
|
const navigationItems = computedInjectMany(preferenceNavigationItemInjectionToken);
|
||||||
|
|
||||||
|
return computed((): PreferenceNavigationItem[] =>
|
||||||
pipeline(
|
pipeline(
|
||||||
di.injectMany(preferenceNavigationItemInjectionToken),
|
navigationItems.get(),
|
||||||
filter((item) => !!item.isVisible.get()),
|
filter((item) => !!item.isVisible.get()),
|
||||||
(items) => orderBy([(item) => item.orderNumber], ["asc"], items),
|
(items) => orderBy([(item) => item.orderNumber], ["asc"], items),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default preferenceNavigationItemsInjectable;
|
export default preferenceNavigationItemsInjectable;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user