From 438044f00100ab7814153b9ef01f60e68840d77d Mon Sep 17 00:00:00 2001 From: Iku-turso Date: Wed, 23 Mar 2022 15:55:49 +0200 Subject: [PATCH] Introduce a collection of behavioural unit tests for navigation This reverts commit ecd881c25df219b511d7efd43dac59e748b21cc7. --- ...acters-in-page-registrations.test.tsx.snap | 11 + .../navigate-to-extension-page.test.tsx.snap | 83 + .../navigating-between-routes.test.tsx.snap | 20 + ...gation-using-application-menu.test.ts.snap | 89 + .../navigation-using-application-menu.test.ts | 51 + .../order-of-sidebar-items.test.tsx.snap | 719 +++++ ...-and-tab-navigation-for-core.test.tsx.snap | 2126 +++++++++++++ ...ab-navigation-for-extensions.test.tsx.snap | 2644 +++++++++++++++++ .../visibility-of-sidebar-items.test.tsx.snap | 569 ++++ .../cluster/order-of-sidebar-items.test.tsx | 136 + ...debar-and-tab-navigation-for-core.test.tsx | 345 +++ ...and-tab-navigation-for-extensions.test.tsx | 455 +++ .../visibility-of-sidebar-items.test.tsx | 124 + ...-characters-in-page-registrations.test.tsx | 61 + ...gation-using-application-menu.test.ts.snap | 123 + .../navigation-using-application-menu.test.ts | 66 + .../navigate-to-extension-page.test.tsx | 185 ++ .../navigating-between-routes.test.tsx | 241 ++ .../closing-preferences.test.tsx.snap | 1591 ++++++++++ ...on-to-application-preferences.test.ts.snap | 696 +++++ ...igation-to-editor-preferences.test.ts.snap | 886 ++++++ ...tension-specific-preferences.test.tsx.snap | 1175 ++++++++ ...ion-to-kubernetes-preferences.test.ts.snap | 917 ++++++ ...vigation-to-proxy-preferences.test.ts.snap | 696 +++++ ...ion-to-telemetry-preferences.test.tsx.snap | 1500 ++++++++++ ...ation-to-terminal-preferences.test.ts.snap | 805 +++++ ...gation-using-application-menu.test.ts.snap | 498 ++++ .../preferences/closing-preferences.test.tsx | 273 ++ ...igation-to-application-preferences.test.ts | 72 + .../navigation-to-editor-preferences.test.ts | 69 + ...to-extension-specific-preferences.test.tsx | 135 + ...vigation-to-kubernetes-preferences.test.ts | 70 + .../navigation-to-proxy-preferences.test.ts | 68 + ...vigation-to-telemetry-preferences.test.tsx | 202 ++ ...navigation-to-terminal-preferences.test.ts | 71 + .../navigation-using-application-menu.test.ts | 66 + ...gation-using-application-menu.test.ts.snap | 90 + .../navigation-using-application-menu.test.ts | 47 + 38 files changed, 17975 insertions(+) create mode 100644 src/behaviours/__snapshots__/extension-special-characters-in-page-registrations.test.tsx.snap create mode 100644 src/behaviours/__snapshots__/navigate-to-extension-page.test.tsx.snap create mode 100644 src/behaviours/__snapshots__/navigating-between-routes.test.tsx.snap create mode 100644 src/behaviours/add-cluster/__snapshots__/navigation-using-application-menu.test.ts.snap create mode 100644 src/behaviours/add-cluster/navigation-using-application-menu.test.ts create mode 100644 src/behaviours/cluster/__snapshots__/order-of-sidebar-items.test.tsx.snap create mode 100644 src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-core.test.tsx.snap create mode 100644 src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-extensions.test.tsx.snap create mode 100644 src/behaviours/cluster/__snapshots__/visibility-of-sidebar-items.test.tsx.snap create mode 100644 src/behaviours/cluster/order-of-sidebar-items.test.tsx create mode 100644 src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx create mode 100644 src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx create mode 100644 src/behaviours/cluster/visibility-of-sidebar-items.test.tsx create mode 100644 src/behaviours/extension-special-characters-in-page-registrations.test.tsx create mode 100644 src/behaviours/extensions/__snapshots__/navigation-using-application-menu.test.ts.snap create mode 100644 src/behaviours/extensions/navigation-using-application-menu.test.ts create mode 100644 src/behaviours/navigate-to-extension-page.test.tsx create mode 100644 src/behaviours/navigating-between-routes.test.tsx create mode 100644 src/behaviours/preferences/__snapshots__/closing-preferences.test.tsx.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-application-preferences.test.ts.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-editor-preferences.test.ts.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-extension-specific-preferences.test.tsx.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-kubernetes-preferences.test.ts.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-proxy-preferences.test.ts.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-telemetry-preferences.test.tsx.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-to-terminal-preferences.test.ts.snap create mode 100644 src/behaviours/preferences/__snapshots__/navigation-using-application-menu.test.ts.snap create mode 100644 src/behaviours/preferences/closing-preferences.test.tsx create mode 100644 src/behaviours/preferences/navigation-to-application-preferences.test.ts create mode 100644 src/behaviours/preferences/navigation-to-editor-preferences.test.ts create mode 100644 src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx create mode 100644 src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts create mode 100644 src/behaviours/preferences/navigation-to-proxy-preferences.test.ts create mode 100644 src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx create mode 100644 src/behaviours/preferences/navigation-to-terminal-preferences.test.ts create mode 100644 src/behaviours/preferences/navigation-using-application-menu.test.ts create mode 100644 src/behaviours/welcome/__snapshots__/navigation-using-application-menu.test.ts.snap create mode 100644 src/behaviours/welcome/navigation-using-application-menu.test.ts diff --git a/src/behaviours/__snapshots__/extension-special-characters-in-page-registrations.test.tsx.snap b/src/behaviours/__snapshots__/extension-special-characters-in-page-registrations.test.tsx.snap new file mode 100644 index 0000000000000..3b43a51f66b36 --- /dev/null +++ b/src/behaviours/__snapshots__/extension-special-characters-in-page-registrations.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`extension special characters in page registrations renders 1`] = `
`; + +exports[`extension special characters in page registrations when navigating to route with ID having special characters renders 1`] = ` +
+
+ Some page +
+
+`; diff --git a/src/behaviours/__snapshots__/navigate-to-extension-page.test.tsx.snap b/src/behaviours/__snapshots__/navigate-to-extension-page.test.tsx.snap new file mode 100644 index 0000000000000..edab04b903897 --- /dev/null +++ b/src/behaviours/__snapshots__/navigate-to-extension-page.test.tsx.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`navigate to extension page renders 1`] = `
`; + +exports[`navigate to extension page when extension navigates to child route renders 1`] = ` +
+
+ Child page +
+
+`; + +exports[`navigate to extension page when extension navigates to route with parameters renders 1`] = ` +
+
+
    +
  • + some-string-value-from-navigate +
  • +
  • + 126 +
  • +
  • + some-array-value-from-navigate +
  • +
+ +
+
+`; + +exports[`navigate to extension page when extension navigates to route without parameters renders 1`] = ` +
+
+
    +
  • + some-string-value +
  • +
  • + 42 +
  • +
  • + some-array-value,some-other-array-value +
  • +
+ +
+
+`; + +exports[`navigate to extension page when extension navigates to route without parameters when changing page parameters renders 1`] = ` +
+
+
    +
  • + some-changed-string-value +
  • +
  • + 84 +
  • +
  • + some-changed-array-value,some-other-changed-array-value +
  • +
+ +
+
+`; diff --git a/src/behaviours/__snapshots__/navigating-between-routes.test.tsx.snap b/src/behaviours/__snapshots__/navigating-between-routes.test.tsx.snap new file mode 100644 index 0000000000000..90ff615b2b0e2 --- /dev/null +++ b/src/behaviours/__snapshots__/navigating-between-routes.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`navigating between routes given route with optional path parameters when navigating to route with path parameters renders 1`] = ` +
+
+    {
+  "someParameter": "some-value",
+  "someOtherParameter": "some-other-value"
+}
+  
+
+`; + +exports[`navigating between routes given route without path parameters when navigating to route renders 1`] = ` +
+
+ Some component +
+
+`; diff --git a/src/behaviours/add-cluster/__snapshots__/navigation-using-application-menu.test.ts.snap b/src/behaviours/add-cluster/__snapshots__/navigation-using-application-menu.test.ts.snap new file mode 100644 index 0000000000000..221440818f310 --- /dev/null +++ b/src/behaviours/add-cluster/__snapshots__/navigation-using-application-menu.test.ts.snap @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`add-cluster - navigation using application menu renders 1`] = `
`; + +exports[`add-cluster - navigation using application menu when navigating to add cluster using application menu renders 1`] = ` +
+
+
+
+

+ Add Clusters from Kubeconfig +

+

+ Clusters added here are + + not + + merged into the + + ~/.kube/config + + file. + + + Read more about adding clusters + + . +

+
+
+ +
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/add-cluster/navigation-using-application-menu.test.ts b/src/behaviours/add-cluster/navigation-using-application-menu.test.ts new file mode 100644 index 0000000000000..7cd84cd444c99 --- /dev/null +++ b/src/behaviours/add-cluster/navigation-using-application-menu.test.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import isAutoUpdateEnabledInjectable from "../../main/is-auto-update-enabled.injectable"; + +// TODO: Make components free of side effects by making them deterministic +jest.mock("../../renderer/components/tooltip"); +jest.mock("../../renderer/components/monaco-editor/monaco-editor"); + +describe("add-cluster - navigation using application menu", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder().beforeSetups(({ mainDi }) => { + mainDi.override(isAutoUpdateEnabledInjectable, () => () => false); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show welcome page yet", () => { + const actual = rendered.queryByTestId("add-cluster-page"); + + expect(actual).toBeNull(); + }); + + describe("when navigating to add cluster using application menu", () => { + beforeEach(() => { + applicationBuilder.applicationMenu.click("file.add-cluster"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows add cluster page", () => { + const actual = rendered.getByTestId("add-cluster-page"); + + expect(actual).not.toBeNull(); + }); + }); +}); diff --git a/src/behaviours/cluster/__snapshots__/order-of-sidebar-items.test.tsx.snap b/src/behaviours/cluster/__snapshots__/order-of-sidebar-items.test.tsx.snap new file mode 100644 index 0000000000000..4a5b4f13602ea --- /dev/null +++ b/src/behaviours/cluster/__snapshots__/order-of-sidebar-items.test.tsx.snap @@ -0,0 +1,719 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cluster - order of sidebar items when rendered renders 1`] = ` +
+ +`; + +exports[`cluster - order of sidebar items when rendered when parent is expanded renders 1`] = ` +
+ +`; diff --git a/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-core.test.tsx.snap b/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-core.test.tsx.snap new file mode 100644 index 0000000000000..7e1c7406fdaf1 --- /dev/null +++ b/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-core.test.tsx.snap @@ -0,0 +1,2126 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cluster - sidebar and tab navigation for core given core registrations given empty state for expanded sidebar items already exists, when rendered renders without errors 1`] = ` +
+
+ +`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given no initially persisted state for sidebar items, when rendered renders 1`] = ` +
+
+ +`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given no initially persisted state for sidebar items, when rendered when a parent sidebar item is expanded renders 1`] = ` +
+
+ +`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given no initially persisted state for sidebar items, when rendered when a parent sidebar item is expanded when a child of the parent is selected renders 1`] = ` +
+
+
+
+ ?? +
+
+
+ +
+
+`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered renders 1`] = ` +
+
+
+
+ ?? +
+
+
+ +
+
+`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given state for expanded sidebar items already exists, when rendered renders 1`] = ` +
+
+ +`; + +exports[`cluster - sidebar and tab navigation for core given core registrations given state for expanded unknown sidebar items already exists, when rendered renders without errors 1`] = ` +
+
+ +`; diff --git a/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-extensions.test.tsx.snap b/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-extensions.test.tsx.snap new file mode 100644 index 0000000000000..469eba69f6381 --- /dev/null +++ b/src/behaviours/cluster/__snapshots__/sidebar-and-tab-navigation-for-extensions.test.tsx.snap @@ -0,0 +1,2644 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given empty state for expanded sidebar items already exists, when rendered renders without errors 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given no initially persisted state for sidebar items, when rendered renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given no initially persisted state for sidebar items, when rendered when a parent sidebar item is expanded renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given no initially persisted state for sidebar items, when rendered when a parent sidebar item is expanded when a child of the parent is selected renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given no initially persisted state for sidebar items, when rendered when a parent sidebar item is expanded when a child of the parent is selected when selecting sibling tab renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given state for expanded sidebar items already exists, when rendered renders 1`] = ` +
+ +`; + +exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus given state for expanded unknown sidebar items already exists, when rendered renders without errors 1`] = ` +
+ +`; diff --git a/src/behaviours/cluster/__snapshots__/visibility-of-sidebar-items.test.tsx.snap b/src/behaviours/cluster/__snapshots__/visibility-of-sidebar-items.test.tsx.snap new file mode 100644 index 0000000000000..37a9c3fcbe5b6 --- /dev/null +++ b/src/behaviours/cluster/__snapshots__/visibility-of-sidebar-items.test.tsx.snap @@ -0,0 +1,569 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cluster - visibility of sidebar items given kube resource for route is not allowed renders 1`] = ` +
+ +`; + +exports[`cluster - visibility of sidebar items given kube resource for route is not allowed when kube resource becomes allowed renders 1`] = ` +
+ +`; diff --git a/src/behaviours/cluster/order-of-sidebar-items.test.tsx b/src/behaviours/cluster/order-of-sidebar-items.test.tsx new file mode 100644 index 0000000000000..034b18fd4f78a --- /dev/null +++ b/src/behaviours/cluster/order-of-sidebar-items.test.tsx @@ -0,0 +1,136 @@ +/** + * 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 { fireEvent, RenderResult } from "@testing-library/react"; +import { SidebarItemRegistration, sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; +import { computed } from "mobx"; +import { get, includes, noop } from "lodash/fp"; +import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; + +describe("cluster - order of sidebar items", () => { + let rendered: RenderResult; + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(testSidebarItemsInjectable); + }); + }); + + describe("when rendered", () => { + beforeEach(async () => { + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("has parent items in order", () => { + const actual = rendered + .queryAllByTestId("sidebar-item") + + .filter((element) => + includes(element.dataset.idTest)([ + "some-parent-id", + "some-other-parent-id", + "some-another-parent-id", + ]), + ) + + .map(get("dataset.idTest")); + + expect(actual).toEqual([ + "some-parent-id", + "some-another-parent-id", + "some-other-parent-id", + ]); + }); + + describe("when parent is expanded", () => { + beforeEach(() => { + const parentLink = rendered.getByTestId( + "sidebar-item-link-for-some-parent-id", + ); + + fireEvent.click(parentLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("has child items in order", () => { + const actual = rendered + .queryAllByTestId("sidebar-item") + .filter( + (element) => element.dataset.parentIdTest === "some-parent-id", + ) + .map(get("dataset.idTest")); + + expect(actual).toEqual([ + "some-child-id", + "some-another-child-id", + "some-other-child-id", + ]); + }); + }); + }); +}); + +const testSidebarItemsInjectable = getInjectable({ + id: "some-sidebar-item-injectable", + + instantiate: () => + computed((): SidebarItemRegistration[] => [ + { + id: "some-parent-id", + parentId: null, + title: "Some parent", + onClick: noop, + orderNumber: 42, + }, + { + id: "some-other-parent-id", + parentId: null, + title: "Some other parent", + onClick: noop, + orderNumber: 126, + }, + { + id: "some-another-parent-id", + parentId: null, + title: "Some another parent", + onClick: noop, + orderNumber: 84, + }, + { + id: "some-child-id", + parentId: "some-parent-id", + title: "Some child", + onClick: noop, + orderNumber: 168, + }, + { + id: "some-other-child-id", + parentId: "some-parent-id", + title: "Some other child", + onClick: noop, + orderNumber: 252, + }, + { + id: "some-another-child-id", + parentId: "some-parent-id", + title: "Some another child", + onClick: noop, + orderNumber: 210, + }, + ]), + + injectionToken: sidebarItemsInjectionToken, +}); diff --git a/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx b/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx new file mode 100644 index 0000000000000..3446d8fbd7962 --- /dev/null +++ b/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx @@ -0,0 +1,345 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { DiContainer, getInjectable } from "@ogre-tools/injectable"; +import React from "react"; +import { fireEvent, RenderResult } from "@testing-library/react"; +import directoryForLensLocalStorageInjectable from "../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; +import { SidebarItemRegistration, sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; +import { computed } from "mobx"; +import { noop } from "lodash/fp"; +import routeIsActiveInjectable from "../../renderer/routes/route-is-active.injectable"; +import { routeInjectionToken } from "../../common/front-end-routing/route-injection-token"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; +import pathExistsInjectable from "../../common/fs/path-exists.injectable"; +import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; +import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; + +describe("cluster - sidebar and tab navigation for core", () => { + let applicationBuilder: ApplicationBuilder; + let rendererDi: DiContainer; + let rendered: RenderResult; + + beforeEach(() => { + jest.useFakeTimers(); + + applicationBuilder = getApplicationBuilder(); + rendererDi = applicationBuilder.dis.rendererDi; + + applicationBuilder.setEnvironmentToClusterFrame(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override( + directoryForLensLocalStorageInjectable, + () => "/some-directory-for-lens-local-storage", + ); + }); + }); + + describe("given core registrations", () => { + beforeEach(() => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(testRouteInjectable); + rendererDi.register(testRouteComponentInjectable); + rendererDi.register(testSidebarItemsInjectable); + }); + }); + + describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(({ rendererDi }) => { + const route = rendererDi.inject(testRouteInjectable); + + const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + + navigateToRoute(route); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent is highlighted", () => { + const parent = getSidebarItem(rendered, "some-parent-id"); + + expect(parent.dataset.isActiveTest).toBe("true"); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).toBe(null); + }); + + it("child page is shown", () => { + expect(rendered.getByTestId("some-child-page")).not.toBeNull(); + }); + }); + + describe("given state for expanded sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + sidebar: { + expanded: { "some-parent-id": true }, + width: 200, + }, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem(rendered, "some-parent-id"); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).not.toBe(null); + }); + }); + + describe("given state for expanded unknown sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + sidebar: { + expanded: { "some-unknown-parent-id": true }, + width: 200, + }, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders without errors", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).toBe(null); + }); + }); + + describe("given empty state for expanded sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + someThingButSidebar: {}, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders without errors", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).toBe(null); + }); + }); + + describe("given no initially persisted state for sidebar items, when rendered", () => { + beforeEach(async () => { + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem(rendered, "some-parent-id"); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).toBe(null); + }); + + describe("when a parent sidebar item is expanded", () => { + beforeEach(() => { + const parentLink = rendered.getByTestId( + "sidebar-item-link-for-some-parent-id", + ); + + fireEvent.click(parentLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem(rendered, "some-parent-id"); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is expanded", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child).not.toBe(null); + }); + + describe("when a child of the parent is selected", () => { + beforeEach(() => { + const childLink = rendered.getByTestId( + "sidebar-item-link-for-some-child-id", + ); + + fireEvent.click(childLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent is highlighted", () => { + const parent = getSidebarItem(rendered, "some-parent-id"); + + expect(parent.dataset.isActiveTest).toBe("true"); + }); + + it("child is highlighted", () => { + const child = getSidebarItem(rendered, "some-child-id"); + + expect(child.dataset.isActiveTest).toBe("true"); + }); + + it("child page is shown", () => { + expect(rendered.getByTestId("some-child-page")).not.toBeNull(); + }); + + it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { + jest.advanceTimersByTime(250 - 1); + + const pathExistsFake = rendererDi.inject(pathExistsInjectable); + + const actual = await pathExistsFake( + "/some-directory-for-lens-local-storage/app.json", + ); + + expect(actual).toBe(false); + }); + + it("when enough time passes, stores state for expanded sidebar items to file system", async () => { + jest.advanceTimersByTime(250); + + const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); + + const actual = await readJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + ); + + expect(actual).toEqual({ + sidebar: { + expanded: { "some-parent-id": true }, + width: 200, + }, + }); + }); + }); + }); + }); + }); +}); + +const getSidebarItem = (rendered: RenderResult, itemId: string) => + rendered + .queryAllByTestId("sidebar-item") + .find((x) => x.dataset.idTest === itemId) || null; + +const testSidebarItemsInjectable = getInjectable({ + id: "some-sidebar-items-injectable", + + instantiate: (di) => { + const route = di.inject(testRouteInjectable); + const navigateToRoute = di.inject(navigateToRouteInjectionToken); + const routeIsActive = di.inject(routeIsActiveInjectable, route); + + return computed((): SidebarItemRegistration[] => [ + { + id: "some-parent-id", + parentId: null, + title: "Some parent", + onClick: noop, + getIcon: () =>
, + orderNumber: 42, + }, + + { + id: "some-child-id", + parentId: "some-parent-id", + title: "Some child", + onClick: () => navigateToRoute(route), + isActive: routeIsActive, + orderNumber: 42, + }, + ]); + }, + + injectionToken: sidebarItemsInjectionToken, +}); + +const testRouteInjectable = getInjectable({ + id: "some-route-injectable-id", + + instantiate: () => ({ + path: "/some-child-page", + clusterFrame: true, + isEnabled: computed(() => true), + }), + + injectionToken: routeInjectionToken, +}); + +const testRouteComponentInjectable = getInjectable({ + id: "some-child-page-route-component-injectable", + + instantiate: (di) => ({ + route: di.inject(testRouteInjectable), + Component: () =>
, + }), + + injectionToken: routeSpecificComponentInjectionToken, +}); diff --git a/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx new file mode 100644 index 0000000000000..67aa8ccd80e98 --- /dev/null +++ b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx @@ -0,0 +1,455 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { fireEvent, RenderResult } from "@testing-library/react"; +import { getRendererExtensionFake } from "../../renderer/components/test-utils/get-renderer-extension-fake"; +import type { LensRendererExtension } from "../../extensions/lens-renderer-extension"; +import directoryForLensLocalStorageInjectable from "../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import routesInjectable from "../../renderer/routes/routes.injectable"; +import { matches } from "lodash/fp"; +import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; +import pathExistsInjectable from "../../common/fs/path-exists.injectable"; +import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; +import type { DiContainer } from "@ogre-tools/injectable"; +import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; + +describe("cluster - sidebar and tab navigation for extensions", () => { + let applicationBuilder: ApplicationBuilder; + let rendererDi: DiContainer; + let rendered: RenderResult; + + beforeEach(() => { + jest.useFakeTimers(); + + applicationBuilder = getApplicationBuilder(); + rendererDi = applicationBuilder.dis.rendererDi; + + applicationBuilder.setEnvironmentToClusterFrame(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override( + directoryForLensLocalStorageInjectable, + () => "/some-directory-for-lens-local-storage", + ); + }); + }); + + describe("given extension with cluster pages and cluster page menus", () => { + beforeEach(async () => { + const testExtension = getRendererExtensionFake( + extensionStubWithSidebarItems, + ); + + await applicationBuilder.addExtensions(testExtension); + }); + + describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(({ rendererDi }) => { + const navigateToRoute = rendererDi.inject( + navigateToRouteInjectionToken, + ); + + const route = rendererDi + .inject(routesInjectable) + .get() + .find( + matches({ + path: "/extension/some-extension-id/some-child-page-id", + }), + ); + + navigateToRoute(route); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent is highlighted", () => { + const parent = getSidebarItem( + rendered, + "some-extension-id-some-parent-id", + ); + + expect(parent.dataset.isActiveTest).toBe("true"); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).toBe(null); + }); + + it("child page is shown", () => { + expect(rendered.getByTestId("some-child-page")).not.toBeNull(); + }); + }); + + describe("given state for expanded sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + sidebar: { + expanded: { "some-extension-id-some-parent-id": true }, + width: 200, + }, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem( + rendered, + "some-extension-id-some-parent-id", + ); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).not.toBe(null); + }); + }); + + describe("given state for expanded unknown sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + sidebar: { + expanded: { "some-extension-id-some-unknown-parent-id": true }, + width: 200, + }, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders without errors", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).toBe(null); + }); + }); + + describe("given empty state for expanded sidebar items already exists, when rendered", () => { + beforeEach(async () => { + applicationBuilder.beforeRender(async ({ rendererDi }) => { + const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + + await writeJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + { + someThingButSidebar: {}, + }, + ); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders without errors", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).toBe(null); + }); + }); + + describe("given no initially persisted state for sidebar items, when rendered", () => { + beforeEach(async () => { + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem( + rendered, + "some-extension-id-some-parent-id", + ); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is not expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).toBe(null); + }); + + describe("when a parent sidebar item is expanded", () => { + beforeEach(() => { + const parentLink = rendered.getByTestId( + "sidebar-item-link-for-some-extension-id-some-parent-id", + ); + + fireEvent.click(parentLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent sidebar item is not highlighted", () => { + const parent = getSidebarItem( + rendered, + "some-extension-id-some-parent-id", + ); + + expect(parent.dataset.isActiveTest).toBe("false"); + }); + + it("parent sidebar item is expanded", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child).not.toBe(null); + }); + + describe("when a child of the parent is selected", () => { + beforeEach(() => { + const childLink = rendered.getByTestId( + "sidebar-item-link-for-some-extension-id-some-child-id", + ); + + fireEvent.click(childLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("parent is highlighted", () => { + const parent = getSidebarItem( + rendered, + "some-extension-id-some-parent-id", + ); + + expect(parent.dataset.isActiveTest).toBe("true"); + }); + + it("child is highlighted", () => { + const child = getSidebarItem( + rendered, + "some-extension-id-some-child-id", + ); + + expect(child.dataset.isActiveTest).toBe("true"); + }); + + it("child page is shown", () => { + expect(rendered.getByTestId("some-child-page")).not.toBeNull(); + }); + + it("renders tabs", () => { + expect(rendered.getByTestId("tab-layout")).not.toBeNull(); + }); + + it("tab for child page is active", () => { + const tabLink = rendered.getByTestId( + "tab-link-for-some-extension-id-some-child-id", + ); + + expect(tabLink.dataset.isActiveTest).toBe("true"); + }); + + it("tab for sibling page is not active", () => { + const tabLink = rendered.getByTestId( + "tab-link-for-some-extension-id-some-other-child-id", + ); + + expect(tabLink.dataset.isActiveTest).toBe("false"); + }); + + it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { + jest.advanceTimersByTime(250 - 1); + + const pathExistsFake = rendererDi.inject(pathExistsInjectable); + + const actual = await pathExistsFake( + "/some-directory-for-lens-local-storage/app.json", + ); + + expect(actual).toBe(false); + }); + + it("when enough time passes, stores state for expanded sidebar items to file system", async () => { + jest.advanceTimersByTime(250); + + const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); + + const actual = await readJsonFileFake( + "/some-directory-for-lens-local-storage/app.json", + ); + + expect(actual).toEqual({ + sidebar: { + expanded: { "some-extension-id-some-parent-id": true }, + width: 200, + }, + }); + }); + + describe("when selecting sibling tab", () => { + beforeEach(() => { + const childTabLink = rendered.getByTestId( + "tab-link-for-some-extension-id-some-other-child-id", + ); + + fireEvent.click(childTabLink); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("sibling child page is shown", () => { + expect( + rendered.getByTestId("some-other-child-page"), + ).not.toBeNull(); + }); + + it("tab for sibling page is active", () => { + const tabLink = rendered.getByTestId( + "tab-link-for-some-extension-id-some-other-child-id", + ); + + expect(tabLink.dataset.isActiveTest).toBe("true"); + }); + + it("tab for previous page is not active", () => { + const tabLink = rendered.getByTestId( + "tab-link-for-some-extension-id-some-child-id", + ); + + expect(tabLink.dataset.isActiveTest).toBe("false"); + }); + }); + }); + }); + }); + }); +}); + +const extensionStubWithSidebarItems: Partial = { + id: "some-extension-id", + + clusterPages: [ + { + components: { + Page: () => { + throw new Error("should never come here"); + }, + }, + }, + + { + id: "some-child-page-id", + + components: { + Page: () =>
Some child page
, + }, + }, + + { + id: "some-other-child-page-id", + + components: { + Page: () => ( +
Some other child page
+ ), + }, + }, + ], + + clusterPageMenus: [ + { + id: "some-parent-id", + title: "Parent", + + components: { + Icon: () =>
Some icon
, + }, + }, + + { + id: "some-child-id", + target: { pageId: "some-child-page-id" }, + parentId: "some-parent-id", + title: "Child 1", + + components: { + Icon: null, + }, + }, + + { + id: "some-other-child-id", + target: { pageId: "some-other-child-page-id" }, + parentId: "some-parent-id", + title: "Child 2", + + components: { + Icon: null, + }, + }, + ], +}; + +const getSidebarItem = (rendered: RenderResult, itemId: string) => + rendered + .queryAllByTestId("sidebar-item") + .find((x) => x.dataset.idTest === itemId) || null; diff --git a/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx b/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx new file mode 100644 index 0000000000000..a8d5d9e1361f4 --- /dev/null +++ b/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx @@ -0,0 +1,124 @@ +/** + * 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 { RenderResult } from "@testing-library/react"; +import { SidebarItemRegistration, sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; +import { computed } from "mobx"; +import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; +import React from "react"; +import isAllowedResourceInjectable from "../../common/utils/is-allowed-resource.injectable"; +import { routeInjectionToken } from "../../common/front-end-routing/route-injection-token"; +import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; + +describe("cluster - visibility of sidebar items", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.setEnvironmentToClusterFrame(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(testRouteInjectable); + rendererDi.register(testRouteComponentInjectable); + rendererDi.register(testSidebarItemsInjectable); + }); + }); + + describe("given kube resource for route is not allowed", () => { + beforeEach(async () => { + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("related sidebar item does not exist", () => { + const item = getSidebarItem(rendered, "some-item-id"); + + expect(item).toBeNull(); + }); + + describe("when kube resource becomes allowed", () => { + beforeEach(() => { + applicationBuilder.allowKubeResource("namespaces"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("related sidebar item exists", () => { + const item = getSidebarItem(rendered, "some-item-id"); + + expect(item).not.toBeNull(); + }); + }); + }); +}); + +const getSidebarItem = (rendered: RenderResult, itemId: string) => + rendered + .queryAllByTestId("sidebar-item") + .find((x) => x.dataset.idTest === itemId) || null; + +const testRouteInjectable = getInjectable({ + id: "some-route-injectable-id", + + instantiate: (di) => { + const someKubeResourceName = "namespaces"; + + const kubeResourceIsAllowed = di.inject( + isAllowedResourceInjectable, + someKubeResourceName, + ); + + return { + path: "/some-child-page", + isEnabled: kubeResourceIsAllowed, + clusterFrame: true, + }; + }, + + injectionToken: routeInjectionToken, +}); + +const testRouteComponentInjectable = getInjectable({ + id: "some-child-page-route-component-injectable", + + instantiate: (di) => ({ + route: di.inject(testRouteInjectable), + Component: () =>
, + }), + + injectionToken: routeSpecificComponentInjectionToken, +}); + +const testSidebarItemsInjectable = getInjectable({ + id: "some-sidebar-item-injectable", + + instantiate: (di) => { + const testRoute = di.inject(testRouteInjectable); + const navigateToRoute = di.inject(navigateToRouteInjectionToken); + + return computed((): SidebarItemRegistration[] => [ + { + id: "some-item-id", + parentId: null, + title: "Some item", + onClick: () => navigateToRoute(testRoute), + isVisible: testRoute.isEnabled, + orderNumber: 42, + }, + ]); + }, + + injectionToken: sidebarItemsInjectionToken, +}); + diff --git a/src/behaviours/extension-special-characters-in-page-registrations.test.tsx b/src/behaviours/extension-special-characters-in-page-registrations.test.tsx new file mode 100644 index 0000000000000..062200cd311a0 --- /dev/null +++ b/src/behaviours/extension-special-characters-in-page-registrations.test.tsx @@ -0,0 +1,61 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getRendererExtensionFake, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake"; +import React from "react"; +import type { RenderResult } from "@testing-library/react"; +import currentPathInjectable from "../renderer/routes/current-path.injectable"; +import type { LensRendererExtension } from "../extensions/lens-renderer-extension"; +import { ApplicationBuilder, getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; + +describe("extension special characters in page registrations", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + let testExtension: TestExtension; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder(); + + testExtension = getRendererExtensionFake( + extensionWithPagesHavingSpecialCharacters, + ); + + await applicationBuilder.addExtensions(testExtension); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when navigating to route with ID having special characters", () => { + beforeEach(() => { + testExtension.navigate("/some-page-id/"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("knows URL", () => { + const currentPath = applicationBuilder.dis.rendererDi.inject(currentPathInjectable); + + expect(currentPath.get()).toBe("/extension/some-extension-id--/some-page-id"); + }); + }); +}); + +const extensionWithPagesHavingSpecialCharacters: Partial = { + id: "@some-extension-id/", + + globalPages: [ + { + id: "/some-page-id/", + components: { + Page: () =>
Some page
, + }, + }, + ], +}; diff --git a/src/behaviours/extensions/__snapshots__/navigation-using-application-menu.test.ts.snap b/src/behaviours/extensions/__snapshots__/navigation-using-application-menu.test.ts.snap new file mode 100644 index 0000000000000..a60732c10150c --- /dev/null +++ b/src/behaviours/extensions/__snapshots__/navigation-using-application-menu.test.ts.snap @@ -0,0 +1,123 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`extensions - navigation using application menu renders 1`] = `
`; + +exports[`extensions - navigation using application menu when navigating to extensions using application menu renders 1`] = ` +
+
+
+
+
+

