mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
desktop: migrate tests to vitest 3
This commit is contained in:
@@ -17,214 +17,210 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { test } from "vitest";
|
import { test, testCleanup } from "./utils.js";
|
||||||
import { harness } from "./utils.js";
|
|
||||||
import { writeFile } from "fs/promises";
|
import { writeFile } from "fs/promises";
|
||||||
import { Page } from "playwright";
|
import { Page } from "playwright";
|
||||||
import { gt, lt } from "semver";
|
import { gt, lt } from "semver";
|
||||||
|
import { describe } from "vitest";
|
||||||
|
|
||||||
test("update starts downloading if version is outdated", async (t) => {
|
test("update starts downloading if version is outdated", async ({
|
||||||
await harness(
|
ctx: { page },
|
||||||
t,
|
expect,
|
||||||
async ({ page }) => {
|
onTestFinished
|
||||||
await page.waitForSelector("#authForm");
|
}) => {
|
||||||
|
onTestFinished(testCleanup);
|
||||||
|
|
||||||
t.expect(
|
await page.waitForSelector("#authForm");
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
expect(
|
||||||
).toBe(true);
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
await skipDialog(page);
|
await skipDialog(page);
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
await page.waitForSelector(".ProseMirror");
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.locator(".theme-scope-statusBar")
|
.locator(".theme-scope-statusBar")
|
||||||
.getByRole("button", { name: /updating/i })
|
.getByRole("button", { name: /updating/i })
|
||||||
.waitFor({ state: "attached" });
|
.waitFor({ state: "attached" });
|
||||||
},
|
|
||||||
{ version: "3.0.0" }
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("update is only shown if version is outdated and auto updates are disabled", async (t) => {
|
test("update is only shown if version is outdated and auto updates are disabled", async ({
|
||||||
await harness(
|
ctx,
|
||||||
t,
|
expect,
|
||||||
async (ctx) => {
|
onTestFinished
|
||||||
await ctx.app.close();
|
}) => {
|
||||||
await writeFile(
|
onTestFinished(testCleanup);
|
||||||
ctx.configPath,
|
|
||||||
JSON.stringify({
|
|
||||||
automaticUpdates: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await ctx.relaunch();
|
await ctx.app.close();
|
||||||
|
await writeFile(
|
||||||
|
ctx.configPath,
|
||||||
|
JSON.stringify({
|
||||||
|
automaticUpdates: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const { page } = ctx;
|
await ctx.relaunch();
|
||||||
|
|
||||||
await page.waitForSelector("#authForm");
|
const { page } = ctx;
|
||||||
|
|
||||||
t.expect(
|
await page.waitForSelector("#authForm");
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
|
||||||
).toBe(true);
|
|
||||||
|
|
||||||
await page
|
expect(
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
.click();
|
).toBe(true);
|
||||||
|
|
||||||
await skipDialog(page);
|
await page
|
||||||
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
|
.click();
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
await skipDialog(page);
|
||||||
|
|
||||||
|
await page.waitForSelector(".ProseMirror");
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator(".theme-scope-statusBar")
|
||||||
|
.getByRole("button", { name: /available/i })
|
||||||
|
.waitFor({ state: "attached" });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("update to stable if it is newer", () => {
|
||||||
|
test.scoped({ options: { version: "3.0.0-beta.0" } });
|
||||||
|
test("test", async ({ ctx, expect, onTestFinished }) => {
|
||||||
|
onTestFinished(testCleanup);
|
||||||
|
|
||||||
|
await ctx.app.close();
|
||||||
|
await writeFile(
|
||||||
|
ctx.configPath,
|
||||||
|
JSON.stringify({
|
||||||
|
automaticUpdates: false,
|
||||||
|
releaseTrack: "beta"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await ctx.relaunch();
|
||||||
|
|
||||||
|
const { page } = ctx;
|
||||||
|
|
||||||
|
await page.waitForSelector("#authForm");
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await skipDialog(page);
|
||||||
|
|
||||||
|
await page.waitForSelector(".ProseMirror");
|
||||||
|
|
||||||
|
const updateButton = page
|
||||||
|
.locator(".theme-scope-statusBar")
|
||||||
|
.getByRole("button", { name: /available/i });
|
||||||
|
await updateButton.waitFor({ state: "visible" });
|
||||||
|
const content = await updateButton.textContent();
|
||||||
|
const version = content?.split(" ")?.[0] || "";
|
||||||
|
expect(gt(version, "3.0.0-beta.0")).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("update is not available if it latest stable version is older", () => {
|
||||||
|
test.scoped({ options: { version: "99.0.0-beta.0" } });
|
||||||
|
test("test", async ({ ctx, expect, onTestFinished }) => {
|
||||||
|
onTestFinished(testCleanup);
|
||||||
|
|
||||||
|
await ctx.app.close();
|
||||||
|
await writeFile(
|
||||||
|
ctx.configPath,
|
||||||
|
JSON.stringify({
|
||||||
|
automaticUpdates: false,
|
||||||
|
releaseTrack: "beta"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await ctx.relaunch();
|
||||||
|
|
||||||
|
const { page } = ctx;
|
||||||
|
|
||||||
|
await page.waitForSelector("#authForm");
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await skipDialog(page);
|
||||||
|
|
||||||
|
await page.waitForSelector(".ProseMirror");
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator(".theme-scope-statusBar")
|
||||||
|
.getByRole("button", { name: /checking for updates/i })
|
||||||
|
.waitFor({ state: "hidden" });
|
||||||
|
|
||||||
|
expect(
|
||||||
await page
|
await page
|
||||||
.locator(".theme-scope-statusBar")
|
.locator(".theme-scope-statusBar")
|
||||||
.getByRole("button", { name: /available/i })
|
.getByRole("button", { name: /available/i })
|
||||||
.waitFor({ state: "attached" });
|
.isHidden()
|
||||||
},
|
).toBe(true);
|
||||||
{ version: "3.0.0" }
|
});
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("update to stable if it is newer", async (t) => {
|
describe("downgrade to stable on switching to stable release track", () => {
|
||||||
await harness(
|
test.scoped({ options: { version: "99.0.0-beta.0" } });
|
||||||
t,
|
test("test", async ({ ctx, expect, onTestFinished }) => {
|
||||||
async (ctx) => {
|
onTestFinished(testCleanup);
|
||||||
await ctx.app.close();
|
|
||||||
await writeFile(
|
|
||||||
ctx.configPath,
|
|
||||||
JSON.stringify({
|
|
||||||
automaticUpdates: false,
|
|
||||||
releaseTrack: "beta"
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await ctx.relaunch();
|
await ctx.app.close();
|
||||||
|
await writeFile(
|
||||||
|
ctx.configPath,
|
||||||
|
JSON.stringify({
|
||||||
|
automaticUpdates: false,
|
||||||
|
releaseTrack: "stable"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const { page } = ctx;
|
await ctx.relaunch();
|
||||||
|
|
||||||
await page.waitForSelector("#authForm");
|
const { page } = ctx;
|
||||||
|
|
||||||
t.expect(
|
await page.waitForSelector("#authForm");
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
|
||||||
).toBe(true);
|
|
||||||
|
|
||||||
await page
|
expect(
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
.click();
|
).toBe(true);
|
||||||
|
|
||||||
await skipDialog(page);
|
await page
|
||||||
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
|
.click();
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
await skipDialog(page);
|
||||||
|
|
||||||
const updateButton = page
|
await page.waitForSelector(".ProseMirror");
|
||||||
.locator(".theme-scope-statusBar")
|
|
||||||
.getByRole("button", { name: /available/i });
|
|
||||||
await updateButton.waitFor({ state: "visible" });
|
|
||||||
const content = await updateButton.textContent();
|
|
||||||
const version = content?.split(" ")?.[0] || "";
|
|
||||||
t.expect(gt(version, "3.0.0-beta.0")).toBe(true);
|
|
||||||
},
|
|
||||||
{ version: "3.0.0-beta.0" }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("update is not available if it latest stable version is older", async (t) => {
|
await page
|
||||||
await harness(
|
.locator(".theme-scope-statusBar")
|
||||||
t,
|
.getByRole("button", { name: /checking for updates/i })
|
||||||
async (ctx) => {
|
.waitFor({ state: "hidden" });
|
||||||
await ctx.app.close();
|
|
||||||
await writeFile(
|
|
||||||
ctx.configPath,
|
|
||||||
JSON.stringify({
|
|
||||||
automaticUpdates: false,
|
|
||||||
releaseTrack: "beta"
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await ctx.relaunch();
|
const updateButton = page
|
||||||
|
.locator(".theme-scope-statusBar")
|
||||||
const { page } = ctx;
|
.getByRole("button", { name: /available/i });
|
||||||
|
await updateButton.waitFor({ state: "visible" });
|
||||||
await page.waitForSelector("#authForm");
|
const content = await updateButton.textContent();
|
||||||
|
const version = content?.split(" ")?.[0] || "";
|
||||||
t.expect(
|
expect(lt(version, "99.0.0-beta.0")).toBe(true);
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
});
|
||||||
).toBe(true);
|
|
||||||
|
|
||||||
await page
|
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await skipDialog(page);
|
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
|
||||||
|
|
||||||
await page
|
|
||||||
.locator(".theme-scope-statusBar")
|
|
||||||
.getByRole("button", { name: /checking for updates/i })
|
|
||||||
.waitFor({ state: "hidden" });
|
|
||||||
|
|
||||||
t.expect(
|
|
||||||
await page
|
|
||||||
.locator(".theme-scope-statusBar")
|
|
||||||
.getByRole("button", { name: /available/i })
|
|
||||||
.isHidden()
|
|
||||||
).toBe(true);
|
|
||||||
},
|
|
||||||
{ version: "99.0.0-beta.0" }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("downgrade to stable on switching to stable release track", async (t) => {
|
|
||||||
await harness(
|
|
||||||
t,
|
|
||||||
async (ctx) => {
|
|
||||||
await ctx.app.close();
|
|
||||||
await writeFile(
|
|
||||||
ctx.configPath,
|
|
||||||
JSON.stringify({
|
|
||||||
automaticUpdates: false,
|
|
||||||
releaseTrack: "stable"
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await ctx.relaunch();
|
|
||||||
|
|
||||||
const { page } = ctx;
|
|
||||||
|
|
||||||
await page.waitForSelector("#authForm");
|
|
||||||
|
|
||||||
t.expect(
|
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
|
||||||
).toBe(true);
|
|
||||||
|
|
||||||
await page
|
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await skipDialog(page);
|
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
|
||||||
|
|
||||||
await page
|
|
||||||
.locator(".theme-scope-statusBar")
|
|
||||||
.getByRole("button", { name: /checking for updates/i })
|
|
||||||
.waitFor({ state: "hidden" });
|
|
||||||
|
|
||||||
const updateButton = page
|
|
||||||
.locator(".theme-scope-statusBar")
|
|
||||||
.getByRole("button", { name: /available/i });
|
|
||||||
await updateButton.waitFor({ state: "visible" });
|
|
||||||
const content = await updateButton.textContent();
|
|
||||||
const version = content?.split(" ")?.[0] || "";
|
|
||||||
t.expect(lt(version, "99.0.0-beta.0")).toBe(true);
|
|
||||||
},
|
|
||||||
{ version: "99.0.0-beta.0" }
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function skipDialog(page: Page) {
|
async function skipDialog(page: Page) {
|
||||||
@@ -237,9 +233,9 @@ async function skipDialog(page: Page) {
|
|||||||
"button[data-role='negative-button']"
|
"button[data-role='negative-button']"
|
||||||
);
|
);
|
||||||
if (await positiveButton.isVisible())
|
if (await positiveButton.isVisible())
|
||||||
await positiveButton.click({ timeout: 2000 });
|
await positiveButton.click({ timeout: 1000 });
|
||||||
else if (await negativeButton.isVisible())
|
else if (await negativeButton.isVisible())
|
||||||
await negativeButton.click({ timeout: 2000 });
|
await negativeButton.click({ timeout: 1000 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore error
|
// ignore error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,22 +17,24 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { test } from "vitest";
|
import { testCleanup, test } from "./utils.js";
|
||||||
import { harness } from "./utils.js";
|
|
||||||
import assert from "assert";
|
|
||||||
|
|
||||||
test("make sure app loads", async (t) => {
|
test("make sure app loads", async ({
|
||||||
await harness(t, async ({ page }) => {
|
ctx: { page },
|
||||||
await page.waitForSelector("#authForm");
|
expect,
|
||||||
|
onTestFinished
|
||||||
|
}) => {
|
||||||
|
onTestFinished(testCleanup);
|
||||||
|
|
||||||
assert.ok(
|
await page.waitForSelector("#authForm");
|
||||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
|
||||||
);
|
|
||||||
|
|
||||||
await page
|
expect(
|
||||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||||
.click();
|
).toBe(true);
|
||||||
|
|
||||||
await page.waitForSelector(".ProseMirror");
|
await page
|
||||||
});
|
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page.waitForSelector(".ProseMirror");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { fileURLToPath } from "node:url";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { _electron as electron } from "playwright";
|
import { _electron as electron } from "playwright";
|
||||||
import slugify from "slugify";
|
import slugify from "slugify";
|
||||||
import { TaskContext } from "vitest";
|
import { test as vitestTest, TestContext } from "vitest";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
@@ -42,31 +42,34 @@ interface TestOptions {
|
|||||||
version: string;
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function harness(
|
interface Fixtures {
|
||||||
t: TaskContext,
|
options: TestOptions;
|
||||||
cb: (ctx: AppContext) => Promise<void>,
|
ctx: AppContext;
|
||||||
options?: TestOptions
|
}
|
||||||
) {
|
|
||||||
const ctx = await buildAndLaunchApp(options);
|
|
||||||
|
|
||||||
t.onTestFinished(async (result) => {
|
export const test = vitestTest.extend<Fixtures>({
|
||||||
if (result.state === "fail") {
|
options: { version: "3.0.0" } as TestOptions,
|
||||||
await mkdir("test-results", { recursive: true });
|
ctx: async ({ options }, use) => {
|
||||||
await ctx.page.screenshot({
|
const ctx = await buildAndLaunchApp(options);
|
||||||
path: path.join(
|
await use(ctx);
|
||||||
"test-results",
|
|
||||||
`${slugify(t.task.name)}-${process.platform}-${
|
|
||||||
process.arch
|
|
||||||
}-error.png`
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await ctx.app.close();
|
await ctx.app.close();
|
||||||
await rm(ctx.userDataDir, { recursive: true, force: true });
|
await rm(ctx.userDataDir, { recursive: true, force: true });
|
||||||
await rm(ctx.outputDir, { recursive: true, force: true });
|
await rm(ctx.outputDir, { recursive: true, force: true });
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await cb(ctx);
|
export async function testCleanup(context: TestContext) {
|
||||||
|
if (context.task.result?.state === "fail") {
|
||||||
|
await mkdir("test-results", { recursive: true });
|
||||||
|
await (context.task.context as unknown as Fixtures).ctx.page.screenshot({
|
||||||
|
path: path.join(
|
||||||
|
"test-results",
|
||||||
|
`${slugify(context.task.name)}-${process.platform}-${
|
||||||
|
process.arch
|
||||||
|
}-error.png`
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAndLaunchApp(options?: TestOptions): Promise<AppContext> {
|
async function buildAndLaunchApp(options?: TestOptions): Promise<AppContext> {
|
||||||
|
|||||||
Reference in New Issue
Block a user