diff --git a/integration/__tests__/app.tests.ts b/integration/__tests__/app.tests.ts index 65e53335ea..00e4f1ef74 100644 --- a/integration/__tests__/app.tests.ts +++ b/integration/__tests__/app.tests.ts @@ -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"], + }); }); }); diff --git a/integration/helpers/utils.ts b/integration/helpers/utils.ts index 79f54fe9ba..31b9e0ca76 100644 --- a/integration/helpers/utils.ts +++ b/integration/helpers/utils.ts @@ -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.*)", source: http:\/\//; + +export interface LogMatches { + renderer?: string[]; + main?: string[]; +} + +interface LogLines { + renderer: string[]; + main: string[]; +} + +async function* splitLogs(app: Application): AsyncGenerator { + 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 { - const notFoundValues = new Set(values); - let lastLogLineCount = 0; +export async function waitForLogsToContain(app: Application, matches: LogMatches): Promise { + 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 + } } } diff --git a/src/common/utils/delay.ts b/src/common/utils/delay.ts index 208e042759..7d0686d29b 100644 --- a/src/common/utils/delay.ts +++ b/src/common/utils/delay.ts @@ -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 { + return new Promise(resolve => setTimeout(resolve, timeout)); } diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 6f26bab2da..2bdd20b844 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -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"; diff --git a/src/main/protocol-handler/__test__/router.test.ts b/src/main/protocol-handler/__test__/router.test.ts index a46da3fe9f..4ac94dcbb7 100644 --- a/src/main/protocol-handler/__test__/router.test.ts +++ b/src/main/protocol-handler/__test__/router.test.ts @@ -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"); }); });