+ Extensions +

+
+

+ Add new features via Lens Extensions. + + Check out + + docs + + + and list of + + available extensions + + . +

+
+
+
+ Name or file path or URL to an extension package (tar, tgz) + +
+
+
+
+ +
+
+ + + Pro-Tip + + : you can drag-n-drop tarball-file to this area + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/extensions/navigation-using-application-menu.test.ts b/src/behaviours/extensions/navigation-using-application-menu.test.ts new file mode 100644 index 0000000000000..31fe918b20022 --- /dev/null +++ b/src/behaviours/extensions/navigation-using-application-menu.test.ts @@ -0,0 +1,66 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import isAutoUpdateEnabledInjectable from "../../main/is-auto-update-enabled.injectable"; +import extensionsStoreInjectable from "../../extensions/extensions-store/extensions-store.injectable"; +import type { ExtensionsStore } from "../../extensions/extensions-store/extensions-store"; +import fileSystemProvisionerStoreInjectable from "../../extensions/extension-loader/create-extension-instance/file-system-provisioner-store/file-system-provisioner-store.injectable"; +import type { FileSystemProvisionerStore } from "../../extensions/extension-loader/create-extension-instance/file-system-provisioner-store/file-system-provisioner-store"; +import focusWindowInjectable from "../../renderer/ipc-channel-listeners/focus-window.injectable"; + +// TODO: Make components free of side effects by making them deterministic +jest.mock("../../renderer/components/input/input"); + +describe("extensions - navigation using application menu", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + let focusWindowMock: jest.Mock; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder().beforeSetups(({ mainDi, rendererDi }) => { + mainDi.override(isAutoUpdateEnabledInjectable, () => () => false); + rendererDi.override(extensionsStoreInjectable, () => ({}) as unknown as ExtensionsStore); + rendererDi.override(fileSystemProvisionerStoreInjectable, () => ({}) as unknown as FileSystemProvisionerStore); + + focusWindowMock = jest.fn(); + + rendererDi.override(focusWindowInjectable, () => focusWindowMock); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show extensions page yet", () => { + const actual = rendered.queryByTestId("extensions-page"); + + expect(actual).toBeNull(); + }); + + describe("when navigating to extensions using application menu", () => { + beforeEach(() => { + applicationBuilder.applicationMenu.click("root.extensions"); + }); + + it("focuses the window", () => { + expect(focusWindowMock).toHaveBeenCalled(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows extensions page", () => { + const actual = rendered.getByTestId("extensions-page"); + + expect(actual).not.toBeNull(); + }); + }); +}); diff --git a/src/behaviours/navigate-to-extension-page.test.tsx b/src/behaviours/navigate-to-extension-page.test.tsx new file mode 100644 index 0000000000000..eb034defdf7af --- /dev/null +++ b/src/behaviours/navigate-to-extension-page.test.tsx @@ -0,0 +1,185 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getRendererExtensionFake, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake"; +import React from "react"; +import { fireEvent, RenderResult } from "@testing-library/react"; +import isEmpty from "lodash/isEmpty"; +import queryParametersInjectable from "../renderer/routes/query-parameters.injectable"; +import currentPathInjectable from "../renderer/routes/current-path.injectable"; +import type { IComputedValue } from "mobx"; +import type { LensRendererExtension } from "../extensions/lens-renderer-extension"; +import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; + +describe("navigate to extension page", () => { + let rendered: RenderResult; + let testExtension: TestExtension; + let queryParameters: IComputedValue; + let currentPath: IComputedValue; + + beforeEach(async () => { + const applicationBuilder = getApplicationBuilder(); + + testExtension = getRendererExtensionFake( + extensionWithPagesHavingParameters, + ); + + await applicationBuilder.addExtensions(testExtension); + + rendered = await applicationBuilder.render(); + + const rendererDi = applicationBuilder.dis.rendererDi; + + queryParameters = rendererDi.inject(queryParametersInjectable); + currentPath = rendererDi.inject(currentPathInjectable); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when extension navigates to route without parameters", () => { + beforeEach(() => { + testExtension.navigate(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("URL is correct", () => { + expect(currentPath.get()).toBe("/extension/some-extension-id"); + }); + + it("query parameters is empty", () => { + expect(queryParameters.get()).toEqual({}); + }); + + describe("when changing page parameters", () => { + beforeEach(() => { + const button = rendered.getByTestId("button-to-change-page-parameters"); + + fireEvent.click(button); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("URL is correct", () => { + expect(currentPath.get()).toBe("/extension/some-extension-id"); + }); + + it("knows query parameters", () => { + expect(queryParameters.get()).toEqual({ + someStringParameter: "some-changed-string-value", + someNumberParameter: "84", + someArrayParameter: + "some-changed-array-value,some-other-changed-array-value", + }); + }); + }); + }); + + describe("when extension navigates to route with parameters", () => { + beforeEach(() => { + testExtension.navigate(undefined, { + someStringParameter: "some-string-value-from-navigate", + someNumberParameter: 126, + someArrayParameter: ["some-array-value-from-navigate"], + }); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("URL is correct", () => { + expect(currentPath.get()).toBe("/extension/some-extension-id"); + }); + + it("knows query parameters", () => { + expect(queryParameters.get()).toEqual({ + someStringParameter: "some-string-value-from-navigate", + someNumberParameter: "126", + someArrayParameter: "some-array-value-from-navigate", + }); + }); + }); + + describe("when extension navigates to child route", () => { + beforeEach(() => { + testExtension.navigate("some-child-page-id"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("URL is correct", () => { + expect(currentPath.get()).toBe("/extension/some-extension-id/some-child-page-id"); + }); + }); +}); + +const extensionWithPagesHavingParameters: Partial = { + id: "some-extension-id", + + globalPages: [ + { + components: { + Page: ({ params }) => ( +
+
    +
  • {params.someStringParameter.get()}
  • +
  • {params.someNumberParameter.get()}
  • +
  • {params.someArrayParameter.get().join(",")}
  • +
