Making apiBase injectable (#6022)

* Making apiBase injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all of Helm functions to be DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make PortForward's use of apiBase fully injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all metric requests to be injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace resource applier with injectables

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch KubeJsonApi.forCluster to be injectable but do not use

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert the rest of shell sessions to be DI-ed

- This is a prerequesit for using the new
  createKubeJsonApiForClusterInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Use new createKubeJsonApiForClusterInjectable for openNodeShellSession

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make KubeconfigDialog injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove jest-fetch-mock and make fetch injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests with new global override

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add new injectable for create KubeJsonApi and JsonApi instances

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix showing-details-for-helm-release behavioural tests

- Remove HelmChartStore in favour of all injectables

- Create a model for UpgradeChartDockTab

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix show details and updating helm releases tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix residual typing issues related to metrics

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix crash on load due to circular dependency

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix create resource tab not working

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove legacy apiBase global

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Introduce and use isDebuggingInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Introduce and use windowLocationInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove global legacy apiKube

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve injectable filenames compared to the injectables inside

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove modifying input in requestActivePortForwardInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Introduce and use get(Milli)SecondsFromUnixEpochInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch to non-reactive way of gettting possible helm release versions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix typo

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix bug in KubeApi constructor

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all KubeApi related tests to use asyncFn

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix unit tests after introducing new injectables that have side effects

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix bad rebase causing tests to fail

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve expects for multiple field values

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix crash will looking up api refs

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix breaking change on KubeApi.list

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Better fix for formatting urls

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove injectable for time since we should just use useMockTime

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add happy path behavioural tests for upgrade chart tab

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove debug message

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix showing-details-for-helm-release tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix installing-helm-chart-from-new-tab tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests relating to hosted cluster id

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots to recent changes in master

Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>

Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>

* Reupdated upgrade chart new tab test snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix flakiness in unit test when using <Animated>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix flakiness and improve tests for DeleteClusterDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix kubeconfig-sync tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix <Extensions> tests by removing mockFs and making everything injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build issues

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix getElectronAppPathInjectable override not returning absolute paths

- Also fixes the listing-active-helm-repos-in-prefs tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace all uses of getAbsolutePath with joinPaths as it is more correct and less confusing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix opening application window tests by making override properly absolute

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots relating no longer using getAbsolutePath

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix and add behavioural tests for RenderDelay

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix extension discovery tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test flakiness because of path side effects, propagate uses to as many places

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix extension-discovery tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add global override to fix some tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rewrite and fix implementation of KubeconfigManager and its tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests by global override pathExists

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix unit tests failing on windows by using injectable verions of path functions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Attempt to fix test timeout by using runInAction

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix setupIpcMainHandlers usage

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>
Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>
Co-authored-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
authored and GitHub committed 2022-10-05 08:10:36 -04:00
1 parent ed073d6562
commit 76066c5ebf
367 files changed
+16701 -5302

No files matched your search

+28 -5
View File
@@ -3,12 +3,29 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { describeIf } from "../../../../integration/helpers/utils";
import { isWindows } from "../../vars";
import { isLogicalChildPath } from "../paths";
import type { DiContainer } from "@ogre-tools/injectable";
import path from "path";
import { getDiForUnitTesting } from "../../../main/getDiForUnitTesting";
import getAbsolutePathInjectable from "../../path/get-absolute-path.injectable";
import getDirnameOfPathInjectable from "../../path/get-dirname.injectable";
import type { IsLogicalChildPath } from "../../path/is-logical-child-path.injectable";
import isLogicalChildPathInjectable from "../../path/is-logical-child-path.injectable";
describe("isLogicalChildPath", () => {
describeIf(isWindows)("windows tests", () => {
let di: DiContainer;
let isLogicalChildPath: IsLogicalChildPath;
beforeEach(() => {
di = getDiForUnitTesting();
});
describe("when using win32 paths", () => {
beforeEach(() => {
di.override(getAbsolutePathInjectable, () => path.win32.resolve);
di.override(getDirnameOfPathInjectable, () => path.win32.dirname);
isLogicalChildPath = di.inject(isLogicalChildPathInjectable);
});
it.each([
{
parentPath: "C:\\Foo",
@@ -40,7 +57,13 @@ describe("isLogicalChildPath", () => {
});
});
describeIf(!isWindows)("posix tests", () => {
describe("when using posix paths", () => {
beforeEach(() => {
di.override(getAbsolutePathInjectable, () => path.posix.resolve);
di.override(getDirnameOfPathInjectable, () => path.posix.dirname);
isLogicalChildPath = di.inject(isLogicalChildPathInjectable);
});
it.each([
{
parentPath: "/foo",
+21
View File
@@ -35,3 +35,24 @@ export function buildURLPositional<P extends object = {}, Q extends object = {}>
return buildURL(path, { params, query, fragment });
};
}
export type UrlParamsFor<Pathname extends string> =
Pathname extends `${string}/:${infer A}?/${infer Tail}`
? Partial<Record<A, string>> & UrlParamsFor<`/${Tail}`>
: Pathname extends `${string}/:${infer A}/${infer Tail}`
? Record<A, string> & UrlParamsFor<`/${Tail}`>
: Pathname extends `${string}/:${infer A}?`
? Partial<Record<A, string>>
: Pathname extends `${string}/:${infer A}`
? Record<A, string>
: {};
export interface UrlBuilder<Pathname extends string> {
compile(params: UrlParamsFor<Pathname>, query?: object, fragment?: string): string;
}
export function urlBuilderFor<Pathname extends string>(pathname: Pathname): UrlBuilder<Pathname> {
return {
compile: buildURLPositional(pathname),
};
}
@@ -12,7 +12,7 @@ export type RequestFromChannel = <
channel: TChannel,
...request: TChannel["_requestSignature"] extends void
? []
: [TChannel["_requestSignature"]]
: [SetRequired<TChannel, "_requestSignature">["_requestSignature"]]
) => Promise<SetRequired<TChannel, "_responseSignature">["_responseSignature"]>;
export const requestFromChannelInjectionToken =
@@ -5,3 +5,7 @@
import moment from "moment";
export const getCurrentDateTime = () => moment().utc().format();
export const getMillisecondsFromUnixEpoch = () => Date.now();
export const getSecondsFromUnixEpoch = () => Math.floor(getMillisecondsFromUnixEpoch() / 1000);
-1
View File
@@ -22,7 +22,6 @@ export * from "./hash-set";
export * from "./n-fircate";
export * from "./noop";
export * from "./observable-crate/impl";
export * from "./paths";
export * from "./promise-exec";
export * from "./readonly";
export * from "./reject-promise";
-55
View File
@@ -1,55 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import path from "path";
import os from "os";
export function resolveTilde(filePath: string) {
if (filePath === "~") {
return os.homedir();
}
if (filePath.startsWith("~/")) {
return `${os.homedir()}${filePath.slice(1)}`;
}
return filePath;
}
export function resolvePath(filePath: string): string {
return path.resolve(resolveTilde(filePath));
}
/**
* Checks if `testPath` represents a potential filesystem entry that would be
* logically "within" the `parentPath` directory.
*
* This function will return `true` in the above case, and `false` otherwise.
* It will return `false` if the two paths are the same (after resolving them).
*
* The function makes no FS calls and is platform dependant. Meaning that the
* results are only guaranteed to be correct for the platform you are running
* on.
* @param parentPath The known path of a directory
* @param testPath The path that is to be tested
*/
export function isLogicalChildPath(parentPath: string, testPath: string): boolean {
parentPath = path.resolve(parentPath);
testPath = path.resolve(testPath);
if (parentPath === testPath) {
return false;
}
while (testPath.length >= parentPath.length) {
if (testPath === parentPath) {
return true;
}
testPath = path.dirname(testPath);
}
return false;
}
+27 -52
View File
@@ -3,11 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { SemVer } from "semver";
import semver, { coerce } from "semver";
import * as iter from "./iter";
import type { RawHelmChart } from "../k8s-api/endpoints/helm-charts.api";
import logger from "../logger";
export enum Ordering {
LESS = -1,
@@ -49,52 +45,31 @@ export function sortCompare<T>(left: T, right: T): Ordering {
return Ordering.GREATER;
}
interface ChartVersion {
version: string;
__version?: SemVer | null;
}
export function sortCompareChartVersions(left: ChartVersion, right: ChartVersion): Ordering {
if (left.__version && right.__version) {
return semver.compare(right.__version, left.__version);
}
if (!left.__version && right.__version) {
return Ordering.GREATER;
}
if (left.__version && !right.__version) {
return Ordering.LESS;
}
return sortCompare(left.version, right.version);
}
export function sortCharts(charts: RawHelmChart[]) {
interface ExtendedHelmChart extends RawHelmChart {
__version?: SemVer | null;
}
const chartsWithVersion = Array.from(
iter.map(
charts,
chart => {
const __version = coerce(chart.version, { loose: true });
if (!__version) {
logger.warn(`[HELM-SERVICE]: Version from helm chart is not loosely coercable to semver.`, { name: chart.name, version: chart.version, repo: chart.repo });
}
(chart as ExtendedHelmChart).__version = __version;
return chart as ExtendedHelmChart;
},
),
);
return chartsWithVersion
.sort(sortCompareChartVersions)
.map(chart => (delete chart.__version, chart as RawHelmChart));
/**
* This function sorts of list of items that have what should be a semver version formated string
* as the field `version` but if it is not loosely coercable to semver falls back to sorting them
* alphanumerically
*/
export function sortBySemverVersion<T extends { version: string }>(versioneds: T[]): T[] {
return versioneds
.map(versioned => ({
__version: coerce(versioned.version, { loose: true }),
raw: versioned,
}))
.sort((left, right) => {
if (left.__version && right.__version) {
return semver.compare(right.__version, left.__version);
}
if (!left.__version && right.__version) {
return Ordering.GREATER;
}
if (left.__version && !right.__version) {
return Ordering.LESS;
}
return sortCompare(left.raw.version, right.raw.version);
})
.map(({ raw }) => raw);
}
+2 -10
View File
@@ -5,7 +5,7 @@
// Helper for working with tarball files (.tar, .tgz)
// Docs: https://github.com/npm/node-tar
import type { ExtractOptions, FileStat } from "tar";
import type { FileStat } from "tar";
import tar from "tar";
import path from "path";
import { parse } from "./json";
@@ -62,18 +62,10 @@ export async function listTarEntries(filePath: string): Promise<string[]> {
await tar.list({
file: filePath,
onentry: (entry: FileStat) => {
onentry: (entry) => {
entries.push(path.normalize(entry.path as unknown as string));
},
});
return entries;
}
export function extractTar(filePath: string, opts: ExtractOptions & { sync?: boolean } = {}) {
return tar.extract({
file: filePath,
cwd: path.dirname(filePath),
...opts,
});
}