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

fixed all src/** tests, moved from spec/src to source code locations

This commit is contained in:
Roman 2020-06-25 15:21:28 +03:00
parent a772ef6b94
commit 43b3453e24
20 changed files with 167 additions and 160 deletions

View File

@ -3,7 +3,8 @@ module.exports = {
match: jest.fn(),
app: {
getVersion: jest.fn().mockReturnValue("3.0.0"),
getPath: jest.fn().mockReturnValue("/foo/bar")
getPath: jest.fn().mockReturnValue("tmp"),
getLocale: jest.fn().mockRejectedValue("en"),
},
remote: {
app: {

View File

@ -25,8 +25,8 @@
"build:linux": "yarn compile && electron-builder --linux --dir -c.productName=LensDev",
"build:mac": "yarn compile && electron-builder --mac --dir -c.productName=LensDev",
"build:win": "yarn compile && electron-builder --win --dir -c.productName=LensDev",
"test": "jest spec/src $@",
"integration": "jest spec/integration $@",
"test": "jest --env=jsdom src $@",
"integration": "jest --coverage integration $@",
"dist": "yarn compile && electron-builder -p onTag",
"dist:win": "yarn compile && electron-builder -p onTag --x64 --ia32",
"dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null",
@ -63,7 +63,7 @@
]
},
"jest": {
"testRegex": ".*_(spec)\\.[jt]sx?$",
"testRegex": ".*_(spec|test)\\.[jt]sx?$",
"collectCoverage": false,
"verbose": true,
"testEnvironment": "node",

View File

@ -1,17 +1,7 @@
import mockFs from "mock-fs"
import yaml from "js-yaml"
import { ClusterStore } from "../../../src/common/cluster-store";
import { Cluster } from "../../../src/main/cluster";
jest.mock("electron", () => {
return {
app: {
getVersion: () => '99.99.99',
getPath: () => 'tmp',
getLocale: () => 'en'
}
}
})
import { ClusterStore } from "./cluster-store";
import { Cluster } from "../main/cluster";
// Console.log needs to be called before fs-mocks, see https://github.com/tschaub/mock-fs/issues/234
console.log("");

View File

@ -1,15 +1,7 @@
import mockFs from "mock-fs"
import { userStore, UserStore } from "../../../src/common/user-store"
import { userStore, UserStore } from "./user-store"
jest.mock("electron", () => {
return {
app: {
getVersion: () => '99.99.99',
getPath: () => 'tmp',
getLocale: () => 'en'
}
}
})
jest.mock("electron")
// Console.log needs to be called before fs-mocks, see https://github.com/tschaub/mock-fs/issues/234
console.log("");

View File

@ -1,4 +1,4 @@
import { splitArray } from "../splitArray";
import { splitArray } from "./splitArray";
describe("split array on element tests", () => {
test("empty array", () => {

View File

@ -12,6 +12,7 @@ export const isDebugging = process.env.DEBUG === "true";
export const isProduction = process.env.NODE_ENV === "production"
export const isDevelopment = isDebugging || !isProduction;
export const buildVersion = process.env.BUILD_VERSION;
export const isTestEnv = !!process.env.JEST_WORKER_ID;
// Paths
export const contextDir = process.cwd();

View File

@ -1,14 +1,10 @@
import packageInfo from "../../../package.json"
// fixme: ENOENT: no such file or directory, mkdir '/foo/bar'
// import { bundledKubectl, Kubectl } from "../../../src/main/kubectl";
var bundledKubectl: any;
var Kubectl: any;
import packageInfo from "../../package.json"
import { bundledKubectl, Kubectl } from "../../src/main/kubectl";
jest.mock("electron")
jest.mock("../../../src/common/user-store")
jest.mock("../common/user-store")
xdescribe("kubectlVersion", () => {
describe("kubectlVersion", () => {
it("returns bundled version if exactly same version used", async () => {
const kubectl = new Kubectl(bundledKubectl.kubectlVersion)
expect(kubectl.kubectlVersion).toBe(bundledKubectl.kubectlVersion)

View File

@ -1,24 +1,25 @@
import { EventEmitter } from 'events'
import { getFreePort } from "./port"
import net from "net"
jest.mock("net");
class MockServer extends EventEmitter {
listen = jest.fn((obj) => {
this.emit('listening', {})
return this
})
address = () => { return { port: 12345 }}
address = () => {
return { port: 12345 }
}
unref = jest.fn()
close = jest.fn((cb) => {
cb()
})
close = jest.fn(cb => cb())
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
const net = require("net")
jest.mock("net")
import * as port from "../../../src/main/port"
describe("getFreePort", () => {
describe.only("getFreePort", () => {
beforeEach(() => {
// @ts-ignore
// fixme: find a better way to support types for mocked module
net.createServer.mockReturnValue(new MockServer)
})
@ -27,6 +28,6 @@ describe("getFreePort", () => {
})
it("finds the next free port", async () => {
return expect(port.getFreePort()).resolves.toEqual(expect.any(Number))
return expect(getFreePort()).resolves.toEqual(expect.any(Number))
})
})

View File

@ -1,8 +1,12 @@
/* Early store format had the kubeconfig directly under context name, this moves
it under the kubeConfig key */
import { isTestEnv } from "../../common/vars";
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.0.0-beta.2");
if(!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.0.0-beta.2");
}
for (const value of store) {
const contextName = value[0];
// Looping all the keys gives out the store internal stuff too...

View File

@ -1,9 +1,13 @@
// Cleans up a store that had the state related data stored
import { isTestEnv } from "../../common/vars";
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.4.1");
if (!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.4.1");
}
for (const value of store) {
const contextName = value[0];
if(contextName === "__internal__") continue;
if (contextName === "__internal__") continue;
const cluster = value[1];
store.set(contextName, { kubeConfig: cluster.kubeConfig, icon: cluster.icon || null, preferences: cluster.preferences || {} });

View File

@ -1,6 +1,10 @@
// Move cluster icon from root to preferences
import { isTestEnv } from "../../common/vars";
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.2");
if(!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.2");
}
for (const value of store) {
const clusterKey = value[0];
if(clusterKey === "__internal__") continue

View File

@ -1,8 +1,11 @@
import * as yaml from "js-yaml"
import { isTestEnv } from "../../common/vars";
// Convert access token and expiry from arrays into strings
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.3");
if(!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.3");
}
for (const value of store) {
const clusterKey = value[0];
if(clusterKey === "__internal__") continue

View File

@ -1,6 +1,10 @@
// Add existing clusters to "default" workspace
import { isTestEnv } from "../../common/vars";
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.0");
if(!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.0");
}
for (const value of store) {
const clusterKey = value[0];
if(clusterKey === "__internal__") continue

View File

@ -1,8 +1,11 @@
// add id for clusters and store them to array
import { v4 as uuid } from "uuid"
import { isTestEnv } from "../../common/vars";
export function migration(store: any) {
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.1");
if(!isTestEnv) {
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.1");
}
const clusters: any[] = []
for (const value of store) {
const clusterKey = value[0];

View File

@ -0,0 +1,103 @@
// Parse kube-api path and get api-version, group, etc.
import { splitArray } from "../../common/utils";
export interface IKubeApiLinkRef {
apiPrefix?: string;
apiVersion: string;
resource: string;
name: string;
namespace?: string;
}
export interface IKubeApiLinkBase extends IKubeApiLinkRef {
apiBase: string;
apiGroup: string;
apiVersionWithGroup: string;
}
export function parseApi(path: string): IKubeApiLinkBase {
path = new URL(path, location.origin).pathname;
const [, prefix, ...parts] = path.split("/");
const apiPrefix = `/${prefix}`;
const [left, right, namespaced] = splitArray(parts, "namespaces");
let apiGroup, apiVersion, namespace, resource, name;
if (namespaced) {
switch (right.length) {
case 1:
name = right[0];
// fallthrough
case 0:
resource = "namespaces"; // special case this due to `split` removing namespaces
break;
default:
[namespace, resource, name] = right;
break;
}
apiVersion = left.pop();
apiGroup = left.join("/");
} else {
switch (left.length) {
case 2:
resource = left.pop();
// fallthrough
case 1:
apiVersion = left.pop();
apiGroup = "";
break;
default:
/**
* Given that
* - `apiVersion` is `GROUP/VERSION` and
* - `VERSION` is `DNS_LABEL` which is /^[a-z0-9]((-[a-z0-9])|[a-z0-9])*$/i
* where length <= 63
* - `GROUP` is /^D(\.D)*$/ where D is `DNS_LABEL` and length <= 253
*
* There is no well defined selection from an array of items that were
* seperated by '/'
*
* Solution is to create a huristic. Namely:
* 1. if '.' in left[0] then apiGroup <- left[0]
* 2. if left[1] matches /^v[0-9]/ then apiGroup, apiVersion <- left[0], left[1]
* 3. otherwise assume apiVersion <- left[0]
* 4. always resource, name <- left[(0 or 1)+1..]
*/
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
[apiGroup, apiVersion] = left;
resource = left.slice(2).join("/")
} else {
apiGroup = "";
apiVersion = left[0];
[resource, name] = left.slice(1)
}
break;
}
}
const apiVersionWithGroup = [apiGroup, apiVersion].filter(v => v).join("/");
const apiBase = [apiPrefix, apiGroup, apiVersion, resource].filter(v => v).join("/");
if (!apiBase) {
throw new Error(`invalid apiPath: ${path}`)
}
return {
apiBase,
apiPrefix, apiGroup,
apiVersion, apiVersionWithGroup,
namespace, resource, name,
};
}
export function createApiLink(ref: IKubeApiLinkRef): string {
const { apiPrefix = "/apis", resource, apiVersion, name } = ref;
let { namespace } = ref;
if (namespace) {
namespace = `namespaces/${namespace}`
}
return [apiPrefix, apiVersion, namespace, resource, name]
.filter(v => v)
.join("/")
}

View File

@ -1,11 +1,11 @@
import { IKubeApiLinkBase, KubeApi } from "../kube-api";
import { IKubeApiLinkBase, parseApi } from "./kube-api-parse";
interface ParseAPITest {
interface KubeApi_Parse_Test {
url: string;
expected: Required<IKubeApiLinkBase>;
}
const tests: ParseAPITest[] = [
const tests: KubeApi_Parse_Test[] = [
{
url: "/api/v1/namespaces/kube-system/pods/coredns-6955765f44-v8p27",
expected: {
@ -112,12 +112,11 @@ const tests: ParseAPITest[] = [
},
];
jest.mock('../kube-watch-api.ts', () => 'KubeWatchApi');
describe("parseApi unit tests", () => {
describe.only("parseApi unit tests", () => {
for (const i in tests) {
const { url: tUrl, expected:tExpect} = tests[i];
test(`test #${parseInt(i)+1}`, () => {
expect(KubeApi.parseApi(tUrl)).toStrictEqual(tExpect);
expect(parseApi(tUrl)).toStrictEqual(tExpect);
});
}
});

View File

@ -7,7 +7,7 @@ import { IKubeObjectRef, KubeJsonApi, KubeJsonApiData, KubeJsonApiDataList } fro
import { apiKube } from "./index";
import { kubeWatchApi } from "./kube-watch-api";
import { apiManager } from "./api-manager";
import { splitArray } from "../../common/utils";
import { createApiLink, parseApi } from "./kube-api-parse";
export interface IKubeApiOptions<T extends KubeObject> {
kind: string; // resource type within api-group, e.g. "Namespace"
@ -25,107 +25,9 @@ export interface IKubeApiQueryParams {
continue?: string; // might be used with ?limit from second request
}
export interface IKubeApiLinkRef {
apiPrefix?: string;
apiVersion: string;
resource: string;
name: string;
namespace?: string;
}
export interface IKubeApiLinkBase extends IKubeApiLinkRef {
apiBase: string;
apiGroup: string;
apiVersionWithGroup: string;
}
export class KubeApi<T extends KubeObject = any> {
static parseApi(apiPath = ""): IKubeApiLinkBase {
apiPath = new URL(apiPath, location.origin).pathname;
const [, prefix, ...parts] = apiPath.split("/");
const apiPrefix = `/${prefix}`;
const [left, right, namespaced] = splitArray(parts, "namespaces");
let apiGroup, apiVersion, namespace, resource, name;
if (namespaced) {
switch (right.length) {
case 1:
name = right[0];
// fallthrough
case 0:
resource = "namespaces"; // special case this due to `split` removing namespaces
break;
default:
[namespace, resource, name] = right;
break;
}
apiVersion = left.pop();
apiGroup = left.join("/");
} else {
switch (left.length) {
case 2:
resource = left.pop();
// fallthrough
case 1:
apiVersion = left.pop();
apiGroup = "";
break;
default:
/**
* Given that
* - `apiVersion` is `GROUP/VERSION` and
* - `VERSION` is `DNS_LABEL` which is /^[a-z0-9]((-[a-z0-9])|[a-z0-9])*$/i
* where length <= 63
* - `GROUP` is /^D(\.D)*$/ where D is `DNS_LABEL` and length <= 253
*
* There is no well defined selection from an array of items that were
* seperated by '/'
*
* Solution is to create a huristic. Namely:
* 1. if '.' in left[0] then apiGroup <- left[0]
* 2. if left[1] matches /^v[0-9]/ then apiGroup, apiVersion <- left[0], left[1]
* 3. otherwise assume apiVersion <- left[0]
* 4. always resource, name <- left[(0 or 1)+1..]
*/
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
[apiGroup, apiVersion] = left;
resource = left.slice(2).join("/")
} else {
apiGroup = "";
apiVersion = left[0];
[resource, name] = left.slice(1)
}
break;
}
}
const apiVersionWithGroup = [apiGroup, apiVersion].filter(v => v).join("/");
const apiBase = [apiPrefix, apiGroup, apiVersion, resource].filter(v => v).join("/");
if (!apiBase) {
throw new Error(`invalid apiPath: ${apiPath}`)
}
return {
apiBase,
apiPrefix, apiGroup,
apiVersion, apiVersionWithGroup,
namespace, resource, name,
};
}
static createLink(ref: IKubeApiLinkRef): string {
const { apiPrefix = "/apis", resource, apiVersion, name } = ref;
let { namespace } = ref;
if (namespace) {
namespace = `namespaces/${namespace}`
}
return [apiPrefix, apiVersion, namespace, resource, name]
.filter(v => v)
.join("/")
}
static parseApi = parseApi;
static createLink = createApiLink;
static watchAll(...apis: KubeApi[]) {
const disposers = apis.map(api => api.watch());