+ + +
+ ), + }, + + params: { + someStringParameter: "some-string-value", + + someNumberParameter: { + defaultValue: 42, + + stringify: (value) => value.toString(), + + parse: (value) => (value ? Number(value) : undefined), + }, + + someArrayParameter: { + defaultValue: ["some-array-value", "some-other-array-value"], + + stringify: (value) => value.join(","), + + parse: (value: string[]) => (!isEmpty(value) ? value : undefined), + }, + }, + }, + { + id: "some-child-page-id", + components: { + Page: () =>
Child page
, + }, + }, + ], +}; diff --git a/src/behaviours/navigating-between-routes.test.tsx b/src/behaviours/navigating-between-routes.test.tsx new file mode 100644 index 0000000000000..152830e4636d1 --- /dev/null +++ b/src/behaviours/navigating-between-routes.test.tsx @@ -0,0 +1,241 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { DiContainer, getInjectable } from "@ogre-tools/injectable"; +import React from "react"; +import { computed } from "mobx"; +import type { RenderResult } from "@testing-library/react"; +import { routeSpecificComponentInjectionToken } from "../renderer/routes/route-specific-component-injection-token"; +import { observer } from "mobx-react"; +import { Route, routeInjectionToken } from "../common/front-end-routing/route-injection-token"; +import type { ApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import currentRouteInjectable from "../renderer/routes/current-route.injectable"; +import currentPathInjectable from "../renderer/routes/current-path.injectable"; +import queryParametersInjectable from "../renderer/routes/query-parameters.injectable"; +import currentPathParametersInjectable from "../renderer/routes/current-path-parameters.injectable"; +import { navigateToRouteInjectionToken } from "../common/front-end-routing/navigate-to-route-injection-token"; + +describe("navigating between routes", () => { + let rendererDi: DiContainer; + let rendered: RenderResult; + let applicationBuilder: ApplicationBuilder; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder(); + rendererDi = applicationBuilder.dis.rendererDi; + }); + + describe("given route without path parameters", () => { + beforeEach(async () => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(testRouteWithoutPathParametersInjectable); + rendererDi.register(testRouteWithoutPathParametersComponentInjectable); + }); + + rendered = await applicationBuilder.render(); + }); + + describe("when navigating to route", () => { + let route: Route; + + beforeEach(() => { + const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + + route = rendererDi.inject(testRouteWithoutPathParametersInjectable); + + navigateToRoute(route); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("knows current route", () => { + const currentRoute = rendererDi.inject(currentRouteInjectable); + + expect(currentRoute.get()).toBe(route); + }); + + it("knows current path", () => { + const currentPath = rendererDi.inject(currentPathInjectable); + + expect(currentPath.get()).toBe("/some-path"); + }); + + it("does not have query parameters", () => { + const queryParameters = rendererDi.inject(queryParametersInjectable); + + expect(queryParameters.get()).toEqual({}); + }); + + it("does not have path parameters", () => { + const pathParameters = rendererDi.inject(currentPathParametersInjectable); + + expect(pathParameters.get()).toEqual({}); + }); + }); + + it("when navigating to route with query parameters, knows query parameters", () => { + const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const queryParameters = rendererDi.inject(queryParametersInjectable); + + const route = rendererDi.inject(testRouteWithoutPathParametersInjectable); + + navigateToRoute(route, { + query: { + someParameter: "some-value", + someOtherParameter: "some-other-value", + }, + }); + + expect(queryParameters.get()).toEqual({ + someParameter: "some-value", + someOtherParameter: "some-other-value", + }); + }); + }); + + describe("given route with optional path parameters", () => { + beforeEach(async () => { + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(routeWithOptionalPathParametersInjectable); + rendererDi.register(routeWithOptionalPathParametersComponentInjectable); + }); + + + rendered = await applicationBuilder.render(); + }); + + describe("when navigating to route with path parameters", () => { + let route: Route; + + beforeEach(() => { + route = rendererDi.inject(routeWithOptionalPathParametersInjectable); + + const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + + navigateToRoute(route, { + parameters: { + someParameter: "some-value", + someOtherParameter: "some-other-value", + }, + }); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("knows current route", () => { + const currentRoute = rendererDi.inject(currentRouteInjectable); + + expect(currentRoute.get()).toBe(route); + }); + + it("knows current path", () => { + const currentPath = rendererDi.inject(currentPathInjectable); + + expect(currentPath.get()).toBe( + "/some-path/some-value/some-other-value", + ); + }); + + it("knows path parameters", () => { + const pathParameters = rendererDi.inject(currentPathParametersInjectable); + + expect(pathParameters.get()).toEqual({ + someParameter: "some-value", + someOtherParameter: "some-other-value", + }); + }); + }); + + describe("when navigating to route without path parameters", () => { + let route: Route; + + beforeEach(() => { + route = rendererDi.inject(routeWithOptionalPathParametersInjectable); + + const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + + navigateToRoute(route); + }); + + it("knows current route", () => { + const currentRoute = rendererDi.inject(currentRouteInjectable); + + expect(currentRoute.get()).toBe(route); + }); + + it("knows current path", () => { + const currentPath = rendererDi.inject(currentPathInjectable); + + expect(currentPath.get()).toBe("/some-path"); + }); + + it("knows path parameters", () => { + const pathParameters = rendererDi.inject(currentPathParametersInjectable); + + expect(pathParameters.get()).toEqual({ + someParameter: undefined, + someOtherParameter: undefined, + }); + }); + }); + }); +}); + +const testRouteWithoutPathParametersInjectable = getInjectable({ + id: "some-route", + injectionToken: routeInjectionToken, + + instantiate: () => ({ + path: "/some-path", + clusterFrame: false, + isEnabled: computed(() => true), + }), +}); + +const testRouteWithoutPathParametersComponentInjectable = getInjectable({ + id: "some-route-component", + + instantiate: (di) => ({ + route: di.inject(testRouteWithoutPathParametersInjectable), + Component: () =>
Some component
, + }), + + injectionToken: routeSpecificComponentInjectionToken, +}); + +const routeWithOptionalPathParametersInjectable = getInjectable({ + id: "some-route", + injectionToken: routeInjectionToken, + + instantiate: (): Route<{ someParameter?: string; someOtherParameter?: string }> => ({ + path: "/some-path/:someParameter?/:someOtherParameter?", + clusterFrame: false, + isEnabled: computed(() => true), + }), +}); + +const routeWithOptionalPathParametersComponentInjectable = getInjectable({ + id: "some-route-component", + + instantiate: (di) => { + const pathParameters = di.inject(currentPathParametersInjectable); + + return { + route: di.inject(routeWithOptionalPathParametersInjectable), + + Component: observer(() => ( +
{JSON.stringify(pathParameters.get(), null, 2)}
+ )), + }; + }, + + injectionToken: routeSpecificComponentInjectionToken, +}); + diff --git a/src/behaviours/preferences/__snapshots__/closing-preferences.test.tsx.snap b/src/behaviours/preferences/__snapshots__/closing-preferences.test.tsx.snap new file mode 100644 index 0000000000000..2fc1f4410f980 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/closing-preferences.test.tsx.snap @@ -0,0 +1,1591 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - closing-preferences given accessing preferences directly renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - closing-preferences given accessing preferences directly when navigating to a tab in preferences renders 1`] = ` +
+
+ +
+
+ Some test page +
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - closing-preferences given accessing preferences directly when navigating to a tab in preferences when preferences are closed renders 1`] = ` +
+
+ Some front page +
+
+`; + +exports[`preferences - closing-preferences given accessing preferences directly when preferences are closed renders 1`] = ` +
+
+ Some front page +
+
+`; + +exports[`preferences - closing-preferences given already in a page and then navigated to preferences renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - closing-preferences given already in a page and then navigated to preferences when navigating to a tab in preferences renders 1`] = ` +
+
+ +
+
+ Some test page +
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - closing-preferences given already in a page and then navigated to preferences when navigating to a tab in preferences when preferences are closed renders 1`] = ` +
+
+ +
+
+ Some test page +
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - closing-preferences given already in a page and then navigated to preferences when preferences are closed renders 1`] = ` +
+
+ +
+
+ Some test page +
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-application-preferences.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-to-application-preferences.test.ts.snap new file mode 100644 index 0000000000000..bb431f6c98814 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-application-preferences.test.ts.snap @@ -0,0 +1,696 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to application preferences given in some child page of preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+
+

