more e2e tuning (#614)

* more e2e tuning

* prettier
This commit is contained in:
ABevier 2023-05-15 19:53:27 -04:00 committed by GitHub
parent 7d4469418b
commit 67edf9971b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 73 deletions

View file

@ -4,6 +4,11 @@ export const setSentryLogging = (sentry: any) => {
const oldError = log.error; const oldError = log.error;
log.error = (...params: any[]) => { log.error = (...params: any[]) => {
if (process.env.TEST === "true") {
log.info(params);
return;
}
oldError(params); oldError(params);
sentry.captureException(params[0].message); sentry.captureException(params[0].message);
}; };

View file

@ -125,6 +125,7 @@
<ToolTip> <ToolTip>
<Button <Button
slot="target" slot="target"
data-testid="uninstall-button"
class="h-10" class="h-10"
type="plain" type="plain"
color="blue" color="blue"

View file

@ -249,11 +249,9 @@ const uninstallPkg = async (pkg: GUIPackage) => {
await deletePkg(pkg, v); await deletePkg(pkg, v);
} }
await withDelay(() => { updatePackage(pkg.full_name, {
updatePackage(pkg.full_name, { installed_versions: []
installed_versions: [] });
});
}, 1000);
} catch (error) { } catch (error) {
log.error(error); log.error(error);
notificationStore.add({ notificationStore.add({

View file

@ -1,5 +1,5 @@
import { browser } from "wdio-electron-service"; import { browser } from "wdio-electron-service";
import { setupUtils, sleep } from "./utils.ts"; import { setupUtils } from "./utils.ts";
type utilType = ReturnType<typeof setupUtils>; type utilType = ReturnType<typeof setupUtils>;
@ -30,19 +30,10 @@ describe("basic smoke test", () => {
// Be nice to devs running this over and over // Be nice to devs running this over and over
await utils.uninstallPackageIfNeeded(); await utils.uninstallPackageIfNeeded();
await utils.installLatestVersion(); await utils.installLatestVersion("tea_xyz_brewkit");
//use findByText to wait for the install to complete await utils.verifyAndCloseNotification(/^Package tea.xyz\/brewkit .* has been installed./);
await expect(
await screen.findByText(
/^Package tea.xyz\/brewkit .* has been installed./,
{},
{ timeout: 60000, interval: 1000 }
)
).toExist();
await expect(await screen.findByRole("button", { name: "OPEN IN TERMINAL" })).toExist(); await expect(await screen.findByRole("button", { name: "OPEN IN TERMINAL" })).toExist();
await utils.closeNotification();
}); });
it("search and install create-dmg", async () => { it("search and install create-dmg", async () => {
@ -58,17 +49,11 @@ describe("basic smoke test", () => {
await utils.packageDetailsLoaded(); await utils.packageDetailsLoaded();
await utils.uninstallPackageIfNeeded(); await utils.uninstallPackageIfNeeded();
await utils.installLatestVersion(); await utils.installLatestVersion("github_com_create_dmg_create_dmg");
await expect( await utils.verifyAndCloseNotification(
await screen.findByText( /^Package github.com\/create-dmg\/create-dmg .* has been installed./
/^Package github.com\/create-dmg\/create-dmg .* has been installed./, );
{},
{ timeout: 60000, interval: 1000 }
)
).toExist();
await utils.closeNotification();
}); });
it("should be able to install specific version", async () => { it("should be able to install specific version", async () => {
@ -79,42 +64,23 @@ describe("basic smoke test", () => {
pnpmCard.click(); pnpmCard.click();
await utils.uninstallPackageIfNeeded(); await utils.uninstallPackageIfNeeded();
await utils.installSpecificVersion("pnpm_io", "8.0.0");
await utils.installSpecificVersion("8.0.0"); await utils.verifyAndCloseNotification(/^Package pnpm.io .* has been installed./);
await expect( // Now test the update
await screen.findByText( await utils.goHome();
/^Package pnpm.io .* has been installed./,
{},
{ timeout: 60000, interval: 1000 }
)
).toExist();
await utils.closeNotification();
});
it("should be able to update a package", async () => {
// this requires ^ to succeed first
const { screen } = utils!;
const menuBtn = await screen.findByTestId("menu-button-updates-available"); const menuBtn = await screen.findByTestId("menu-button-updates-available");
menuBtn.click(); menuBtn.click();
const header = await screen.findByText("available updates"); const header = await screen.findByText("available updates");
await expect(header).toExist(); await expect(header).toExist();
const updateBtn = await screen.findByTestId("install-button-pnpm_io"); const updateBtn = await utils.findByTestId("install-button-pnpm_io");
await expect(updateBtn).toExist(); await expect(updateBtn).toExist();
updateBtn.click(); updateBtn.click();
await expect( await utils.verifyAndCloseNotification(/^Package pnpm.io .* has been installed./);
await screen.findByText(
/^Package pnpm.io .* has been installed./,
{},
{ timeout: 60000, interval: 1000 }
)
).toExist();
await utils.closeNotification();
}); });
}); });

View file

@ -1,4 +1,5 @@
import * as testingLibraryWdio from "@testing-library/webdriverio"; import * as testingLibraryWdio from "@testing-library/webdriverio";
import { waitForNotExist } from "./waitutils.ts";
// work around for importing CommonJS module // work around for importing CommonJS module
const { setupBrowser } = testingLibraryWdio; const { setupBrowser } = testingLibraryWdio;
@ -11,6 +12,14 @@ export function setupUtils(browser: WebdriverIO.Browser) {
return (await screen.findByRole("button", { name })) as unknown as HTMLElement; return (await screen.findByRole("button", { name })) as unknown as HTMLElement;
}; };
const findByTestId = async (testId: string) => {
return (await screen.findByTestId(
testId,
{},
{ interval: 1000, timeout: 10000 }
)) as unknown as HTMLElement;
};
// //
// Package List Page // Package List Page
// //
@ -40,31 +49,34 @@ export function setupUtils(browser: WebdriverIO.Browser) {
}; };
const uninstallPackageIfNeeded = async () => { const uninstallPackageIfNeeded = async () => {
const uninstallButton = (await screen.queryByRole("button", { const uninstallButton = (await screen.queryByTestId(
name: "UNINSTALL" "uninstall-button"
})) as unknown as HTMLElement; )) as unknown as HTMLElement;
console.log(`will uninstall package = ${!!uninstallButton}`);
if (uninstallButton) { if (uninstallButton) {
uninstallButton.click(); uninstallButton.click();
// wait for the install button to show back up // wait for the uninstall button to disappear
await screen.findByRole("button", { name: /^INSTALL / }, { timeout: 60000, interval: 1000 }); await waitForNotExist(() => screen.queryByTestId("uninstall-button"), { timeout: 20000 });
} }
}; };
const installLatestVersion = async () => { const installLatestVersion = async (slug: string) => {
await installSpecificVersion("latest"); await installSpecificVersion(slug, "latest");
}; };
const installSpecificVersion = async (version: string) => { const installSpecificVersion = async (slug: string, version: string) => {
const installButton = await findButton(/^INSTALL |^UPDATE/); console.log(`Installing package: ${slug}@${version}`);
const installButton = await findByTestId(`install-button-${slug}`);
expect(installButton).toExist();
installButton.click(); installButton.click();
const versionButton = await screen.findByTestId(`install-${version}`); const versionButton = await findByTestId(`install-${version}`);
await versionButton.waitForExist(); expect(versionButton).toExist();
versionButton.click(); versionButton.click();
}; };
const goHome = async () => { const goHome = async () => {
// await browser.url("/");
const homeButton = await screen.findByTestId("home-button"); const homeButton = await screen.findByTestId("home-button");
await homeButton.click(); await homeButton.click();
const homeMenu = $("#side-menu"); const homeMenu = $("#side-menu");
@ -82,10 +94,17 @@ export function setupUtils(browser: WebdriverIO.Browser) {
}; };
const closeNotification = async () => { const closeNotification = async () => {
const closeNotificationBtn = $(".close-notification"); console.log("Closing notification");
const closeNotificationBtn = await findByTestId("close-notification");
await expect(closeNotificationBtn).toExist(); await expect(closeNotificationBtn).toExist();
await closeNotificationBtn.click(); closeNotificationBtn.click();
await expect(closeNotificationBtn).not.toExist(); await waitForNotExist(() => screen.queryByTestId("close-notification"));
};
// verify a notification matching the regex is shown and then close it
const verifyAndCloseNotification = async (regex: RegExp) => {
await expect(await screen.findByText(regex, {}, { timeout: 30000, interval: 1000 })).toExist();
await closeNotification();
}; };
return { return {
@ -93,14 +112,14 @@ export function setupUtils(browser: WebdriverIO.Browser) {
searchTerm, searchTerm,
goHome, goHome,
findButton, findButton,
findByTestId,
findPackageCardBySlug, findPackageCardBySlug,
findSearchPackageCardBySlug, findSearchPackageCardBySlug,
packageDetailsLoaded, packageDetailsLoaded,
uninstallPackageIfNeeded, uninstallPackageIfNeeded,
installLatestVersion, installLatestVersion,
installSpecificVersion, installSpecificVersion,
closeNotification closeNotification,
verifyAndCloseNotification
}; };
} }
export const sleep = (delayMs: number) => new Promise((resolve) => setTimeout(resolve, delayMs));

View file

@ -0,0 +1,34 @@
export const sleep = (delayMs: number) => new Promise((resolve) => setTimeout(resolve, delayMs));
export type WaitOpts = { timeout?: number; interval?: number };
// wait for a query to return a non-truthy value
export const waitForNotExist = async (
query: () => Promise<WebdriverIO.Element | null>,
opts: WaitOpts = {}
) => {
return waitFor(async () => await expect(await query()).not.toExist(), opts);
};
export const waitFor = async (
action: () => Promise<void>,
{ interval = 1000, timeout = 5000 }: WaitOpts = {}
) => {
const start = Date.now();
let lastErr;
console.log("Wait For", { interval, timeout });
while (Date.now() - start < timeout) {
try {
await action();
return;
} catch (e) {
// swallow it and keep trying
lastErr = e;
}
await sleep(interval);
}
throw new Error(`waitFor timed out. Last error: ${lastErr}`);
};

View file

@ -27,7 +27,7 @@ export const config: Options.Testrunner = {
browserName: "chrome" // or "firefox", "microsoftedge", "safari" browserName: "chrome" // or "firefox", "microsoftedge", "safari"
} }
], ],
logLevel: "debug", logLevel: "info",
bail: 0, bail: 0,
baseUrl: "http://localhost", baseUrl: "http://localhost",
waitforTimeout: 10000, waitforTimeout: 10000,
@ -54,6 +54,6 @@ export const config: Options.Testrunner = {
ui: "bdd", ui: "bdd",
timeout: 120000 timeout: 120000
}, },
specFileRetries: 3, specFileRetries: 2,
specFileRetriesDelay: 5 specFileRetriesDelay: 5
}; };

View file

@ -28,7 +28,11 @@
}}>{notification.callback_label}</button }}>{notification.callback_label}</button
> >
{/if} {/if}
<button class="close-notification icon-tea-x-btn mt-1 text-xs" on:click={onClose} /> <button
data-testid="close-notification"
class="close-notification icon-tea-x-btn mt-1 text-xs"
on:click={onClose}
/>
</div> </div>
</div> </div>