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

Introduce a collection of behavioural unit tests for navigation (#5085)

This reverts commit ecd881c25df219b511d7efd43dac59e748b21cc7.

Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>
Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>

Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Iku-turso 2022-04-12 07:39:46 +03:00 committed by GitHub
parent 68a605ded9
commit 55d8e0e06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 17978 additions and 0 deletions

View File

@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`extension special characters in page registrations renders 1`] = `<div />`;
exports[`extension special characters in page registrations when navigating to route with ID having special characters renders 1`] = `
<div>
<div>
Some page
</div>
</div>
`;

View File

@ -0,0 +1,83 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`navigate to extension page renders 1`] = `<div />`;
exports[`navigate to extension page when extension navigates to child route renders 1`] = `
<div>
<div>
Child page
</div>
</div>
`;
exports[`navigate to extension page when extension navigates to route with parameters renders 1`] = `
<div>
<div>
<ul>
<li>
some-string-value-from-navigate
</li>
<li>
126
</li>
<li>
some-array-value-from-navigate
</li>
</ul>
<button
data-testid="button-to-change-page-parameters"
type="button"
>
Some button
</button>
</div>
</div>
`;
exports[`navigate to extension page when extension navigates to route without parameters renders 1`] = `
<div>
<div>
<ul>
<li>
some-string-value
</li>
<li>
42
</li>
<li>
some-array-value,some-other-array-value
</li>
</ul>
<button
data-testid="button-to-change-page-parameters"
type="button"
>
Some button
</button>
</div>
</div>
`;
exports[`navigate to extension page when extension navigates to route without parameters when changing page parameters renders 1`] = `
<div>
<div>
<ul>
<li>
some-changed-string-value
</li>
<li>
84
</li>
<li>
some-changed-array-value,some-other-changed-array-value
</li>
</ul>
<button
data-testid="button-to-change-page-parameters"
type="button"
>
Some button
</button>
</div>
</div>
`;

View File

@ -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`] = `
<div>
<pre>
{
"someParameter": "some-value",
"someOtherParameter": "some-other-value"
}
</pre>
</div>
`;
exports[`navigating between routes given route without path parameters when navigating to route renders 1`] = `
<div>
<div>
Some component
</div>
</div>
`;

View File

@ -0,0 +1,89 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`add-cluster - navigation using application menu renders 1`] = `<div />`;
exports[`add-cluster - navigation using application menu when navigating to add cluster using application menu renders 1`] = `
<div>
<div
class="SettingLayout"
data-testid="add-cluster-page"
>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content flex column gaps"
>
<h2>
Add Clusters from Kubeconfig
</h2>
<p>
Clusters added here are
<b>
not
</b>
merged into the
<code>
~/.kube/config
</code>
file.
<a
href="https://docs.k8slens.dev/main//catalog/add-clusters/"
rel="noreferrer"
target="_blank"
>
Read more about adding clusters
</a>
.
</p>
<div
class="flex column"
/>
<div
class="actions-panel"
>
<button
class="Button primary"
disabled=""
type="button"
>
Add clusters
</button>
</div>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -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 add cluster 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();
});
});
});

View File