+ Proxy +

+
+ HTTP Proxy + +
+
+ +
+
+ + Proxy is used only for non-cluster communication. + +
+
+
+
+ Certificate Trust + +
+ + + This will make Lens to trust ANY certificate authority without any validations. + + Needed with some corporate proxies that do certificate re-writing. + + Does not affect cluster communications! + +
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to application preferences given in some child page of preferences, when rendered when navigating to application preferences using navigation renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-editor-preferences.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-to-editor-preferences.test.ts.snap new file mode 100644 index 0000000000000..db63d5659aba9 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-editor-preferences.test.ts.snap @@ -0,0 +1,886 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to editor preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to editor preferences given in preferences, when rendered when navigating to editor preferences using navigation renders 1`] = ` +
+
+ +
+
+
+

+ Editor configuration +

+
+ Minimap + +
+
+
+
+ +
+
+
+ Position +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ Line numbers + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+ Tab size + +
+
+ +
+
+
+
+
+ Font size + +
+
+ +
+
+
+
+
+ Font family + +
+
+ +
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-extension-specific-preferences.test.tsx.snap b/src/behaviours/preferences/__snapshots__/navigation-to-extension-specific-preferences.test.tsx.snap new file mode 100644 index 0000000000000..c2d0584210b2e --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-extension-specific-preferences.test.tsx.snap @@ -0,0 +1,1175 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to extension specific preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to extension specific preferences given in preferences, when rendered when extension with specific preferences is enabled renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +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 renders 1`] = ` +
+
+ +
+
+
+

