mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Upgrade to electron 12 and Node 14
- Compute cluster ID for tests - Switch to temporary appData path while testing Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
ac2ce1ba57
commit
2d75fd6717
11 files changed
+112
-97
No files matched your search
@@ -27,8 +27,6 @@
|
||||
*/
|
||||
import * as utils from "../helpers/utils";
|
||||
|
||||
jest.setTimeout(20_000);
|
||||
|
||||
describe("preferences page tests", () => {
|
||||
it('shows "preferences" and can navigate through the tabs', async () => {
|
||||
const { window, cleanup } = await utils.start();
|
||||
@@ -59,15 +57,9 @@ describe("preferences page tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
|
||||
it("ensures helm repos", async () => {
|
||||
const repos = await utils.listHelmRepositories();
|
||||
|
||||
if (repos.length === 0) {
|
||||
fail("Lens failed to add any repositories");
|
||||
}
|
||||
|
||||
const { window, cleanup } = await utils.start();
|
||||
|
||||
try {
|
||||
@@ -75,7 +67,7 @@ describe("preferences page tests", () => {
|
||||
await window.keyboard.press("Meta+,");
|
||||
|
||||
await window.click("[data-testid=kubernetes-tab]");
|
||||
await window.waitForSelector(`[data-testid=repository-name] >> text=${repos[0].name}`, {
|
||||
await window.waitForSelector("[data-testid=repository-name]", {
|
||||
timeout: 100_000,
|
||||
});
|
||||
await window.click("#HelmRepoSelect");
|
||||
@@ -83,5 +75,5 @@ describe("preferences page tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
}, 120_000);
|
||||
}, 10*60*1000);
|
||||
});
|
||||
@@ -30,8 +30,6 @@ import { minikubeReady } from "../helpers/minikube";
|
||||
|
||||
const TEST_NAMESPACE = "integration-tests";
|
||||
|
||||
jest.setTimeout(30_000);
|
||||
|
||||
function getSidebarSelectors(itemId: string) {
|
||||
const root = `.SidebarItem[data-test-id="${itemId}"]`;
|
||||
|
||||
@@ -252,7 +250,7 @@ const commonPageTests: CommonPageTest[] = [{
|
||||
name: "Releases",
|
||||
href: "apps/releases",
|
||||
expectedSelector: "h5.title",
|
||||
expectedText: "Helm Releases"
|
||||
expectedText: "Releases"
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -344,7 +342,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
|
||||
it("show logs and highlight the log search entries", async () => {
|
||||
const { window, cleanup } = await utils.start();
|
||||
@@ -354,11 +352,11 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
|
||||
const frame = await utils.lauchMinikubeClusterFromCatalog(window);
|
||||
|
||||
if ((await frame.innerText(`a[href^="/workloads"] .Icon .icon`)) === "keyboard_arrow_down") {
|
||||
await frame.click(`a[href^="/workloads"]`);
|
||||
if ((await frame.innerText(`a[href="/workloads"] .expand-icon`)) === "keyboard_arrow_down") {
|
||||
await frame.click(`a[href="/workloads"]`);
|
||||
}
|
||||
|
||||
await frame.click(`a[href^="/pods"]`);
|
||||
await frame.click(`a[href="/pods"]`);
|
||||
|
||||
const namespacesSelector = await frame.waitForSelector(".NamespaceSelect");
|
||||
|
||||
@@ -395,7 +393,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
|
||||
it("should show the default namespaces", async () => {
|
||||
const { window, cleanup } = await utils.start();
|
||||
@@ -411,7 +409,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
|
||||
it(`should create the ${TEST_NAMESPACE} and a pod in the namespace`, async () => {
|
||||
const { window, cleanup } = await utils.start();
|
||||
@@ -430,9 +428,9 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
await namespaceNameInput.type(TEST_NAMESPACE);
|
||||
await namespaceNameInput.press("Enter");
|
||||
|
||||
await frame.waitForSelector(`div.TableCell >> text='${TEST_NAMESPACE}'`);
|
||||
await frame.waitForSelector(`div.TableCell >> text=${TEST_NAMESPACE}`);
|
||||
|
||||
if ((await frame.innerText(`a[href^="/workloads"] .Icon .icon`)) === "keyboard_arrow_down") {
|
||||
if ((await frame.innerText(`a[href^="/workloads"] .expand-icon`)) === "keyboard_arrow_down") {
|
||||
await frame.click(`a[href^="/workloads"]`);
|
||||
}
|
||||
|
||||
@@ -446,14 +444,24 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
await namespacesSelector.click();
|
||||
|
||||
await frame.click(".Icon.new-dock-tab");
|
||||
await frame.waitForTimeout(500); // TODO: fix menus to be less flaky
|
||||
const createResourceTabButtom = await frame.waitForSelector("li.MenuItem.create-resource-tab");
|
||||
|
||||
await frame.waitForTimeout(500); // TODO: fix menus to be less flaky
|
||||
await createResourceTabButtom.click();
|
||||
try {
|
||||
await frame.click("li.MenuItem.create-resource-tab", {
|
||||
// NOTE: the following shouldn't be required, but is because without it a TypeError is thrown
|
||||
// see: https://github.com/microsoft/playwright/issues/8229
|
||||
position: {
|
||||
y: 0,
|
||||
x: 0,
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
await frame.waitForTimeout(100_000);
|
||||
}
|
||||
|
||||
const inputField = await frame.waitForSelector(".CreateResource div.ace_content");
|
||||
const inputField = await frame.waitForSelector(".CreateResource div.react-monaco-editor-container");
|
||||
|
||||
await inputField.click();
|
||||
await inputField.type("apiVersion: v1", { delay: 10 });
|
||||
await inputField.press("Enter", { delay: 10 });
|
||||
await inputField.type("kind: Pod", { delay: 10 });
|
||||
@@ -480,5 +488,5 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
});
|
||||
@@ -21,8 +21,6 @@
|
||||
|
||||
import * as utils from "../helpers/utils";
|
||||
|
||||
jest.setTimeout(20_000);
|
||||
|
||||
describe("Lens command palette", () => {
|
||||
describe("menu", () => {
|
||||
it("opens command dialog from keyboard shortcut", async () => {
|
||||
@@ -35,6 +33,6 @@ describe("Lens command palette", () => {
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
}, 10*60*1000);
|
||||
});
|
||||
});
|
||||
@@ -18,9 +18,12 @@
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import * as util from "util";
|
||||
import { exec } from "child_process";
|
||||
import { Frame, Page, _electron as electron } from "playwright";
|
||||
import { createHash } from "crypto";
|
||||
import { mkdirp, remove } from "fs-extra";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as uuid from "uuid";
|
||||
import { ElectronApplication, Frame, Page, _electron as electron } from "playwright";
|
||||
|
||||
export const AppPaths: Partial<Record<NodeJS.Platform, string>> = {
|
||||
"win32": "./dist/win-unpacked/OpenLens.exe",
|
||||
@@ -36,52 +39,74 @@ export function describeIf(condition: boolean) {
|
||||
return condition ? describe : describe.skip;
|
||||
}
|
||||
|
||||
export const promiseExec = util.promisify(exec);
|
||||
async function getMainWindow(app: ElectronApplication, timeout = 50_000): Promise<Page> {
|
||||
const deadline = Date.now() + timeout;
|
||||
|
||||
type HelmRepository = {
|
||||
name: string;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export async function listHelmRepositories(): Promise<HelmRepository[]>{
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
try {
|
||||
const { stdout } = await promiseExec("helm repo list -o json");
|
||||
|
||||
return JSON.parse(stdout);
|
||||
} catch {
|
||||
await new Promise(r => setTimeout(r, 2000)); // if no repositories, wait for Lens adding bitnami repository
|
||||
for (; Date.now() < deadline;) {
|
||||
for (const page of app.windows()) {
|
||||
if (page.url().startsWith("http://localhost")) {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2_000));
|
||||
}
|
||||
|
||||
return [];
|
||||
throw new Error(`Lens did not open the main window within ${timeout}ms`);
|
||||
}
|
||||
|
||||
async function closeApp(app: ElectronApplication, timeout = 30_000) {
|
||||
// TODO: change once timeouts for the native function are available
|
||||
await Promise.race([
|
||||
app.evaluateHandle(({ app }) => app.quit()),
|
||||
new Promise((r, reject) => setTimeout(() => reject(`Lens failed to quit within ${timeout}ms`), timeout)),
|
||||
]);
|
||||
}
|
||||
|
||||
export async function start() {
|
||||
const CICD = path.join(os.tmpdir(), "lens-integration-testing", uuid.v4());
|
||||
|
||||
// Make sure that the directory is clear
|
||||
await remove(CICD);
|
||||
await mkdirp(CICD);
|
||||
|
||||
const app = await electron.launch({
|
||||
args: ["--integration-testing"], // this argument turns off the blocking of quit
|
||||
executablePath: AppPaths[process.platform],
|
||||
bypassCSP: true,
|
||||
});
|
||||
env: { CICD },
|
||||
timeout: 100_000,
|
||||
} as Parameters<typeof electron["launch"]>[0]);
|
||||
|
||||
const window = await app.waitForEvent("window", {
|
||||
predicate: async (page) => page.url().startsWith("http://localhost"),
|
||||
});
|
||||
try {
|
||||
const window = await getMainWindow(app);
|
||||
|
||||
return {
|
||||
app,
|
||||
window,
|
||||
cleanup: async () => {
|
||||
await window.close();
|
||||
await app.close();
|
||||
},
|
||||
};
|
||||
return {
|
||||
app,
|
||||
window,
|
||||
cleanup: async () => {
|
||||
try {
|
||||
await window.close();
|
||||
} catch {}
|
||||
await closeApp(app);
|
||||
await remove(CICD);
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
await closeApp(app);
|
||||
await remove(CICD);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function clickWelcomeButton(window: Page) {
|
||||
await window.click("#hotbarIcon-catalog-entity .Icon");
|
||||
}
|
||||
|
||||
function minikubeEntityId() {
|
||||
return createHash("md5").update(`${path.join(os.homedir(), ".kube", "config")}:minikube`).digest("hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* From the catalog, click the minikube entity and wait for it to connect, returning its frame
|
||||
*/
|
||||
@@ -91,7 +116,7 @@ export async function lauchMinikubeClusterFromCatalog(window: Page): Promise<Fra
|
||||
await window.waitForSelector("div.drawer-title-text >> text='KubernetesCluster: minikube'");
|
||||
await window.click("div.EntityIcon div.HotbarIcon div div.MuiAvatar-root");
|
||||
|
||||
const minikubeFrame = await window.waitForSelector("#cluster-frame-484e864bad9b84ce5d6b4fff704cc0e4");
|
||||
const minikubeFrame = await window.waitForSelector(`#cluster-frame-${minikubeEntityId()}`);
|
||||
|
||||
const frame = await minikubeFrame.contentFrame();
|
||||
|
||||
|
||||
Reference in new issue
Block a user