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

fix unit and integration tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-01-28 14:22:44 -05:00
parent 0062395550
commit f8b36055f5
5 changed files with 87 additions and 45 deletions

View File

@ -31,12 +31,12 @@ describe("Lens integration tests", () => {
describe("protocol app start", () => {
it("should handle opening lens:// links", async () => {
await open("lens://internal/foobar");
await open("lens://app/foobar");
await Promise.all([
utils.waitForLogsToContain(app, "main", "No handler", "lens://internal/foobar"),
utils.waitForLogsToContain(app, "renderer", "No handler", "lens://internal/foobar"),
]);
await utils.waitForLogsToContain(app, {
main: ["No handler", "lens://app/foobar"],
renderer: ["No handler", "lens://app/foobar"],
});
});
});

View File

@ -3,6 +3,7 @@ import * as util from "util";
import { exec } from "child_process";
import fse from "fs-extra";
import path from "path";
import { delay } from "../../src/common/utils";
interface AppTestingPaths {
testingPath: string,
@ -114,7 +115,46 @@ export async function listHelmRepositories(retries = 0): Promise<HelmRepository
return [];
}
const rendererLogPrefixMatcher = /^\[[0-9]{5}:[0-9]{4}\/[0-9]{6}\.[0-9]{6}:[A-Z]+:CONSOLE\([0-9)]+\)\]/;
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): AsyncGenerator<LogLines, void, void> {
let lastLogLineCount = 0;
for(;;) { // 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); // only delay after the first attempt
}
}
/**
* Wait for all of `values` to be part of the logs. Does not clear logs. Does
@ -126,34 +166,33 @@ const rendererLogPrefixMatcher = /^\[[0-9]{5}:[0-9]{4}\/[0-9]{6}\.[0-9]{6}:[A-Z]
* @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, source: "renderer" | "main", ...values: string[]): Promise<void> {
const notFoundValues = new Set(values);
let lastLogLineCount = 0;
export async function waitForLogsToContain(app: Application, matches: LogMatches): Promise<void> {
const notYetFound = {
main: new Set(matches.main ?? []),
renderer: new Set(matches.renderer ?? []),
};
while (notFoundValues.size > 0) {
// get all the logs (this returns both) and doesn't clear them
const curLogs = ((app as any).chromeDriver.getLogs() as string[]);
// skip the logs already seen
const newLogs = curLogs.slice(lastLogLineCount);
lastLogLineCount += newLogs.length;
// filter the logs depending on whether we are waiting for logs from main or renderer
const filteredLogs = newLogs.filter(logLine => (source === "main") !== Boolean(logLine.match(rendererLogPrefixMatcher)));
for (const logLine of filteredLogs) {
if (notFoundValues.size === 0) {
break;
}
for (const value of notFoundValues) {
if (logLine.includes(value)) {
notFoundValues.delete(value);
for await (const logs of splitLogs(app)) {
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
}
}
}
await new Promise(resolve => setTimeout(resolve, 500)); // long poll getting logs
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
}
}
}

View File

@ -1,6 +1,8 @@
// Create async delay for provided timeout in milliseconds
export async function delay(timeoutMs = 1000) {
if (!timeoutMs) return;
await new Promise(resolve => setTimeout(resolve, timeoutMs));
/**
* Return a promise that will be resolved after at least `timeout` ms have
* passed
* @param timeout The number of milliseconds before resolving
*/
export function delay(timeout = 1000): Promise<void> {
return new Promise(resolve => setTimeout(resolve, timeout));
}

View File

@ -10,6 +10,7 @@ export * from "./cloneJson";
export * from "./delay";
export * from "./debouncePromise";
export * from "./defineGlobal";
export * from "./delay";
export * from "./getRandId";
export * from "./splitArray";
export * from "./saveToAppFiles";

View File

@ -67,7 +67,7 @@ describe("protocol router tests", () => {
lpr.addInternalHandler("/", noop);
try {
expect(await lpr.route("lens://internal")).toBeUndefined();
expect(await lpr.route("lens://app")).toBeUndefined();
} catch (error) {
expect(throwIfDefined(error)).not.toThrow();
}
@ -79,7 +79,7 @@ describe("protocol router tests", () => {
expect(throwIfDefined(error)).not.toThrow();
}
expect(broadcastMessage).toHaveBeenNthCalledWith(1, ProtocolHandlerInternal, "lens://internal");
expect(broadcastMessage).toHaveBeenNthCalledWith(1, ProtocolHandlerInternal, "lens://app");
expect(broadcastMessage).toHaveBeenNthCalledWith(2, ProtocolHandlerExtension, "lens://extension/@mirantis/minikube");
});
@ -89,13 +89,13 @@ describe("protocol router tests", () => {
lpr.addInternalHandler("/page", () => { called = true; });
try {
expect(await lpr.route("lens://internal/page")).toBeUndefined();
expect(await lpr.route("lens://app/page")).toBeUndefined();
} catch (error) {
expect(throwIfDefined(error)).not.toThrow();
}
expect(called).toBe(true);
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://internal/page");
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page");
});
it("should call most exact handler", async () => {
@ -105,13 +105,13 @@ describe("protocol router tests", () => {
lpr.addInternalHandler("/page/:id", params => { called = params.pathname.id; });
try {
expect(await lpr.route("lens://internal/page/foo")).toBeUndefined();
expect(await lpr.route("lens://app/page/foo")).toBeUndefined();
} catch (error) {
expect(throwIfDefined(error)).not.toThrow();
}
expect(called).toBe("foo");
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://internal/page/foo");
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo");
});
it("should call most exact handler for an extension", async () => {
@ -229,13 +229,13 @@ describe("protocol router tests", () => {
lpr.addInternalHandler("/page/bar", () => { called = 4; });
try {
expect(await lpr.route("lens://internal/page/foo/bar/bat")).toBeUndefined();
expect(await lpr.route("lens://app/page/foo/bar/bat")).toBeUndefined();
} catch (error) {
expect(throwIfDefined(error)).not.toThrow();
}
expect(called).toBe(3);
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://internal/page/foo/bar/bat");
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat");
});
it("should call most exact handler with 2 found handlers", async () => {
@ -246,12 +246,12 @@ describe("protocol router tests", () => {
lpr.addInternalHandler("/page/bar", () => { called = 4; });
try {
expect(await lpr.route("lens://internal/page/foo/bar/bat")).toBeUndefined();
expect(await lpr.route("lens://app/page/foo/bar/bat")).toBeUndefined();
} catch (error) {
expect(throwIfDefined(error)).not.toThrow();
}
expect(called).toBe(1);
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://internal/page/foo/bar/bat");
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat");
});
});