+ Extensions +

+
+
+ Some preference item + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-kubernetes-preferences.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-to-kubernetes-preferences.test.ts.snap new file mode 100644 index 0000000000000..92d486807dd08 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-kubernetes-preferences.test.ts.snap @@ -0,0 +1,917 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to kubernetes preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to kubernetes preferences given in preferences, when rendered when navigating to kubernetes preferences using navigation renders 1`] = ` +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+
+
+
+ Download mirror for kubectl +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+
+
+
+ Repositories +
+
+
+ +
+
+
+
+
+ + +
+
+
+ +
+
+
+
+ The repositories have not been added yet +
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-proxy-preferences.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-to-proxy-preferences.test.ts.snap new file mode 100644 index 0000000000000..e5341cc6356c8 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-proxy-preferences.test.ts.snap @@ -0,0 +1,696 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to proxy preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to proxy preferences given in preferences, when rendered when navigating to proxy preferences using navigation renders 1`] = ` +
+
+ +
+
+
+
+

+ Proxy +

+
+ HTTP Proxy + +
+
+ +
+
+ + Proxy is used only for non-cluster communication. + +
+
+
+
+ Certificate Trust + +
+ + + This will make Lens to trust ANY certificate authority without any validations. + + Needed with some corporate proxies that do certificate re-writing. + + Does not affect cluster communications! + +
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-telemetry-preferences.test.tsx.snap b/src/behaviours/preferences/__snapshots__/navigation-to-telemetry-preferences.test.tsx.snap new file mode 100644 index 0000000000000..afe1e3f114cae --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-telemetry-preferences.test.tsx.snap @@ -0,0 +1,1500 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to telemetry preferences given URL for Sentry DNS, when navigating to preferences when navigating to telemetry preferences renders 1`] = ` +
+
+ +
+
+
+

