mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
revert integration test code
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
65274f0d5f
commit
c80965e512
@ -2,28 +2,16 @@ import { Application } from "spectron";
|
|||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
import { listHelmRepositories } from "../helpers/utils";
|
import { listHelmRepositories } from "../helpers/utils";
|
||||||
import { fail } from "assert";
|
import { fail } from "assert";
|
||||||
import open from "open";
|
|
||||||
import { AbortController } from "abort-controller";
|
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(60000);
|
||||||
|
|
||||||
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
||||||
describe("Lens integration tests", () => {
|
describe("Lens integration tests", () => {
|
||||||
let app: Application;
|
let app: Application;
|
||||||
let abortContoller: AbortController;
|
|
||||||
|
|
||||||
describe("app start", () => {
|
describe("app start", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => app = await utils.appStart(), 20000);
|
||||||
try {
|
|
||||||
app = await utils.appStart();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
abortContoller = new AbortController();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (app?.isRunning()) {
|
if (app?.isRunning()) {
|
||||||
@ -31,10 +19,6 @@ describe("Lens integration tests", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
abortContoller.abort();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows "whats new"', async () => {
|
it('shows "whats new"', async () => {
|
||||||
await utils.clickWhatsNew(app);
|
await utils.clickWhatsNew(app);
|
||||||
});
|
});
|
||||||
@ -44,26 +28,6 @@ describe("Lens integration tests", () => {
|
|||||||
await app.client.waitUntilTextExists("h2", "Add Cluster");
|
await app.client.waitUntilTextExists("h2", "Add Cluster");
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* skipping this for the time being until we can figure out why they are opening a second instace
|
|
||||||
* and seemingly bypassing the single instance lock
|
|
||||||
*/
|
|
||||||
describe.skip("protocol app start", () => {
|
|
||||||
it("should handle opening lens:// links", async () => {
|
|
||||||
await open("lens://app/foobar");
|
|
||||||
|
|
||||||
await utils.waitForLogsToContain(app, abortContoller, {
|
|
||||||
main: ["No handler", "lens://app/foobar"],
|
|
||||||
renderer: ["No handler", "lens://app/foobar"],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should opening lens://app/preferences", async () => {
|
|
||||||
await open("lens://app/preferences");
|
|
||||||
await app.client.waitUntilTextExists("h2", "Preferences");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("preferences page", () => {
|
describe("preferences page", () => {
|
||||||
it('shows "preferences"', async () => {
|
it('shows "preferences"', async () => {
|
||||||
const appName: string = process.platform === "darwin" ? "Lens" : "File";
|
const appName: string = process.platform === "darwin" ? "Lens" : "File";
|
||||||
|
|||||||
@ -9,8 +9,6 @@ import * as utils from "../helpers/utils";
|
|||||||
import { addMinikubeCluster, minikubeReady, waitForMinikubeDashboard } from "../helpers/minikube";
|
import { addMinikubeCluster, minikubeReady, waitForMinikubeDashboard } from "../helpers/minikube";
|
||||||
import { exec } from "child_process";
|
import { exec } from "child_process";
|
||||||
import * as util from "util";
|
import * as util from "util";
|
||||||
import { delay } from "../../src/common/utils";
|
|
||||||
import { AbortController } from "abort-controller";
|
|
||||||
|
|
||||||
export const promiseExec = util.promisify(exec);
|
export const promiseExec = util.promisify(exec);
|
||||||
|
|
||||||
@ -34,21 +32,11 @@ describe("Lens cluster pages", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe("cluster add", () => {
|
describe("cluster add", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => app = await utils.appStart(), 20000);
|
||||||
try {
|
|
||||||
app = await utils.appStart();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
try {
|
if (app && app.isRunning()) {
|
||||||
if (app?.isRunning()) {
|
return utils.tearDown(app);
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,420 +53,299 @@ describe("Lens cluster pages", () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("cluster menu pages", () => {
|
describe("cluster pages", () => {
|
||||||
beforeAll(async () => {
|
|
||||||
try {
|
beforeAll(appStartAddCluster, 40000);
|
||||||
await appStartAddCluster();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
try {
|
if (app && app.isRunning()) {
|
||||||
if (app?.isRunning()) {
|
return utils.tearDown(app);
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
type Page = [
|
const tests: {
|
||||||
string, // name
|
drawer?: string
|
||||||
{
|
drawerId?: string
|
||||||
|
pages: {
|
||||||
|
name: string,
|
||||||
href: string,
|
href: string,
|
||||||
expectedSelector: string,
|
expectedSelector: string,
|
||||||
expectedText: string,
|
expectedText: string
|
||||||
}
|
}[]
|
||||||
];
|
}[] = [{
|
||||||
|
drawer: "",
|
||||||
type PageTestCase = [
|
drawerId: "",
|
||||||
string, // drawer
|
pages: [{
|
||||||
|
name: "Cluster",
|
||||||
|
href: "cluster",
|
||||||
|
expectedSelector: "div.ClusterOverview div.label",
|
||||||
|
expectedText: "Master"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [{
|
||||||
|
name: "Nodes",
|
||||||
|
href: "nodes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Nodes"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Workloads",
|
||||||
|
drawerId: "workloads",
|
||||||
|
pages: [{
|
||||||
|
name: "Overview",
|
||||||
|
href: "workloads",
|
||||||
|
expectedSelector: "h5.box",
|
||||||
|
expectedText: "Overview"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
drawerId: string,
|
name: "Pods",
|
||||||
pages: Page[],
|
href: "pods",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pods"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Deployments",
|
||||||
|
href: "deployments",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Deployments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DaemonSets",
|
||||||
|
href: "daemonsets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Daemon Sets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatefulSets",
|
||||||
|
href: "statefulsets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Stateful Sets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ReplicaSets",
|
||||||
|
href: "replicasets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Replica Sets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jobs",
|
||||||
|
href: "jobs",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Jobs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CronJobs",
|
||||||
|
href: "cronjobs",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Cron Jobs"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Configuration",
|
||||||
|
drawerId: "config",
|
||||||
|
pages: [{
|
||||||
|
name: "ConfigMaps",
|
||||||
|
href: "configmaps",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Config Maps"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Secrets",
|
||||||
|
href: "secrets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Secrets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Resource Quotas",
|
||||||
|
href: "resourcequotas",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Resource Quotas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Limit Ranges",
|
||||||
|
href: "limitranges",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Limit Ranges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "HPA",
|
||||||
|
href: "hpa",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Horizontal Pod Autoscalers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pod Disruption Budgets",
|
||||||
|
href: "poddisruptionbudgets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pod Disruption Budgets"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Network",
|
||||||
|
drawerId: "networks",
|
||||||
|
pages: [{
|
||||||
|
name: "Services",
|
||||||
|
href: "services",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Services"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Endpoints",
|
||||||
|
href: "endpoints",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Endpoints"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ingresses",
|
||||||
|
href: "ingresses",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Ingresses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Network Policies",
|
||||||
|
href: "network-policies",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Network Policies"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Storage",
|
||||||
|
drawerId: "storage",
|
||||||
|
pages: [{
|
||||||
|
name: "Persistent Volume Claims",
|
||||||
|
href: "persistent-volume-claims",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Persistent Volume Claims"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Persistent Volumes",
|
||||||
|
href: "persistent-volumes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Persistent Volumes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Storage Classes",
|
||||||
|
href: "storage-classes",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Storage Classes"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [{
|
||||||
|
name: "Namespaces",
|
||||||
|
href: "namespaces",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Namespaces"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "",
|
||||||
|
drawerId: "",
|
||||||
|
pages: [{
|
||||||
|
name: "Events",
|
||||||
|
href: "events",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Events"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Apps",
|
||||||
|
drawerId: "apps",
|
||||||
|
pages: [{
|
||||||
|
name: "Charts",
|
||||||
|
href: "apps/charts",
|
||||||
|
expectedSelector: "div.HelmCharts input",
|
||||||
|
expectedText: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Releases",
|
||||||
|
href: "apps/releases",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Releases"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Access Control",
|
||||||
|
drawerId: "users",
|
||||||
|
pages: [{
|
||||||
|
name: "Service Accounts",
|
||||||
|
href: "service-accounts",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Service Accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Role Bindings",
|
||||||
|
href: "role-bindings",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Role Bindings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Roles",
|
||||||
|
href: "roles",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Roles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pod Security Policies",
|
||||||
|
href: "pod-security-policies",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Pod Security Policies"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
drawer: "Custom Resources",
|
||||||
|
drawerId: "custom-resources",
|
||||||
|
pages: [{
|
||||||
|
name: "Definitions",
|
||||||
|
href: "crd/definitions",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Custom Resources"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
|
||||||
|
tests.forEach(({ drawer = "", drawerId = "", pages }) => {
|
||||||
|
if (drawer !== "") {
|
||||||
|
it(`shows ${drawer} drawer`, async () => {
|
||||||
|
expect(clusterAdded).toBe(true);
|
||||||
|
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`);
|
||||||
|
await app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
];
|
pages.forEach(({ name, href, expectedSelector, expectedText }) => {
|
||||||
|
it(`shows ${drawer}->${name} page`, async () => {
|
||||||
const noSubMenuTests: Page[] = [
|
expect(clusterAdded).toBe(true);
|
||||||
[
|
await app.client.click(`a[href^="/${href}"]`);
|
||||||
"Cluster",
|
await app.client.waitUntilTextExists(expectedSelector, expectedText);
|
||||||
{
|
});
|
||||||
href: "cluster",
|
|
||||||
expectedSelector: "div.ClusterOverview div.label",
|
|
||||||
expectedText: "Master",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Nodes",
|
|
||||||
{
|
|
||||||
href: "nodes",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Nodes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Namespaces",
|
|
||||||
{
|
|
||||||
href: "namespaces",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Namespaces"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Events",
|
|
||||||
{
|
|
||||||
href: "events",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Events"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
const subMenuTests: PageTestCase[] = [
|
|
||||||
[
|
|
||||||
"Workloads",
|
|
||||||
{
|
|
||||||
drawerId: "workloads",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Overview",
|
|
||||||
{
|
|
||||||
href: "workloads",
|
|
||||||
expectedSelector: "h5.box",
|
|
||||||
expectedText: "Overview"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Pods",
|
|
||||||
{
|
|
||||||
href: "pods",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Pods"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Deployments",
|
|
||||||
{
|
|
||||||
href: "deployments",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Deployments"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"DaemonSets",
|
|
||||||
{
|
|
||||||
href: "daemonsets",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Daemon Sets"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"StatefulSets",
|
|
||||||
{
|
|
||||||
href: "statefulsets",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Stateful Sets"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"ReplicaSets",
|
|
||||||
{
|
|
||||||
href: "replicasets",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Replica Sets"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Jobs",
|
|
||||||
{
|
|
||||||
href: "jobs",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Jobs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"CronJobs",
|
|
||||||
{
|
|
||||||
href: "cronjobs",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Cron Jobs"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Configuration",
|
|
||||||
{
|
|
||||||
drawerId: "config",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"ConfigMaps",
|
|
||||||
{
|
|
||||||
href: "configmaps",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Config Maps"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Secrets",
|
|
||||||
{
|
|
||||||
href: "secrets",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Secrets"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Resource Quotas",
|
|
||||||
{
|
|
||||||
href: "resourcequotas",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Resource Quotas"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Limit Ranges",
|
|
||||||
{
|
|
||||||
href: "limitranges",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Limit Ranges"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"HPA",
|
|
||||||
{
|
|
||||||
href: "hpa",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Horizontal Pod Autoscalers"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Pod Disruption Budgets",
|
|
||||||
{
|
|
||||||
href: "poddisruptionbudgets",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Pod Disruption Budgets"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Network",
|
|
||||||
{
|
|
||||||
drawerId: "networks",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Services",
|
|
||||||
{
|
|
||||||
href: "services",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Services"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Endpoints",
|
|
||||||
{
|
|
||||||
href: "endpoints",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Endpoints"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Ingresses",
|
|
||||||
{
|
|
||||||
href: "ingresses",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Ingresses"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Network Policies",
|
|
||||||
{
|
|
||||||
href: "network-policies",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Network Policies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Storage",
|
|
||||||
{
|
|
||||||
drawerId: "storage",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Persistent Volume Claims",
|
|
||||||
{
|
|
||||||
href: "persistent-volume-claims",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Persistent Volume Claims"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Persistent Volumes",
|
|
||||||
{
|
|
||||||
href: "persistent-volumes",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Persistent Volumes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Storage Classes",
|
|
||||||
{
|
|
||||||
href: "storage-classes",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Storage Classes"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Apps",
|
|
||||||
{
|
|
||||||
drawerId: "apps",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Charts",
|
|
||||||
{
|
|
||||||
href: "apps/charts",
|
|
||||||
expectedSelector: "div.HelmCharts input",
|
|
||||||
expectedText: ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Releases",
|
|
||||||
{
|
|
||||||
href: "apps/releases",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Releases"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Access Control",
|
|
||||||
{
|
|
||||||
drawerId: "users",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Service Accounts",
|
|
||||||
{
|
|
||||||
href: "service-accounts",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Service Accounts"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Role Bindings",
|
|
||||||
{
|
|
||||||
href: "role-bindings",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Role Bindings"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Roles",
|
|
||||||
{
|
|
||||||
href: "roles",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Roles"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Pod Security Policies",
|
|
||||||
{
|
|
||||||
href: "pod-security-policies",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Pod Security Policies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Custom Resources",
|
|
||||||
{
|
|
||||||
drawerId: "custom-resources",
|
|
||||||
pages: [
|
|
||||||
[
|
|
||||||
"Definitions",
|
|
||||||
{
|
|
||||||
href: "crd/definitions",
|
|
||||||
expectedSelector: "h5.title",
|
|
||||||
expectedText: "Custom Resources"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
describe.each(noSubMenuTests)("%s", (name, { href, expectedSelector, expectedText }) => {
|
|
||||||
it("shows page", async () => {
|
|
||||||
expect(clusterAdded).toBe(true);
|
|
||||||
await app.client.click(`a[href^="/${href}"]`);
|
|
||||||
await app.client.waitUntilTextExists(expectedSelector, expectedText);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe.each(subMenuTests)("%s Drawer", (drawer, { drawerId, pages }) => {
|
|
||||||
it("does open", async () => {
|
|
||||||
expect(clusterAdded).toBe(true);
|
|
||||||
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`);
|
|
||||||
await app.client.waitUntilTextExists(`a[href^="/${pages[0][1].href}"]`, pages[0][0]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(pages)("shows %s page", async (name, { href, expectedSelector, expectedText }) => {
|
if (drawer !== "") {
|
||||||
expect(clusterAdded).toBe(true);
|
// hide the drawer
|
||||||
await app.client.click(`a[href^="/${href}"]`);
|
it(`hides ${drawer} drawer`, async () => {
|
||||||
await app.client.waitUntilTextExists(expectedSelector, expectedText);
|
expect(clusterAdded).toBe(true);
|
||||||
});
|
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`);
|
||||||
|
await expect(app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name, 100)).rejects.toThrow();
|
||||||
it("does close", async () => {
|
});
|
||||||
expect(clusterAdded).toBe(true);
|
}
|
||||||
await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
expect(await app.client.waitUntilTextExists(`a[href^="/${pages[0][1].href}"]`, pages[0][0], 100)).toBeUndefined();
|
|
||||||
} catch (error) {
|
|
||||||
expect(error).not.toBeUndefined();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("viewing pod logs", () => {
|
describe("viewing pod logs", () => {
|
||||||
let abortContoller: AbortController;
|
beforeEach(appStartAddCluster, 40000);
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
abortContoller = new AbortController();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await appStartAddCluster();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
abortContoller.abort();
|
if (app && app.isRunning()) {
|
||||||
|
return utils.tearDown(app);
|
||||||
try {
|
|
||||||
if (app?.isRunning()) {
|
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows a logs for a pod", async () => {
|
it(`shows a logs for a pod`, async () => {
|
||||||
expect(clusterAdded).toBe(true);
|
expect(clusterAdded).toBe(true);
|
||||||
// Go to Pods page
|
// Go to Pods page
|
||||||
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
||||||
@ -488,13 +355,19 @@ describe("Lens cluster pages", () => {
|
|||||||
await app.client.keys("kube-system");
|
await app.client.keys("kube-system");
|
||||||
await app.client.keys("Enter");// "\uE007"
|
await app.client.keys("Enter");// "\uE007"
|
||||||
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
|
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
|
||||||
|
let podMenuItemEnabled = false;
|
||||||
|
|
||||||
await utils.waitForLogsToContain(app, abortContoller, {
|
// Wait until extensions are enabled on renderer
|
||||||
renderer: ["[EXTENSION]: enabled lens-pod-menu@"],
|
while (!podMenuItemEnabled) {
|
||||||
});
|
const logs = await app.client.getRenderProcessLogs();
|
||||||
|
|
||||||
await delay(2000); // Give some extra time to prepare extensions
|
podMenuItemEnabled = !!logs.find(entry => entry.message.includes("[EXTENSION]: enabled lens-pod-menu@"));
|
||||||
|
|
||||||
|
if (!podMenuItemEnabled) {
|
||||||
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise(r => setTimeout(r, 500)); // Give some extra time to prepare extensions
|
||||||
// Open logs tab in dock
|
// Open logs tab in dock
|
||||||
await app.client.click(".list .TableRow:first-child");
|
await app.client.click(".list .TableRow:first-child");
|
||||||
await app.client.waitForVisible(".Drawer");
|
await app.client.waitForVisible(".Drawer");
|
||||||
@ -514,21 +387,11 @@ describe("Lens cluster pages", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("cluster operations", () => {
|
describe("cluster operations", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(appStartAddCluster, 40000);
|
||||||
try {
|
|
||||||
await appStartAddCluster();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
try {
|
if (app && app.isRunning()) {
|
||||||
if (app?.isRunning()) {
|
return utils.tearDown(app);
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -7,21 +7,11 @@ describe("Lens command palette", () => {
|
|||||||
let app: Application;
|
let app: Application;
|
||||||
|
|
||||||
describe("menu", () => {
|
describe("menu", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => app = await utils.appStart(), 20000);
|
||||||
try {
|
|
||||||
app = await utils.appStart();
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
try {
|
if (app?.isRunning()) {
|
||||||
if (app?.isRunning()) {
|
await utils.tearDown(app);
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -14,21 +14,13 @@ describe("Lens integration tests", () => {
|
|||||||
|
|
||||||
utils.describeIf(ready)("workspaces", () => {
|
utils.describeIf(ready)("workspaces", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
try {
|
app = await utils.appStart();
|
||||||
app = await utils.appStart();
|
await utils.clickWhatsNew(app);
|
||||||
await utils.clickWhatsNew(app);
|
}, 20000);
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
try {
|
if (app && app.isRunning()) {
|
||||||
if (app?.isRunning()) {
|
return utils.tearDown(app);
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
fail(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +1,12 @@
|
|||||||
import { AppConstructorOptions, Application } from "spectron";
|
import { Application } from "spectron";
|
||||||
import * as util from "util";
|
import * as util from "util";
|
||||||
import { exec } from "child_process";
|
import { exec } from "child_process";
|
||||||
import { delay } from "../../src/common/utils";
|
|
||||||
import { AbortController } from "abort-controller";
|
|
||||||
|
|
||||||
interface AppTestingPaths {
|
const AppPaths: Partial<Record<NodeJS.Platform, string>> = {
|
||||||
testingPath: string,
|
"win32": "./dist/win-unpacked/Lens.exe",
|
||||||
}
|
"linux": "./dist/linux-unpacked/kontena-lens",
|
||||||
|
"darwin": "./dist/mac/Lens.app/Contents/MacOS/Lens",
|
||||||
function getAppTestingPaths(): AppTestingPaths {
|
};
|
||||||
switch (process.platform) {
|
|
||||||
case "win32":
|
|
||||||
return {
|
|
||||||
testingPath: "./dist/win-unpacked/Lens.exe",
|
|
||||||
};
|
|
||||||
case "linux":
|
|
||||||
return {
|
|
||||||
testingPath: "./dist/linux-unpacked/kontena-lens",
|
|
||||||
};
|
|
||||||
case "darwin":
|
|
||||||
return {
|
|
||||||
testingPath: "./dist/mac/Lens.app/Contents/MacOS/Lens",
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw new TypeError(`platform ${process.platform} is not supported`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function itIf(condition: boolean) {
|
export function itIf(condition: boolean) {
|
||||||
return condition ? it : it.skip;
|
return condition ? it : it.skip;
|
||||||
@ -35,18 +16,16 @@ export function describeIf(condition: boolean) {
|
|||||||
return condition ? describe : describe.skip;
|
return condition ? describe : describe.skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setup(): AppConstructorOptions {
|
export function setup(): Application {
|
||||||
const appPath = getAppTestingPaths();
|
return new Application({
|
||||||
|
path: AppPaths[process.platform], // path to electron app
|
||||||
return {
|
|
||||||
path: appPath.testingPath,
|
|
||||||
args: [],
|
args: [],
|
||||||
startTimeout: 30000,
|
startTimeout: 30000,
|
||||||
waitTimeout: 60000,
|
waitTimeout: 60000,
|
||||||
env: {
|
env: {
|
||||||
CICD: "true"
|
CICD: "true"
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const keys = {
|
export const keys = {
|
||||||
@ -54,7 +33,7 @@ export const keys = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function appStart() {
|
export async function appStart() {
|
||||||
const app = new Application(setup());
|
const app = setup();
|
||||||
|
|
||||||
await app.start();
|
await app.start();
|
||||||
// Wait for splash screen to be closed
|
// Wait for splash screen to be closed
|
||||||
@ -62,31 +41,6 @@ export async function appStart() {
|
|||||||
await app.client.windowByIndex(0);
|
await app.client.windowByIndex(0);
|
||||||
await app.client.waitUntilWindowLoaded();
|
await app.client.waitUntilWindowLoaded();
|
||||||
|
|
||||||
/**
|
|
||||||
* This is commented out to pass CI, need to do some more investiagation into why this isn't working
|
|
||||||
*/
|
|
||||||
// if (process.platform === "linux") {
|
|
||||||
// const testingDesktop = [
|
|
||||||
// "[Desktop Entry]",
|
|
||||||
// "Name=Lens",
|
|
||||||
// `Exec=${path.resolve(getAppTestingPaths().testingPath)} %U`,
|
|
||||||
// "Terminal=false",
|
|
||||||
// "Type=Application",
|
|
||||||
// "Icon=lens",
|
|
||||||
// "StartupWMClass=Lens",
|
|
||||||
// "Comment=Lens - The Kubernetes IDE",
|
|
||||||
// "MimeType=x-scheme-handler/lens;",
|
|
||||||
// "Categories=Network;"
|
|
||||||
// ].join("\n");
|
|
||||||
|
|
||||||
// await mkdirp(path.join(os.homedir(), ".local/share/applications/"));
|
|
||||||
// await writeFile(path.join(os.homedir(), ".local/share/applications/lens-testing.desktop"), testingDesktop);
|
|
||||||
|
|
||||||
// const { status } = spawnSync("xdg-settings set default-url-scheme-handler lens lens-testing.desktop", { shell: true });
|
|
||||||
|
|
||||||
// expect(status).toBe(0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,85 +86,3 @@ export async function listHelmRepositories(retries = 0): Promise<HelmRepository
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const rendererLogPrefixMatcher = /^\[[0-9]{5}:[0-9]{4}\/[0-9]{6}\.[0-9]{6}:[A-Z]+:CONSOLE\([0-9)]+\)\]\s"(?<message>.*)", source: http:\/\//;
|
|
||||||
|
|
||||||
export interface LogMatches {
|
|
||||||
renderer?: string[];
|
|
||||||
main?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LogLines {
|
|
||||||
renderer: string[];
|
|
||||||
main: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function* splitLogs(app: Application, signal: AbortController): AsyncGenerator<LogLines, void, void> {
|
|
||||||
let lastLogLineCount = 0;
|
|
||||||
|
|
||||||
while (!signal.signal.aborted) { // infinite loop
|
|
||||||
const curLogs: string[] = (app as any).chromeDriver.getLogs();
|
|
||||||
const newLogs = curLogs.slice(lastLogLineCount);
|
|
||||||
|
|
||||||
lastLogLineCount = curLogs.length;
|
|
||||||
|
|
||||||
const item: LogLines = {
|
|
||||||
renderer: [],
|
|
||||||
main: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const logLine of newLogs) {
|
|
||||||
const logParts = logLine.match(rendererLogPrefixMatcher);
|
|
||||||
|
|
||||||
if (logParts === null) {
|
|
||||||
item.main.push(logLine);
|
|
||||||
} else {
|
|
||||||
item.renderer.push(logParts.groups.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yield item;
|
|
||||||
await delay(500, signal); // only delay after the first attempt and fail fast if the signal has occured
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for all of `values` to be part of the logs. Does not clear logs. Does
|
|
||||||
* not work well with `app.client.get(Main|Renderer)ProcessLogs()`
|
|
||||||
*
|
|
||||||
* Note: this is a "best attempt" since spectron's `getMainProcessLogs` sometimes
|
|
||||||
* contains `renderer` logs.
|
|
||||||
* @param app The spectron app that we are testing against
|
|
||||||
* @param source Whether to wait for renderer or main logs
|
|
||||||
* @param values The list of strings that should all be contained in the logs
|
|
||||||
*/
|
|
||||||
export async function waitForLogsToContain(app: Application, signal: AbortController, matches: LogMatches): Promise<void> {
|
|
||||||
const notYetFound = {
|
|
||||||
main: new Set(matches.main ?? []),
|
|
||||||
renderer: new Set(matches.renderer ?? []),
|
|
||||||
};
|
|
||||||
|
|
||||||
for await (const logs of splitLogs(app, signal)) {
|
|
||||||
mainMatch: for (const logPart of notYetFound.main) {
|
|
||||||
for (const logLine of logs.main) {
|
|
||||||
if (logLine.includes(logPart)) {
|
|
||||||
notYetFound.main.delete(logPart);
|
|
||||||
continue mainMatch; // we have found this log part, try the next part
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rendererMatch: for (const logPart of notYetFound.renderer) {
|
|
||||||
for (const logLine of logs.renderer) {
|
|
||||||
if (logLine.includes(logPart)) {
|
|
||||||
notYetFound.renderer.delete(logPart);
|
|
||||||
continue rendererMatch; // we have found this log part, try the next part
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notYetFound.main.size === 0 && notYetFound.renderer.size === 0) {
|
|
||||||
return; // we are done, have found all log parts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user