@ -0,0 +1,719 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`cluster - order of sidebar items when rendered renders 1`] = `
<div>
<div
class="flex flex-col"
data-testid="cluster-sidebar"
>
<div>
<div
class=""
style="width: 40px; height: 40px;"
>
??
</div>
<div />
</div>
<div
class="undefined sidebar-active-status"
>
<div
class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false"
data-test-id="workloads"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-workloads"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Workloads
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="config"
data-is-active-test="false"
data-test-id="config"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-config"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="list"
>
list
</span>
</i>
<span
class="link-text box grow"
>
Config
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false"
data-test-id="some-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-some-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some parent
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="network"
data-is-active-test="false"
data-test-id="network"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-network"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="device_hub"
>
device_hub
</span>
</i>
<span
class="link-text box grow"
>
Network
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="storage"
data-is-active-test="false"
data-test-id="storage"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-storage"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="storage"
>
storage
</span>
</i>
<span
class="link-text box grow"
>
Storage
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-another-parent-id"
data-is-active-test="false"
data-test-id="some-another-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-another-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some another parent
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="helm"
data-is-active-test="false"
data-test-id="helm"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-helm"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Helm
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false"
data-test-id="user-management"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-user-management"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="security"
>
security
</span>
</i>
<span
class="link-text box grow"
>
Access Control
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false"
data-test-id="custom-resources"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-custom-resources"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="extension"
>
extension
</span>
</i>
<span
class="link-text box grow"
>
Custom Resources
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-other-parent-id"
data-is-active-test="false"
data-test-id="some-other-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-other-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some other parent
</span>
</a>
</div>
</div>
</div>
</div>
`;
exports[`cluster - order of sidebar items when rendered when parent is expanded renders 1`] = `
<div>
<div
class="flex flex-col"
data-testid="cluster-sidebar"
>
<div>
<div
class=""
style="width: 40px; height: 40px;"
>
??
</div>
<div />
</div>
<div
class="undefined sidebar-active-status"
>
<div
class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false"
data-test-id="workloads"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-workloads"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Workloads
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="config"
data-is-active-test="false"
data-test-id="config"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-config"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="list"
>
list
</span>
</i>
<span
class="link-text box grow"
>
Config
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false"
data-test-id="some-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-some-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some parent
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_up"
>
keyboard_arrow_up
</span>
</i>
</a>
<ul
class="sub-menu"
>
<div
class="SidebarItem"
data-id-test="some-child-id"
data-is-active-test="false"
data-parent-id-test="some-parent-id"
data-test-id="some-child-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-child-id"
href="/"
>
<span
class="link-text box grow"
>
Some child
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-another-child-id"
data-is-active-test="false"
data-parent-id-test="some-parent-id"
data-test-id="some-another-child-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-another-child-id"
href="/"
>
<span
class="link-text box grow"
>
Some another child
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-other-child-id"
data-is-active-test="false"
data-parent-id-test="some-parent-id"
data-test-id="some-other-child-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-other-child-id"
href="/"
>
<span
class="link-text box grow"
>
Some other child
</span>
</a>
</div>
</ul>
</div>
<div
class="SidebarItem"
data-id-test="network"
data-is-active-test="false"
data-test-id="network"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-network"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="device_hub"
>
device_hub
</span>
</i>
<span
class="link-text box grow"
>
Network
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="storage"
data-is-active-test="false"
data-test-id="storage"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-storage"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="storage"
>
storage
</span>
</i>
<span
class="link-text box grow"
>
Storage
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-another-parent-id"
data-is-active-test="false"
data-test-id="some-another-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-another-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some another parent
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="helm"
data-is-active-test="false"
data-test-id="helm"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-helm"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Helm
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false"
data-test-id="user-management"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-user-management"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="security"
>
security
</span>
</i>
<span
class="link-text box grow"
>
Access Control
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false"
data-test-id="custom-resources"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-custom-resources"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="extension"
>
extension
</span>
</i>
<span
class="link-text box grow"
>
Custom Resources
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-other-parent-id"
data-is-active-test="false"
data-test-id="some-other-parent-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-other-parent-id"
href="/"
>
<span
class="link-text box grow"
>
Some other parent
</span>
</a>
</div>
</div>
</div>
</div>
`;

View File

