mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Stop using HelmCli from Renderer (#4861)
* Introduce way for execute file Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make typing of HelmRepo shared Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce way to get Helm environment values Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce function to read YAML file Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for listing active helm repositories in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make sense in name of injectable Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce helper for opening and selecting values of select Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for activating, deactivating public helm repositories in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for deactivating helm repository from list of active repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add missing global overrides Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make some tests more deterministic by mocking tooltips Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for activating custom helm repository in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove old implementation made redundant with competition for preferences of helm repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add success notification for activating custom helm repository Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce way to get single active helm repository Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibilities from god-class and switch to getting helm repositories using competition instead of another god class Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add TODO Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak position of spinner Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Start handling errors when accessing helm repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Handle error about no helm repositories when updating repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove unwarranted function configuration Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add missing global overrides Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove duplication how to acquire binary path for helm Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove redundant comment Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate naming to match Helm's internal Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Relocate file closer to it's relatives Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
1 parent
5420780ae0
commit
1393cc303d
99 files changed
+21409
-1039
No files matched your search
+6813
File diff suppressed because it is too large.
Load diff
+4926
File diff suppressed because it is too large.
Load diff
+4184
File diff suppressed because it is too large.
Load diff
+1887
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,387 @@
|
||||
/**
|
||||
* 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 { fireEvent } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
import type { HelmRepo } from "../../common/helm/helm-repo";
|
||||
import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable";
|
||||
import isPathInjectable from "../../renderer/components/input/validators/is-path.injectable";
|
||||
import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable";
|
||||
import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable";
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
// TODO: Make tooltips free of side effects by making it deterministic
|
||||
jest.mock("../../renderer/components/tooltip/withTooltip", () => ({
|
||||
withTooltip: (target: any) => target,
|
||||
}));
|
||||
|
||||
describe("add custom helm repository in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult<HelmRepo[]>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.useFakeTimers("modern");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
|
||||
// TODO: Figure out how to make async validators unit testable
|
||||
rendererDi.override(isPathInjectable, () => ({ debounce: 0, validate: async () => {} }));
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when active repositories resolve", () => {
|
||||
beforeEach(async () => {
|
||||
await Promise.all([
|
||||
getActiveHelmRepositoriesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{ name: "Some active repository", url: "some-url" },
|
||||
],
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when selecting to add custom repository", () => {
|
||||
beforeEach(() => {
|
||||
const button = rendered.getByTestId("add-custom-helm-repo-button");
|
||||
|
||||
fireEvent.click(button);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows dialog", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("add-custom-helm-repository-dialog"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// TODO: Figure out how to close dialog by clicking outside of it
|
||||
xdescribe("when closing the dialog by clicking outside", () => {
|
||||
beforeEach(() => {});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show dialog anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("add-custom-helm-repository-dialog"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when closing the dialog by clicking cancel", () => {
|
||||
beforeEach(() => {
|
||||
const button = rendered.getByTestId("custom-helm-repository-cancel-button");
|
||||
|
||||
fireEvent.click(button);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show dialog anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("add-custom-helm-repository-dialog"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when inputted minimal options for the repository", () => {
|
||||
beforeEach(() => {
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
const nameInput = rendered.getByTestId("custom-helm-repository-name-input");
|
||||
|
||||
fireEvent.change(nameInput, { target: { value: "some-custom-repository" }});
|
||||
|
||||
const urlInput = rendered.getByTestId("custom-helm-repository-url-input");
|
||||
|
||||
fireEvent.change(urlInput, { target: { value: "http://some.url" }});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when submitted and some time passes", () => {
|
||||
beforeEach(() => {
|
||||
const submitButton = rendered.getByTestId("custom-helm-repository-submit-button");
|
||||
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
// TODO: Remove when debounce is removed from WizardStep.submit
|
||||
jest.runOnlyPendingTimers();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("adds the repository", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "some-custom-repository", "http://some.url"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not reload active repositories yet", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not show notification yet", () => {
|
||||
expect(showSuccessNotificationMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when activation rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject(
|
||||
"Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show success notification", () => {
|
||||
expect(showSuccessNotificationMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not show dialog anymore", () => {
|
||||
expect(rendered.queryByTestId("add-custom-helm-repository-dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not reload active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when activation resolves with success", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "some-custom-repository", "http://some.url"],
|
||||
],
|
||||
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show dialog anymore", () => {
|
||||
expect(rendered.queryByTestId("add-custom-helm-repository-dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("reloads active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows success notification", () => {
|
||||
expect(showSuccessNotificationMock).toHaveBeenCalledWith(
|
||||
"Helm repository some-custom-repository has been added.",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when adding custom repository again", () => {
|
||||
beforeEach(() => {
|
||||
const button = rendered.getByTestId("add-custom-helm-repo-button");
|
||||
|
||||
fireEvent.click(button);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("repository name is empty", () => {
|
||||
const input = rendered.getByTestId("custom-helm-repository-name-input") as HTMLInputElement;
|
||||
|
||||
expect(input.value).toBe("");
|
||||
});
|
||||
|
||||
it("repository url is empty", () => {
|
||||
const input = rendered.getByTestId("custom-helm-repository-url-input") as HTMLInputElement;
|
||||
|
||||
expect(input.value).toBe("");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when showing the maximal options", () => {
|
||||
beforeEach(() => {
|
||||
const button = rendered.getByTestId("toggle-maximal-options-for-custom-helm-repository-button");
|
||||
|
||||
fireEvent.click(button);
|
||||
});
|
||||
|
||||
it("shows maximal options", () => {
|
||||
const maximalOptions = rendered.getByTestId("maximal-options-for-custom-helm-repository-dialog");
|
||||
|
||||
expect(maximalOptions).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("given closing the dialog, when reopening the dialog, still shows maximal options", () => {
|
||||
const cancelButton = rendered.getByTestId("custom-helm-repository-cancel-button");
|
||||
|
||||
fireEvent.click(cancelButton);
|
||||
|
||||
const openButton = rendered.getByTestId("add-custom-helm-repo-button");
|
||||
|
||||
fireEvent.click(openButton);
|
||||
|
||||
const maximalOptions = rendered.getByTestId("maximal-options-for-custom-helm-repository-dialog");
|
||||
|
||||
expect(maximalOptions).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("when hiding maximal options", () => {
|
||||
beforeEach(() => {
|
||||
const button = rendered.getByTestId("toggle-maximal-options-for-custom-helm-repository-button");
|
||||
|
||||
fireEvent.click(button);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show maximal options anymore", () => {
|
||||
const maximalOptions = rendered.queryByTestId("maximal-options-for-custom-helm-repository-dialog");
|
||||
|
||||
expect(maximalOptions).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when inputted maximal options", () => {
|
||||
beforeEach(async () => {
|
||||
[
|
||||
{ selector: "username-input", value: "some-username" },
|
||||
{ selector: "password-input", value: "some-password" },
|
||||
{ selector: "ca-cert-file-input", value: "some-ca-cert-file" },
|
||||
{ selector: "cert-file-input", value: "some-cert-file" },
|
||||
{ selector: "key-file-input", value: "some-key-file" },
|
||||
].forEach(({ selector, value }) => {
|
||||
const input = rendered.getByTestId(`custom-helm-repository-${selector}`);
|
||||
|
||||
fireEvent.change(input, { target: { value }});
|
||||
});
|
||||
|
||||
const checkbox = rendered.getByTestId(`custom-helm-repository-verify-tls-input`);
|
||||
|
||||
fireEvent.click(checkbox);
|
||||
|
||||
jest.runOnlyPendingTimers();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("when submitted and some time passes, adds the repository with maximal options", () => {
|
||||
const submitButton = rendered.getByTestId("custom-helm-repository-submit-button");
|
||||
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
// TODO: Remove when debounce is removed from WizardStep.submit
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
[
|
||||
"repo",
|
||||
"add",
|
||||
"some-custom-repository",
|
||||
"http://some.url",
|
||||
"--insecure-skip-tls-verify",
|
||||
"--username",
|
||||
"some-username",
|
||||
"--password",
|
||||
"some-password",
|
||||
"--ca-file",
|
||||
"some-ca-cert-file",
|
||||
"--key-file",
|
||||
"some-key-file",
|
||||
"--cert-file",
|
||||
"some-cert-file",
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 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 type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
import type { HelmRepo } from "../../common/helm/helm-repo";
|
||||
import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable";
|
||||
import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable";
|
||||
import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable";
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
// TODO: Make tooltips free of side effects by making it deterministic
|
||||
jest.mock("../../renderer/components/tooltip/withTooltip", () => ({
|
||||
withTooltip: (target: any) => target,
|
||||
}));
|
||||
|
||||
describe("add helm repository from list in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult<HelmRepo[]>>;
|
||||
let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise<HelmRepo[]>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
callForPublicHelmRepositoriesMock = asyncFn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
|
||||
rendererDi.override(
|
||||
callForPublicHelmRepositoriesInjectable,
|
||||
() => callForPublicHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("calls for public repositories", () => {
|
||||
expect(callForPublicHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls for active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when both active and public repositories resolve", () => {
|
||||
beforeEach(async () => {
|
||||
await Promise.all([
|
||||
callForPublicHelmRepositoriesMock.resolve([
|
||||
{ name: "Some already active repository", url: "some-url" },
|
||||
{ name: "Some to be added repository", url: "some-other-url" },
|
||||
]),
|
||||
|
||||
getActiveHelmRepositoriesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{ name: "Some already active repository", url: "some-url" },
|
||||
],
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when select for adding public repositories is clicked", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.select.openMenu(
|
||||
"selection-of-active-public-helm-repository",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when deactive public repository is selected", () => {
|
||||
beforeEach(async () => {
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
applicationBuilder.select.selectOption(
|
||||
"selection-of-active-public-helm-repository",
|
||||
"Some to be added repository",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("adds the repository", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "Some to be added repository", "some-other-url"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not reload active repositories yet", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when adding rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject(
|
||||
"Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show success notification", () => {
|
||||
expect(showSuccessNotificationMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not show dialog anymore", () => {
|
||||
expect(rendered.queryByTestId("add-custom-helm-repository-dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not reload active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when adding resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "Some to be added repository", "some-other-url"],
|
||||
],
|
||||
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("reloads active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows success notification", () => {
|
||||
expect(showSuccessNotificationMock).toHaveBeenCalledWith(
|
||||
"Helm repository Some to be added repository has been added.",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when active repositories resolve again", () => {
|
||||
beforeEach(async () => {
|
||||
await getActiveHelmRepositoriesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{ name: "Some already active repository", url: "some-url" },
|
||||
{ name: "Some to be added repository", url: "some-other-url" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when select for selecting active repositories is clicked", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.select.openMenu(
|
||||
"selection-of-active-public-helm-repository",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when active repository is selected", () => {
|
||||
beforeEach(() => {
|
||||
execFileMock.mockClear();
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
applicationBuilder.select.selectOption(
|
||||
"selection-of-active-public-helm-repository",
|
||||
"Some already active repository",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("removes the repository", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "Some already active repository"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not reload active repositories yet", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when removing resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "Some already active repository"],
|
||||
],
|
||||
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("reloads active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,458 @@
|
||||
/**
|
||||
* 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 type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { ReadYamlFile } from "../../common/fs/read-yaml-file.injectable";
|
||||
import readYamlFileInjectable from "../../common/fs/read-yaml-file.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { HelmRepositoriesFromYaml } from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import type { Logger } from "../../common/logger";
|
||||
import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable";
|
||||
import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable";
|
||||
|
||||
// TODO: Make tooltips free of side effects by making it deterministic
|
||||
jest.mock("../../renderer/components/tooltip/withTooltip", () => ({
|
||||
withTooltip: (target: any) => target,
|
||||
}));
|
||||
|
||||
describe("listing active helm repositories in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let readYamlFileMock: AsyncFnMock<ReadYamlFile>;
|
||||
let execFileMock: AsyncFnMock<ReturnType<typeof execFileInjectable["instantiate"]>>;
|
||||
let loggerStub: Logger;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
readYamlFileMock = asyncFn();
|
||||
execFileMock = asyncFn();
|
||||
|
||||
loggerStub = { error: jest.fn() } as unknown as Logger;
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
mainDi.override(readYamlFileInjectable, () => readYamlFileMock);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
mainDi.override(loggerInjectable, () => loggerStub);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows loader for repositories", () => {
|
||||
expect(
|
||||
rendered.getByTestId("helm-repositories-are-loading"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("calls for helm configuration", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["env"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not call for updating of repositories yet", () => {
|
||||
expect(execFileMock).not.toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "update"],
|
||||
);
|
||||
});
|
||||
|
||||
describe("when getting configuration rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("some-error");
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Error getting Helm configuration: some-error",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all helm controls", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-controls"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when configuration resolves without path to repository config file", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
);
|
||||
});
|
||||
|
||||
it("logs error", () => {
|
||||
expect(loggerStub.error).toHaveBeenCalledWith(
|
||||
"Tried to get Helm repositories, but HELM_REPOSITORY_CONFIG was not present in `$ helm env`.",
|
||||
);
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Error getting Helm configuration: Tried to get Helm repositories, but HELM_REPOSITORY_CONFIG was not present in `$ helm env`.",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all helm controls", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-controls"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when configuration resolves without path to repository cache directory", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
);
|
||||
});
|
||||
|
||||
it("logs error", () => {
|
||||
expect(loggerStub.error).toHaveBeenCalledWith(
|
||||
"Tried to get Helm repositories, but HELM_REPOSITORY_CACHE was not present in `$ helm env`.",
|
||||
);
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Error getting Helm configuration: Tried to get Helm repositories, but HELM_REPOSITORY_CACHE was not present in `$ helm env`.",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all helm controls", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-controls"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when configuration resolves", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
|
||||
[
|
||||
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("calls for update of repositories", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "update"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not call for repositories yet", () => {
|
||||
expect(readYamlFileMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when updating repositories reject with any other error", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("Some error");
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Error updating Helm repositories: Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all helm controls", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-controls"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when updating repositories reject with error about no existing repositories", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.reject(
|
||||
"Error: no repositories found. You must add one before updating",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("still shows the loader for repositories", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('adds "bitnami" as default repository', () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "bitnami", "https://charts.bitnami.com/bitnami"],
|
||||
);
|
||||
});
|
||||
|
||||
describe("when adding default repository reject", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("Some error");
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
expect(showErrorNotificationMock).toHaveBeenCalledWith(
|
||||
"Error when adding default Helm repository: Some error",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all helm controls", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-controls"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when adding of default repository resolves", () => {
|
||||
beforeEach(async () => {
|
||||
readYamlFileMock.mockClear();
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
|
||||
[
|
||||
"repo",
|
||||
"add",
|
||||
"bitnami",
|
||||
"https://charts.bitnami.com/bitnami",
|
||||
],
|
||||
],
|
||||
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("still shows the loader for repositories", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("calls for repositories again", () => {
|
||||
expect(readYamlFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-repository-config-file.yaml",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when another call for repositories resolve", () => {
|
||||
beforeEach(async () => {
|
||||
await readYamlFileMock.resolveSpecific(
|
||||
["some-helm-repository-config-file.yaml"],
|
||||
|
||||
{
|
||||
repositories: [
|
||||
{
|
||||
name: "bitnami",
|
||||
url: "https://charts.bitnami.com/bitnami",
|
||||
caFile: "irrelevant",
|
||||
certFile: "irrelevant",
|
||||
insecure_skip_tls_verify: false,
|
||||
keyFile: "irrelevant",
|
||||
pass_credentials_all: false,
|
||||
password: "irrelevant",
|
||||
username: "irrelevant",
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows the added repository", () => {
|
||||
const actual = rendered.getByTestId("helm-repository-bitnami");
|
||||
|
||||
expect(actual).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when updating repositories resolve", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["repo", "update"]],
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("loads repositories from file system", () => {
|
||||
expect(readYamlFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-repository-config-file.yaml",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when repositories resolves", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await readYamlFileMock.resolveSpecific(
|
||||
["some-helm-repository-config-file.yaml"],
|
||||
repositoryConfigStub,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not add default repository", () => {
|
||||
expect(execFileMock).not.toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "bitnami", "https://charts.bitnami.com/bitnami"],
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show loader for repositories anymore", () => {
|
||||
expect(
|
||||
rendered.queryByTestId("helm-repositories-are-loading"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows repositories in use", () => {
|
||||
const actual = rendered.getAllByTestId(
|
||||
/^helm-repository-(some-repository|some-other-repository)$/,
|
||||
);
|
||||
|
||||
expect(actual).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const repositoryConfigStub: HelmRepositoriesFromYaml = {
|
||||
repositories: [
|
||||
{
|
||||
name: "some-repository",
|
||||
url: "some-repository-url",
|
||||
caFile: "irrelevant",
|
||||
certFile: "irrelevant",
|
||||
insecure_skip_tls_verify: false,
|
||||
keyFile: "irrelevant",
|
||||
pass_credentials_all: false,
|
||||
password: "irrelevant",
|
||||
username: "irrelevant",
|
||||
},
|
||||
|
||||
{
|
||||
name: "some-other-repository",
|
||||
url: "some-other-repository-url",
|
||||
caFile: "irrelevant",
|
||||
certFile: "irrelevant",
|
||||
insecure_skip_tls_verify: false,
|
||||
keyFile: "irrelevant",
|
||||
pass_credentials_all: false,
|
||||
password: "irrelevant",
|
||||
username: "irrelevant",
|
||||
},
|
||||
],
|
||||
};
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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 { fireEvent } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
import type { HelmRepo } from "../../common/helm/helm-repo";
|
||||
import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable";
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
// TODO: Make tooltips free of side effects by making it deterministic
|
||||
jest.mock("../../renderer/components/tooltip/withTooltip", () => ({
|
||||
withTooltip: (target: any) => target,
|
||||
}));
|
||||
|
||||
describe("remove helm repository from list of active repositories in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult<HelmRepo[]>>;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when active repositories resolve", () => {
|
||||
beforeEach(async () => {
|
||||
getActiveHelmRepositoriesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{ name: "some-active-repository", url: "some-url" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when removing repository", () => {
|
||||
beforeEach(() => {
|
||||
execFileMock.mockClear();
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
const removeButton = rendered.getByTestId(
|
||||
"remove-helm-repository-some-active-repository",
|
||||
);
|
||||
|
||||
fireEvent.click(removeButton);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("removes the repository", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "some-active-repository"],
|
||||
);
|
||||
});
|
||||
|
||||
it("does not reload active repositories yet", () => {
|
||||
expect(getActiveHelmRepositoriesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when removing resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "some-active-repository"],
|
||||
],
|
||||
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("reloads active repositories", () => {
|
||||
expect(getActiveHelmRepositoriesMock).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+96
-89
@@ -834,114 +834,121 @@ exports[`preferences - navigation to kubernetes preferences given in preferences
|
||||
</h2>
|
||||
<div>
|
||||
<div
|
||||
class="flex gaps"
|
||||
data-testid="helm-controls"
|
||||
>
|
||||
<div
|
||||
class="Select theme-lens box grow Select--is-disabled css-3iigni-container"
|
||||
class="flex gaps"
|
||||
>
|
||||
<span
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
id="react-select-HelmRepoSelect-live-region"
|
||||
/>
|
||||
<span
|
||||
aria-atomic="false"
|
||||
aria-live="polite"
|
||||
aria-relevant="additions text"
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
/>
|
||||
<div
|
||||
class="Select__control Select__control--is-disabled css-1insrsq-control"
|
||||
class="Select theme-lens box grow Select--is-disabled css-3iigni-container"
|
||||
>
|
||||
<span
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
id="react-select-selection-of-active-public-helm-repository-live-region"
|
||||
/>
|
||||
<span
|
||||
aria-atomic="false"
|
||||
aria-live="polite"
|
||||
aria-relevant="additions text"
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
/>
|
||||
<div
|
||||
class="Select__value-container css-319lph-ValueContainer"
|
||||
class="Select__control Select__control--is-disabled css-1insrsq-control"
|
||||
>
|
||||
<div
|
||||
class="Select__placeholder css-14el2xx-placeholder"
|
||||
id="react-select-HelmRepoSelect-placeholder"
|
||||
class="Select__value-container css-319lph-ValueContainer"
|
||||
>
|
||||
Repositories
|
||||
</div>
|
||||
<div
|
||||
class="Select__input-container css-jzldcf-Input"
|
||||
data-value=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-describedby="react-select-HelmRepoSelect-placeholder"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
class="Select__input"
|
||||
disabled=""
|
||||
id="HelmRepoSelect"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__loading-indicator css-at12u2-loadingIndicator"
|
||||
>
|
||||
<span
|
||||
class="css-1xtdfmb-LoadingDot"
|
||||
/>
|
||||
<span
|
||||
class="css-zoievk-LoadingDot"
|
||||
/>
|
||||
<span
|
||||
class="css-x748d8-LoadingDot"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="Select__indicator-separator css-109onse-indicatorSeparator"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="css-tj5bde-Svg"
|
||||
focusable="false"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
<div
|
||||
class="Select__placeholder css-14el2xx-placeholder"
|
||||
id="react-select-selection-of-active-public-helm-repository-placeholder"
|
||||
>
|
||||
<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"
|
||||
Repositories
|
||||
</div>
|
||||
<div
|
||||
class="Select__input-container css-jzldcf-Input"
|
||||
data-value=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-describedby="react-select-selection-of-active-public-helm-repository-placeholder"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
class="Select__input"
|
||||
disabled=""
|
||||
id="selection-of-active-public-helm-repository"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__loading-indicator css-at12u2-loadingIndicator"
|
||||
>
|
||||
<span
|
||||
class="css-1xtdfmb-LoadingDot"
|
||||
/>
|
||||
<span
|
||||
class="css-zoievk-LoadingDot"
|
||||
/>
|
||||
<span
|
||||
class="css-x748d8-LoadingDot"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="Select__indicator-separator css-109onse-indicatorSeparator"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="css-tj5bde-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"
|
||||
data-testid="add-custom-helm-repo-button"
|
||||
type="button"
|
||||
>
|
||||
Add Custom Helm Repo
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
class="Button primary"
|
||||
type="button"
|
||||
>
|
||||
Add Custom Helm Repo
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="repos"
|
||||
>
|
||||
<div
|
||||
class="pt-5 relative"
|
||||
class="repos"
|
||||
>
|
||||
<div
|
||||
class="Spinner singleColor center"
|
||||
/>
|
||||
class="pt-5 relative"
|
||||
>
|
||||
<div
|
||||
class="Spinner singleColor center"
|
||||
data-testid="helm-repositories-are-loading"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
|
||||
describe("preferences - navigation to kubernetes preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
@@ -17,6 +19,15 @@ describe("preferences - navigation to kubernetes preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi, mainDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => async () => ({ callWasSuccessful: true, response: [] }),
|
||||
);
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user