+ Telemetry +

+
+
+ Automatic Error Reporting + +
+ +
+ + Automatic error reports provide vital information about issues and application crashes. It is highly recommended to keep this feature enabled to ensure fast turnaround for issues you might encounter. + +
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to telemetry preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to telemetry preferences given in preferences, when rendered when extension with telemetry preference items gets enabled renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to telemetry preferences given in preferences, when rendered when extension with telemetry preference items gets enabled when clicking link to telemetry preferences from navigation renders 1`] = ` +
+
+ +
+
+
+

+ Telemetry +

+
+
+ Some telemetry-preference item + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to telemetry preferences given no URL for Sentry DNS, when navigating to telemetry preferences renders 1`] = ` +
+
+ +
+
+
+

+ Telemetry +

+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-to-terminal-preferences.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-to-terminal-preferences.test.ts.snap new file mode 100644 index 0000000000000..aa687a8a7b07a --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-to-terminal-preferences.test.ts.snap @@ -0,0 +1,805 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation to terminal preferences given in preferences, when rendered renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; + +exports[`preferences - navigation to terminal preferences given in preferences, when rendered when navigating to terminal preferences using navigation renders 1`] = ` +
+
+ +
+
+
+

+ Terminal +

+
+
+ Terminal Shell Path + +
+
+ +
+
+
+
+
+ Terminal copy & paste + +
+ +
+
+
+ Terminal theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+ Font size + +
+
+ +
+
+
+
+
+ Font family + +
+
+ +
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/__snapshots__/navigation-using-application-menu.test.ts.snap b/src/behaviours/preferences/__snapshots__/navigation-using-application-menu.test.ts.snap new file mode 100644 index 0000000000000..eb8782e28c635 --- /dev/null +++ b/src/behaviours/preferences/__snapshots__/navigation-using-application-menu.test.ts.snap @@ -0,0 +1,498 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preferences - navigation using application menu renders 1`] = `
`; + +exports[`preferences - navigation using application menu when navigating to preferences using application menu renders 1`] = ` +
+
+ +
+
+
+

+ Application +

+
+
+ Theme + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Extension Install Registry + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+

+ This setting is to change the registry URL for installing extensions by name. + + If you are unable to access the default registry ( + https://registry.npmjs.org + ) + + you can change it in your + + .npmrc + +  file or in the input below. +

+
+ +
+
+
+
+
+
+ Start-up + +
+ +
+
+
+
+ Update Channel + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+ Locale Timezone + +
+
+
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+`; diff --git a/src/behaviours/preferences/closing-preferences.test.tsx b/src/behaviours/preferences/closing-preferences.test.tsx new file mode 100644 index 0000000000000..34a44029ca9bb --- /dev/null +++ b/src/behaviours/preferences/closing-preferences.test.tsx @@ -0,0 +1,273 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { DiContainer, getInjectable } from "@ogre-tools/injectable"; +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import currentPathInjectable from "../../renderer/routes/current-path.injectable"; +import { routeInjectionToken } from "../../common/front-end-routing/route-injection-token"; +import { computed } from "mobx"; +import type { UserStore } from "../../common/user-store"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import { preferenceNavigationItemInjectionToken } from "../../renderer/components/+preferences/preferences-navigation/preference-navigation-items.injectable"; +import routeIsActiveInjectable from "../../renderer/routes/route-is-active.injectable"; +import { Preferences } from "../../renderer/components/+preferences"; +import React from "react"; +import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; +import observableHistoryInjectable from "../../renderer/navigation/observable-history.injectable"; +import { searchParamsOptions } from "../../renderer/navigation"; +import { createMemoryHistory } from "history"; +import { createObservableHistory } from "mobx-observable-history"; +import navigateToPreferenceTabInjectable from "../../renderer/components/+preferences/preferences-navigation/navigate-to-preference-tab.injectable"; +import navigateToFrontPageInjectable from "../../common/front-end-routing/navigate-to-front-page.injectable"; +import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; + +describe("preferences - closing-preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.register(testPreferencesRouteInjectable); + rendererDi.register(testPreferencesRouteComponentInjectable); + rendererDi.register(testFrontPageRouteInjectable); + rendererDi.register(testFrontPageRouteComponentInjectable); + rendererDi.register(testNavigationItemInjectable); + + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = { themeOptions: [] } as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + + rendererDi.override(navigateToFrontPageInjectable, (di) => { + const navigateToRoute = di.inject(navigateToRouteInjectionToken); + const testFrontPage = di.inject(testFrontPageRouteInjectable); + + return () => { + navigateToRoute(testFrontPage); + }; + }); + }); + }); + + describe("given already in a page and then navigated to preferences", () => { + let rendered: RenderResult; + let rendererDi: DiContainer; + + beforeEach(async () => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override(observableHistoryInjectable, () => { + const historyFake = createMemoryHistory({ + initialEntries: ["/some-test-path"], + initialIndex: 0, + }); + + return createObservableHistory(historyFake, { + searchParams: searchParamsOptions, + }); + }); + }); + + rendered = await applicationBuilder.render(); + rendererDi = applicationBuilder.dis.rendererDi; + + applicationBuilder.preferences.navigate(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when preferences are closed", () => { + beforeEach(() => { + applicationBuilder.preferences.close(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("navigates back to the original page", () => { + const currentPath = rendererDi.inject(currentPathInjectable).get(); + + expect(currentPath).toBe("/some-test-path"); + }); + }); + + describe("when navigating to a tab in preferences", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click( + "some-test-preference-navigation-item-id", + ); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when preferences are closed", () => { + beforeEach(() => { + applicationBuilder.preferences.close(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("navigates back to the original page", () => { + const currentPath = rendererDi.inject(currentPathInjectable).get(); + + expect(currentPath).toBe("/some-test-path"); + }); + }); + }); + }); + + describe("given accessing preferences directly", () => { + let rendered: RenderResult; + let rendererDi: DiContainer; + + beforeEach(async () => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override(observableHistoryInjectable, () => { + const historyFake = createMemoryHistory({ + initialEntries: ["/preferences/app"], + initialIndex: 0, + }); + + return createObservableHistory(historyFake, { + searchParams: searchParamsOptions, + }); + }); + }); + + rendered = await applicationBuilder.render(); + + rendererDi = applicationBuilder.dis.rendererDi; + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when preferences are closed", () => { + beforeEach(() => { + applicationBuilder.preferences.close(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("navigates back to the front page", () => { + const currentPath = rendererDi.inject(currentPathInjectable).get(); + + expect(currentPath).toBe("/some-front-page"); + }); + }); + + describe("when navigating to a tab in preferences", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click( + "some-test-preference-navigation-item-id", + ); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + describe("when preferences are closed", () => { + beforeEach(() => { + applicationBuilder.preferences.close(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("navigates back to the front page", () => { + const currentPath = rendererDi.inject(currentPathInjectable).get(); + + expect(currentPath).toBe("/some-front-page"); + }); + }); + }); + }); +}); + +const testPreferencesRouteInjectable = getInjectable({ + id: "test-preferences-route", + + instantiate: () => ({ + path: "/some-test-path", + clusterFrame: false, + isEnabled: computed(() => true), + }), + + injectionToken: routeInjectionToken, +}); + +const testPreferencesRouteComponentInjectable = getInjectable({ + id: "test-route-component", + + instantiate: (di) => ({ + route: di.inject(testPreferencesRouteInjectable), + Component: () => Some test page, + }), + + injectionToken: routeSpecificComponentInjectionToken, +}); + +const testFrontPageRouteInjectable = getInjectable({ + id: "test-front-page-route", + + instantiate: () => ({ + path: "/some-front-page", + clusterFrame: false, + isEnabled: computed(() => true), + }), + + injectionToken: routeInjectionToken, +}); + +const testFrontPageRouteComponentInjectable = getInjectable({ + id: "test-front-page-route-component", + + instantiate: (di) => ({ + route: di.inject(testFrontPageRouteInjectable), + Component: () =>
Some front page
, + }), + + injectionToken: routeSpecificComponentInjectionToken, +}); + +const testNavigationItemInjectable = getInjectable({ + id: "some-test-preference-navigation-item-id", + + instantiate: (di) => { + const testRoute = di.inject(testPreferencesRouteInjectable); + const navigateToPreferenceTab = di.inject(navigateToPreferenceTabInjectable); + const routeIsActive = di.inject(routeIsActiveInjectable, testRoute); + + return { + id: "some-test-preference-navigation-item-id", + label: "Some preference navigation item", + isActive: routeIsActive, + isVisible: testRoute.isEnabled, + navigate: navigateToPreferenceTab(testRoute), + orderNumber: 100, + }; + }, + + injectionToken: preferenceNavigationItemInjectionToken, +}); diff --git a/src/behaviours/preferences/navigation-to-application-preferences.test.ts b/src/behaviours/preferences/navigation-to-application-preferences.test.ts new file mode 100644 index 0000000000000..61825e678717b --- /dev/null +++ b/src/behaviours/preferences/navigation-to-application-preferences.test.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import navigateToProxyPreferencesInjectable + from "../../common/front-end-routing/routes/preferences/proxy/navigate-to-proxy-preferences.injectable"; + +describe("preferences - navigation to application preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in some child page of preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(({ rendererDi }) => { + const navigateToProxyPreferences = rendererDi.inject(navigateToProxyPreferencesInjectable); + + navigateToProxyPreferences(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show application preferences yet", () => { + const page = rendered.queryByTestId("application-preferences-page"); + + expect(page).toBeNull(); + }); + + describe("when navigating to application preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("application"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows application preferences", () => { + const page = rendered.getByTestId("application-preferences-page"); + + expect(page).not.toBeNull(); + }); + }); + }); +}); diff --git a/src/behaviours/preferences/navigation-to-editor-preferences.test.ts b/src/behaviours/preferences/navigation-to-editor-preferences.test.ts new file mode 100644 index 0000000000000..6d1b1536e44d8 --- /dev/null +++ b/src/behaviours/preferences/navigation-to-editor-preferences.test.ts @@ -0,0 +1,69 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; + +describe("preferences - navigation to editor preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + editorConfiguration: { minimap: {}, tabSize: 42, fontSize: 42 }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show editor preferences yet", () => { + const page = rendered.queryByTestId("editor-preferences-page"); + + expect(page).toBeNull(); + }); + + describe("when navigating to editor preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("editor"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows editor preferences", () => { + const page = rendered.getByTestId("editor-preferences-page"); + + expect(page).not.toBeNull(); + }); + }); + }); +}); diff --git a/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx b/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx new file mode 100644 index 0000000000000..406efab93d821 --- /dev/null +++ b/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx @@ -0,0 +1,135 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import type { LensRendererExtension } from "../../extensions/lens-renderer-extension"; +import React from "react"; +import { getRendererExtensionFake } from "../../renderer/components/test-utils/get-renderer-extension-fake"; + +describe("preferences - navigation to extension specific preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = { themeOptions: [] } as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show extension preferences yet", () => { + const page = rendered.queryByTestId("extension-preferences-page"); + + expect(page).toBeNull(); + }); + + it("does not show link for extension preferences", () => { + const actual = rendered.queryByTestId("tab-link-for-extensions"); + + expect(actual).toBeNull(); + }); + + describe("when extension with specific preferences is enabled", () => { + beforeEach(() => { + const testExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems); + + applicationBuilder.addExtensions(testExtension); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows link for extension preferences", () => { + const actual = rendered.getByTestId("tab-link-for-extensions"); + + expect(actual).not.toBeNull(); + }); + + describe("when navigating to extension preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("extensions"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows extension specific preferences", () => { + const page = rendered.getByTestId("extension-preferences-page"); + + expect(page).not.toBeNull(); + }); + + it("shows extension specific preference item", () => { + const actual = rendered.getByTestId("extension-preference-item-for-some-preference-item-id"); + + expect(actual).not.toBeNull(); + }); + + it("does not show unrelated preference tab items", () => { + const actual = rendered.queryByTestId("extension-preference-item-for-some-unrelated-preference-item-id"); + + expect(actual).toBeNull(); + }); + }); + }); + }); +}); + +const extensionStubWithExtensionSpecificPreferenceItems: Partial = { + id: "some-test-extension-id", + + appPreferences: [ + { + title: "Some preference item", + id: "some-preference-item-id", + + components: { + Hint: () =>
, + Input: () =>
, + }, + }, + + { + title: "irrelevant", + id: "some-unrelated-preference-item-id", + showInPreferencesTab: "some-tab", + + components: { + Hint: () =>
, + Input: () =>
, + }, + }, + ], +}; + diff --git a/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts b/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts new file mode 100644 index 0000000000000..028689e56827d --- /dev/null +++ b/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts @@ -0,0 +1,70 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import { observable } from "mobx"; + +describe("preferences - navigation to kubernetes preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + syncKubeconfigEntries: observable.map(), + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show kubernetes preferences yet", () => { + const page = rendered.queryByTestId("kubernetes-preferences-page"); + + expect(page).toBeNull(); + }); + + describe("when navigating to kubernetes preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("kubernetes"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows kubernetes preferences", () => { + const page = rendered.getByTestId("kubernetes-preferences-page"); + + expect(page).not.toBeNull(); + }); + }); + }); +}); diff --git a/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts b/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts new file mode 100644 index 0000000000000..2c76212910c94 --- /dev/null +++ b/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts @@ -0,0 +1,68 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; + +describe("preferences - navigation to proxy preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show proxy preferences yet", () => { + const page = rendered.queryByTestId("proxy-preferences-page"); + + expect(page).toBeNull(); + }); + + describe("when navigating to proxy preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("proxy"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows proxy preferences", () => { + const page = rendered.getByTestId("proxy-preferences-page"); + + expect(page).not.toBeNull(); + }); + }); + }); +}); diff --git a/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx b/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx new file mode 100644 index 0000000000000..96919b1679ba0 --- /dev/null +++ b/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx @@ -0,0 +1,202 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import React from "react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { getRendererExtensionFake } from "../../renderer/components/test-utils/get-renderer-extension-fake"; +import type { UserStore } from "../../common/user-store"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import navigateToTelemetryPreferencesInjectable from "../../common/front-end-routing/routes/preferences/telemetry/navigate-to-telemetry-preferences.injectable"; +import sentryDnsUrlInjectable from "../../renderer/components/+preferences/sentry-dns-url.injectable"; + +describe("preferences - navigation to telemetry preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = { themeOptions: [] } as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show telemetry preferences yet", () => { + const page = rendered.queryByTestId("telemetry-preferences-page"); + + expect(page).toBeNull(); + }); + + it("does not show link for telemetry preferences", () => { + const actual = rendered.queryByTestId("tab-link-for-telemetry"); + + expect(actual).toBeNull(); + }); + + describe("when extension with telemetry preference items gets enabled", () => { + beforeEach(() => { + const testExtensionWithTelemetryPreferenceItems = + getRendererExtensionFake(extensionStubWithTelemetryPreferenceItems); + + applicationBuilder.addExtensions( + testExtensionWithTelemetryPreferenceItems, + ); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows link for telemetry preferences", () => { + const actual = rendered.getByTestId("tab-link-for-telemetry"); + + expect(actual).not.toBeNull(); + }); + + describe("when clicking link to telemetry preferences from navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("telemetry"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows telemetry preferences", () => { + const page = rendered.getByTestId("telemetry-preferences-page"); + + expect(page).not.toBeNull(); + }); + + it("shows extension telemetry preference items", () => { + const actual = rendered.getByTestId( + "telemetry-preference-item-for-some-telemetry-preference-item-id", + ); + + expect(actual).not.toBeNull(); + }); + }); + }); + + it("given extensions but no telemetry preference items, does not show link for telemetry preferences", () => { + const testExtensionWithTelemetryPreferenceItems = + getRendererExtensionFake({ + id: "some-test-extension-id", + appPreferences: [ + { + title: "irrelevant", + id: "irrelevant", + showInPreferencesTab: "not-telemetry", + components: { Hint: () =>
, Input: () =>
}, + }, + ], + }); + + applicationBuilder.addExtensions( + testExtensionWithTelemetryPreferenceItems, + ); + + const actual = rendered.queryByTestId("tab-link-for-telemetry"); + + expect(actual).toBeNull(); + }); + }); + + describe("given URL for Sentry DNS, when navigating to preferences", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override(sentryDnsUrlInjectable, () => "some-sentry-dns-url"); + }); + + rendered = await applicationBuilder.render(); + + applicationBuilder.preferences.navigate(); + }); + + describe("when navigating to telemetry preferences", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("telemetry"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("allows configuration of automatic error reporting", () => { + const actual = rendered.getByTestId("telemetry-preferences-for-automatic-error-reporting"); + + expect(actual).not.toBeNull(); + }); + }); + }); + + describe("given no URL for Sentry DNS, when navigating to telemetry preferences", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeSetups(({ rendererDi }) => { + rendererDi.override(sentryDnsUrlInjectable, () => null); + }); + + rendered = await applicationBuilder.render(); + + const navigateToTelemetryPreferences = applicationBuilder.dis.rendererDi.inject(navigateToTelemetryPreferencesInjectable); + + navigateToTelemetryPreferences(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not allow configuration of automatic error reporting", () => { + const actual = rendered.queryByTestId("telemetry-preferences-for-automatic-error-reporting"); + + expect(actual).toBeNull(); + }); + }); +}); + +const extensionStubWithTelemetryPreferenceItems = { + id: "some-test-extension-id", + appPreferences: [ + { + title: "Some telemetry-preference item", + id: "some-telemetry-preference-item-id", + showInPreferencesTab: "telemetry", + + components: { + Hint: () =>
, + Input: () =>
, + }, + }, + ], +}; diff --git a/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts b/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts new file mode 100644 index 0000000000000..3996a4661be7e --- /dev/null +++ b/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { UserStore } from "../../common/user-store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import { observable } from "mobx"; + +describe("preferences - navigation to terminal preferences", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi }) => { + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + syncKubeconfigEntries: observable.map(), + terminalConfig: { fontSize: 42 }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + }); + + describe("given in preferences, when rendered", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.beforeRender(() => { + applicationBuilder.preferences.navigate(); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show terminal preferences yet", () => { + const page = rendered.queryByTestId("terminal-preferences-page"); + + expect(page).toBeNull(); + }); + + describe("when navigating to terminal preferences using navigation", () => { + beforeEach(() => { + applicationBuilder.preferences.navigation.click("terminal"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows terminal preferences", () => { + const page = rendered.getByTestId("terminal-preferences-page"); + + expect(page).not.toBeNull(); + }); + }); + }); +}); diff --git a/src/behaviours/preferences/navigation-using-application-menu.test.ts b/src/behaviours/preferences/navigation-using-application-menu.test.ts new file mode 100644 index 0000000000000..a108c735f5459 --- /dev/null +++ b/src/behaviours/preferences/navigation-using-application-menu.test.ts @@ -0,0 +1,66 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { RenderResult } from "@testing-library/react"; +import { + ApplicationBuilder, + getApplicationBuilder, +} from "../../renderer/components/test-utils/get-application-builder"; +import isAutoUpdateEnabledInjectable from "../../main/is-auto-update-enabled.injectable"; +import type { UserStore } from "../../common/user-store"; +import userStoreInjectable from "../../common/user-store/user-store.injectable"; +import type { ThemeStore } from "../../renderer/theme.store"; +import themeStoreInjectable from "../../renderer/theme-store.injectable"; + +describe("preferences - navigation using application menu", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder(); + + applicationBuilder.beforeSetups(({ rendererDi, mainDi }) => { + mainDi.override(isAutoUpdateEnabledInjectable, () => () => false); + + const userStoreStub = { + extensionRegistryUrl: { customUrl: "some-custom-url" }, + } as unknown as UserStore; + + rendererDi.override(userStoreInjectable, () => userStoreStub); + + const themeStoreStub = { themeOptions: [] } as unknown as ThemeStore; + + rendererDi.override(themeStoreInjectable, () => themeStoreStub); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show application preferences page yet", () => { + const actual = rendered.queryByTestId("application-preferences-page"); + + expect(actual).toBeNull(); + }); + + describe("when navigating to preferences using application menu", () => { + beforeEach(() => { + applicationBuilder.applicationMenu.click("root.preferences"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows application preferences page", () => { + const actual = rendered.getByTestId("application-preferences-page"); + + expect(actual).not.toBeNull(); + }); + }); +}); diff --git a/src/behaviours/welcome/__snapshots__/navigation-using-application-menu.test.ts.snap b/src/behaviours/welcome/__snapshots__/navigation-using-application-menu.test.ts.snap new file mode 100644 index 0000000000000..368d132edb887 --- /dev/null +++ b/src/behaviours/welcome/__snapshots__/navigation-using-application-menu.test.ts.snap @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`welcome - navigation using application menu renders 1`] = `
`; + +exports[`welcome - navigation using application menu when navigating to welcome using application menu renders 1`] = ` +
+
+
+ +
+
+

+ Welcome to + OpenLens + 5! +

+

+ To get you started we have auto-detected your clusters in your kubeconfig file and added them to the catalog, your centralized view for managing all your cloud-native resources. +
+
+ If you have any questions or feedback, please join our + + + Lens Community slack channel + + . +

+ +
+
+
+
+
+`; diff --git a/src/behaviours/welcome/navigation-using-application-menu.test.ts b/src/behaviours/welcome/navigation-using-application-menu.test.ts new file mode 100644 index 0000000000000..e605870cf91f0 --- /dev/null +++ b/src/behaviours/welcome/navigation-using-application-menu.test.ts @@ -0,0 +1,47 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { RenderResult } from "@testing-library/react"; +import { ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import isAutoUpdateEnabledInjectable from "../../main/is-auto-update-enabled.injectable"; + +describe("welcome - navigation using application menu", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder().beforeSetups(({ mainDi }) => { + mainDi.override(isAutoUpdateEnabledInjectable, () => () => false); + }); + + rendered = await applicationBuilder.render(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("does not show welcome page yet", () => { + const actual = rendered.queryByTestId("welcome-page"); + + expect(actual).toBeNull(); + }); + + describe("when navigating to welcome using application menu", () => { + beforeEach(() => { + applicationBuilder.applicationMenu.click("help.welcome"); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows welcome page", () => { + const actual = rendered.getByTestId("welcome-page"); + + expect(actual).not.toBeNull(); + }); + }); +});