@ -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`] = `
<div>
<div
class="flex flex-col"
data-testid="cluster-sidebar"
>
<div>
<div
class=""
style="width: 40px; height: 40px;"
>
??
</div>
<div />
</div>
<div
class="undefined sidebar-active-status"
>
<div
class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false"
data-test-id="workloads"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-workloads"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Workloads
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="config"
data-is-active-test="false"
data-test-id="config"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-config"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="list"
>
list
</span>
</i>
<span
class="link-text box grow"
>
Config
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="network"
data-is-active-test="false"
data-test-id="network"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-network"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="device_hub"
>
device_hub
</span>
</i>
<span
class="link-text box grow"
>
Network
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="storage"
data-is-active-test="false"
data-test-id="storage"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-storage"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="storage"
>
storage
</span>
</i>
<span
class="link-text box grow"
>
Storage
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="helm"
data-is-active-test="false"
data-test-id="helm"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-helm"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Helm
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false"
data-test-id="user-management"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-user-management"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="security"
>
security
</span>
</i>
<span
class="link-text box grow"
>
Access Control
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false"
data-test-id="custom-resources"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-custom-resources"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="extension"
>
extension
</span>
</i>
<span
class="link-text box grow"
>
Custom Resources
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
</div>
</div>
</div>
`;
exports[`cluster - visibility of sidebar items given kube resource for route is not allowed when kube resource becomes allowed renders 1`] = `
<div>
<div
class="flex flex-col"
data-testid="cluster-sidebar"
>
<div>
<div
class=""
style="width: 40px; height: 40px;"
>
??
</div>
<div />
</div>
<div
class="undefined sidebar-active-status"
>
<div
class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false"
data-test-id="workloads"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-workloads"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Workloads
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="config"
data-is-active-test="false"
data-test-id="config"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-config"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="list"
>
list
</span>
</i>
<span
class="link-text box grow"
>
Config
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="some-item-id"
data-is-active-test="false"
data-test-id="some-item-id"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-some-item-id"
href="/"
>
<span
class="link-text box grow"
>
Some item
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="network"
data-is-active-test="false"
data-test-id="network"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-network"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="device_hub"
>
device_hub
</span>
</i>
<span
class="link-text box grow"
>
Network
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="storage"
data-is-active-test="false"
data-test-id="storage"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-storage"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="storage"
>
storage
</span>
</i>
<span
class="link-text box grow"
>
Storage
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="namespaces"
data-is-active-test="false"
data-test-id="namespaces"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-namespaces"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="layers"
>
layers
</span>
</i>
<span
class="link-text box grow"
>
Namespaces
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="helm"
data-is-active-test="false"
data-test-id="helm"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-helm"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span
class="link-text box grow"
>
Helm
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false"
data-test-id="user-management"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center"
data-testid="sidebar-item-link-for-user-management"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="security"
>
security
</span>
</i>
<span
class="link-text box grow"
>
Access Control
</span>
</a>
</div>
<div
class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false"
data-test-id="custom-resources"
data-testid="sidebar-item"
>
<a
class="nav-item flex gaps align-center expandable"
data-testid="sidebar-item-link-for-custom-resources"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="extension"
>
extension
</span>
</i>
<span
class="link-text box grow"
>
Custom Resources
</span>
<i
class="Icon expand-icon box right material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
</div>
</div>
</div>
`;

View File

@ -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,
});

View File

@ -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: () => <div data-testid="some-icon-for-parent" />,
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: () => <div data-testid="some-child-page" />,
}),
injectionToken: routeSpecificComponentInjectionToken,
});

View File

@ -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<LensRendererExtension> = {
id: "some-extension-id",
clusterPages: [
{
components: {
Page: () => {
throw new Error("should never come here");
},
},
},
{
id: "some-child-page-id",
components: {
Page: () => <div data-testid="some-child-page">Some child page</div>,
},
},
{
id: "some-other-child-page-id",
components: {
Page: () => (
<div data-testid="some-other-child-page">Some other child page</div>
),
},
},
],
clusterPageMenus: [
{
id: "some-parent-id",
title: "Parent",
components: {
Icon: () => <div>Some icon</div>,
},
},
{
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;

View File

@ -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: () => <div data-testid="some-child-page" />,
}),
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,
});

View File

@ -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<LensRendererExtension> = {
id: "@some-extension-id/",
globalPages: [
{
id: "/some-page-id/",
components: {
Page: () => <div>Some page</div>,
},
},
],
};

View File

@ -0,0 +1,123 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`extensions - navigation using application menu renders 1`] = `<div />`;
exports[`extensions - navigation using application menu when navigating to extensions using application menu renders 1`] = `
<div>
<div
class="SettingLayout DropFileInput Extensions"
data-testid="extensions-page"
>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section>
<h1>
Extensions
</h1>
<div
class="mb-14 mt-3"
>
<p>
Add new features via Lens Extensions.
Check out
<a
href="https://docs.k8slens.dev/main//extensions/"
rel="noreferrer"
target="_blank"
>
docs
</a>
and list of
<a
href="https://github.com/lensapp/lens-extensions/blob/main/README.md"
rel="noreferrer"
target="_blank"
>
available extensions
</a>
.
</p>
</div>
<section
class="mt-2"
>
<div
class="SubTitle"
>
Name or file path or URL to an extension package (tar, tgz)
</div>
<div
class="flex"
>
<div
class="flex-1"
/>
<div
class="flex-initial"
>
<button
class="Button w-80 h-full primary"
type="button"
>
Install
</button>
</div>
</div>
<small
class="mt-3"
>
<b>
Pro-Tip
</b>
: you can drag-n-drop tarball-file to this area
</small>
</section>
<div>
<div
class="Spinner singleColor center"
/>
</div>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -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();
});
});
});

View File

@ -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<object>;
let currentPath: IComputedValue<string>;
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<LensRendererExtension> = {
id: "some-extension-id",
globalPages: [
{
components: {
Page: ({ params }) => (
<div>
<ul>
<li>{params.someStringParameter.get()}</li>
<li>{params.someNumberParameter.get()}</li>
<li>{params.someArrayParameter.get().join(",")}</li>
</ul>
<button
type="button"
data-testid="button-to-change-page-parameters"
onClick={() => {
params.someStringParameter.set("some-changed-string-value");
params.someNumberParameter.set(84);
params.someArrayParameter.set([
"some-changed-array-value",
"some-other-changed-array-value",
]);
}}
>
Some button
</button>
</div>
),
},
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: () => <div>Child page</div>,
},
},
],
};

View File

@ -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<any>;
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<any>;
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: () => <div>Some component</div>,
}),
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(() => (
<pre>{JSON.stringify(pathParameters.get(), null, 2)}</pre>
)),
};
},
injectionToken: routeSpecificComponentInjectionToken,
});

File diff suppressed because it is too large Load Diff

View File

@ -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`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="proxy-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="proxy"
>
<section>
<h2
data-testid="proxy-header"
>
Proxy
</h2>
<div
class="SubTitle"
>
HTTP Proxy
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)"
spellcheck="false"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
<small
class="hint"
>
Proxy is used only for non-cluster communication.
</small>
</section>
<hr
class="small"
/>
<section
class="small"
>
<div
class="SubTitle"
>
Certificate Trust
</div>
<label
class=""
data-testid="switch"
>
Allow untrusted Certificate Authorities
<input
role="switch"
type="checkbox"
/>
</label>
<small
class="hint"
>
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!
</small>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`preferences - navigation to application preferences given in some child page of preferences, when rendered when navigating to application preferences using navigation renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,886 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`preferences - navigation to editor preferences given in preferences, when rendered renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`preferences - navigation to editor preferences given in preferences, when rendered when navigating to editor preferences using navigation renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="editor-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="editor"
>
<h2
data-testid="editor-configuration-header"
>
Editor configuration
</h2>
<div
class="SubTitle"
>
Minimap
</div>
<section>
<div
class="flex gaps justify-space-between"
>
<div
class="flex gaps align-center"
>
<label
class=""
data-testid="switch"
>
Show minimap
<input
role="switch"
type="checkbox"
/>
</label>
</div>
<div
class="flex gaps align-center"
>
<div
class="SubHeader compact"
>
Position
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="minimap-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section>
<div
class="SubTitle"
>
Line numbers
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="editor-line-numbers-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<section>
<div
class="SubTitle"
>
Tab size
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
min="1"
spellcheck="false"
type="number"
value="42"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<section>
<div
class="SubTitle"
>
Font size
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
min="10"
spellcheck="false"
type="number"
value="42"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<section>
<div
class="SubTitle"
>
Font family
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
spellcheck="false"
type="text"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,917 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`preferences - navigation to kubernetes preferences given in preferences, when rendered renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`preferences - navigation to kubernetes preferences given in preferences, when rendered when navigating to kubernetes preferences using navigation renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="kubernetes-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="kubernetes"
>
<section
id="kubectl"
>
<h2
data-testid="kubernetes-header"
>
Kubernetes
</h2>
<section>
<div
class="SubTitle"
>
Kubectl binary download
</div>
<label
class=""
data-testid="switch"
>
Download kubectl binaries matching the Kubernetes cluster version
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<section>
<div
class="SubTitle"
>
Download mirror
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Download mirror for kubectl
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="download-mirror-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<section>
<div
class="SubTitle"
>
Directory for binaries
</div>
<div
class="Input theme round black disabled"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="/some-absolute-root-directory/some-electron-app-path-for-user-data/binaries"
spellcheck="false"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
<div
class="hint"
>
The directory to download binaries into.
</div>
</section>
<section>
<div
class="SubTitle"
>
Path to kubectl binary
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
placeholder="/some-absolute-root-directory/some-electron-app-path-for-user-data/binaries/kubectl"
spellcheck="false"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
</section>
<hr />
<section
id="kube-sync"
>
<h2
data-testid="kubernetes-sync-header"
>
Kubeconfig Syncs
</h2>
<div
class="self-start mb-5"
>
<button
class="Button PathPicker primary"
type="button"
>
Sync Files and Folders
</button>
</div>
<div
class="SubTitle pt-5"
>
Synced Items
</div>
<div
class="mt-3"
>
<div
class="flex-grow text-center"
>
No files and folders have been synced yet
</div>
</div>
</section>
<hr />
<section
id="helm"
>
<h2>
Helm Charts
</h2>
<div>
<div
class="flex gaps"
>
<div
class="Select theme-lens box grow css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Repositories
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="HelmRepoSelect"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<button
class="Button primary"
type="button"
>
Add Custom Helm Repo
</button>
</div>
<div>
<div
class=""
>
<div
class="flex-grow text-center"
>
The repositories have not been added yet
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,696 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`preferences - navigation to proxy preferences given in preferences, when rendered renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`preferences - navigation to proxy preferences given in preferences, when rendered when navigating to proxy preferences using navigation renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="proxy-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="proxy"
>
<section>
<h2
data-testid="proxy-header"
>
Proxy
</h2>
<div
class="SubTitle"
>
HTTP Proxy
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)"
spellcheck="false"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
<small
class="hint"
>
Proxy is used only for non-cluster communication.
</small>
</section>
<hr
class="small"
/>
<section
class="small"
>
<div
class="SubTitle"
>
Certificate Trust
</div>
<label
class=""
data-testid="switch"
>
Allow untrusted Certificate Authorities
<input
role="switch"
type="checkbox"
/>
</label>
<small
class="hint"
>
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!
</small>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,805 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`preferences - navigation to terminal preferences given in preferences, when rendered renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`preferences - navigation to terminal preferences given in preferences, when rendered when navigating to terminal preferences using navigation renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="terminal-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section>
<h2>
Terminal
</h2>
<section
id="shell"
>
<div
class="SubTitle"
>
Terminal Shell Path
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
placeholder="some-default-shell"
spellcheck="false"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<section
id="terminalSelection"
>
<div
class="SubTitle"
>
Terminal copy & paste
</div>
<label
class=""
data-testid="switch"
>
Copy on select and paste on right-click
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<section
id="terminalTheme"
>
<div
class="SubTitle"
>
Terminal theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="terminal-theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<section>
<div
class="SubTitle"
>
Font size
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
min="10"
spellcheck="false"
type="number"
value="42"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<section>
<div
class="SubTitle"
>
Font family
</div>
<div
class="Input theme round black"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
spellcheck="false"
type="text"
value=""
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,498 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`preferences - navigation using application menu renders 1`] = `<div />`;
exports[`preferences - navigation using application menu when navigating to preferences using application menu renders 1`] = `
<div>
<div
class="SettingLayout showNavigation Preferences"
data-testid="application-preferences-page"
>
<nav
class="sidebarRegion"
>
<div
class="sidebar"
>
<div
class="Tabs flex column"
>
<div
class="header"
>
Preferences
</div>
<div
class="Tab flex gaps align-center active"
data-testid="tab-link-for-application"
role="tab"
tabindex="0"
>
<div
class="label"
>
App
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-proxy"
role="tab"
tabindex="0"
>
<div
class="label"
>
Proxy
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-kubernetes"
role="tab"
tabindex="0"
>
<div
class="label"
>
Kubernetes
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-editor"
role="tab"
tabindex="0"
>
<div
class="label"
>
Editor
</div>
</div>
<div
class="Tab flex gaps align-center"
data-testid="tab-link-for-terminal"
role="tab"
tabindex="0"
>
<div
class="label"
>
Terminal
</div>
</div>
</div>
</div>
</nav>
<div
class="contentRegion"
id="ScrollSpyRoot"
>
<div
class="content"
>
<section
id="application"
>
<h2
data-testid="application-header"
>
Application
</h2>
<section
id="appearance"
>
<div
class="SubTitle"
>
Theme
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="theme-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="extensionRegistryUrl"
>
<div
class="SubTitle"
>
Extension Install Registry
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="extension-install-registry-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
<p
class="mt-4 mb-5 leading-relaxed"
>
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
<b>
.npmrc
</b>
 file or in the input below.
</p>
<div
class="Input theme round black disabled invalid"
>
<label
class="input-area flex gaps align-center"
id=""
>
<input
class="input box grow"
disabled=""
placeholder="Custom Extension Registry URL..."
spellcheck="false"
value="some-custom-url"
/>
</label>
<div
class="input-info flex gaps"
/>
</div>
</section>
<hr />
<section
id="other"
>
<div
class="SubTitle"
>
Start-up
</div>
<label
class=""
data-testid="switch"
>
Automatically start Lens on login
<input
role="switch"
type="checkbox"
/>
</label>
</section>
<hr />
<section
id="update-channel"
>
<div
class="SubTitle"
>
Update Channel
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="update-channel-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
<hr />
<section
id="locale"
>
<div
class="SubTitle"
>
Locale Timezone
</div>
<div
class="Select theme-lens css-2b097c-container"
>
<div
class="Select__control css-yk16xz-control"
>
<div
class="Select__value-container css-g1d714-ValueContainer"
>
<div
class="Select__placeholder css-1wa3eu0-placeholder"
>
Select...
</div>
<div
class="css-b8ldur-Input"
>
<div
class="Select__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="timezone-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
>
<span
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
/>
<div
aria-hidden="true"
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="20"
viewBox="0 0 20 20"
width="20"
>
<path
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
/>
</svg>
</div>
</div>
</div>
</div>
</section>
</section>
</div>
<div
class="toolsRegion"
>
<div
class="fixed top-[60px]"
>
<div
data-testid="close-preferences"
>
<div
aria-label="Close"
role="button"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
<div
aria-hidden="true"
>
ESC
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -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: () => <Preferences>Some test page</Preferences>,
}),
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: () => <div>Some front page</div>,
}),
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,
});

View File

@ -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();
});
});
});
});

View File

@ -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();
});
});
});
});

View File

@ -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<LensRendererExtension> = {
id: "some-test-extension-id",
appPreferences: [
{
title: "Some preference item",
id: "some-preference-item-id",
components: {
Hint: () => <div data-testid="some-preference-item-hint" />,
Input: () => <div data-testid="some-preference-item-input" />,
},
},
{
title: "irrelevant",
id: "some-unrelated-preference-item-id",
showInPreferencesTab: "some-tab",
components: {
Hint: () => <div />,
Input: () => <div />,
},
},
],
};

View File

@ -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();
});
});
});
});

View File

@ -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();
});
});
});
});

View File

@ -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: () => <div />, Input: () => <div /> },
},
],
});
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: () => <div data-testid="some-preference-item-hint" />,
Input: () => <div data-testid="some-preference-item-input" />,
},
},
],
};

View File

@ -0,0 +1,74 @@
/**
* 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";
import defaultShellInjectable from "../../renderer/components/+preferences/default-shell.injectable";
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);
rendererDi.override(defaultShellInjectable, () => "some-default-shell");
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();
});
});
});
});

View File

@ -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();
});
});
});

View File

@ -0,0 +1,90 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`welcome - navigation using application menu renders 1`] = `<div />`;
exports[`welcome - navigation using application menu when navigating to welcome using application menu renders 1`] = `
<div>
<div
class="flex justify-center Welcome align-center"
data-testid="welcome-page"
>
<div
data-testid="welcome-banner-container"
style="width: 320px;"
>
<i
class="Icon logo svg focusable"
>
<span
class="icon"
/>
</i>
<div
class="flex justify-center"
>
<div
data-testid="welcome-text-container"
style="width: 320px;"
>
<h2>
Welcome to
OpenLens
5!
</h2>
<p>
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.
<br />
<br />
If you have any questions or feedback, please join our
<a
class="link"
href="https://join.slack.com/t/k8slens/shared_invite/zt-wcl8jq3k-68R5Wcmk1o95MLBE5igUDQ"
rel="noreferrer"
target="_blank"
>
Lens Community slack channel
</a>
.
</p>
<ul
class="block"
data-testid="welcome-menu-container"
style="width: 320px;"
>
<li
class="flex grid-12"
>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="view_list"
>
view_list
</span>
</i>
<a
class="box col-10"
>
Browse Clusters in Catalog
</a>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="navigate_next"
>
navigate_next
</span>
</i>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -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();
});
});
});