diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..07e7d981 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +node-options=--experimental-strip-types diff --git a/package-lock.json b/package-lock.json index 5523a3f4..f4b2d287 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,10 @@ "@types/backoff": "^2.5.2", "@types/i18n": "^0.13.1", "@types/node": "^22.13.10", + "@types/p-fifo": "^1.0.2", "@types/requestidlecallback": "^0.3.4", "@types/semver": "^7.5.8", + "@types/tape": "^5.8.1", "@types/yaireo__tagify": "^4.3.2", "@yaireo/tagify": "^4.5.0", "adm-zip": "^0.5.5", @@ -3325,6 +3327,13 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/p-fifo": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/p-fifo/-/p-fifo-1.0.2.tgz", + "integrity": "sha512-Iz9wP2le1TQnvXNgPHwvr+16LcmT8T5DRijQCATOdVyL5xOMM/oBUIPFxRs4YJyqiKP5I1XC9vDI4zDxwGpDPA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/pg": { "version": "8.15.5", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz", @@ -3414,6 +3423,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tape": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/@types/tape/-/tape-5.8.1.tgz", + "integrity": "sha512-vRjK+E1c+I4WRDSXcYfgepPjz2Knh+gulU3359LrR9H2KM8AyiMbNmX7W5aMlw7JFoXMpVOhq3bEIm78qakGbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ljharb/through": "*", + "@types/node": "*", + "mock-property": "*" + } + }, "node_modules/@types/tedious": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", diff --git a/package.json b/package.json index 8311da10..c59e19ed 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "lint-js": "xo", "prettier-non-js": "prettier --check --log-level=warn . \"!**/*.{cjs,js,ts}\"", "test": "tsc && npm run lint-html && npm run lint-css && npm run lint-js && npm run prettier-non-js", - "test-e2e": "vite build && tape \"tests/**/*.js\"", + "test-e2e": "vite build && tape \"tests/**/*.ts\"", "pack": "vite build && electron-builder --dir", "dist": "vite build && electron-builder", "mas": "vite build && electron-builder --mac mas" @@ -162,8 +162,10 @@ "@types/backoff": "^2.5.2", "@types/i18n": "^0.13.1", "@types/node": "^22.13.10", + "@types/p-fifo": "^1.0.2", "@types/requestidlecallback": "^0.3.4", "@types/semver": "^7.5.8", + "@types/tape": "^5.8.1", "@types/yaireo__tagify": "^4.3.2", "@yaireo/tagify": "^4.5.0", "adm-zip": "^0.5.5", diff --git a/tests/index.js b/tests/index.ts similarity index 62% rename from tests/index.js rename to tests/index.ts index ccfb9f40..9a7b7583 100644 --- a/tests/index.js +++ b/tests/index.ts @@ -1,16 +1,17 @@ import Fifo from "p-fifo"; +import type {Page} from "playwright-core"; import test from "tape"; -import * as setup from "./setup.js"; +import * as setup from "./setup.ts"; test("app runs", async (t) => { t.timeoutAfter(10e3); setup.resetTestDataDirectory(); const app = await setup.createApp(); try { - const windows = new Fifo(); - for (const win of app.windows()) windows.push(win); - app.on("window", (win) => windows.push(win)); + const windows = new Fifo(); + for (const win of app.windows()) void windows.push(win); + app.on("window", async (win) => windows.push(win)); const mainWindow = await windows.shift(); t.equal(await mainWindow.title(), "Zulip"); diff --git a/tests/setup.js b/tests/setup.ts similarity index 56% rename from tests/setup.js rename to tests/setup.ts index 10707d5a..cb9dd74b 100644 --- a/tests/setup.js +++ b/tests/setup.ts @@ -1,43 +1,50 @@ import fs from "node:fs"; +import os from "node:os"; import path from "node:path"; import process from "node:process"; -import {_electron} from "playwright-core"; +import {type ElectronApplication, _electron} from "playwright-core"; +import z from "zod"; -const testsPackage = JSON.parse( - fs.readFileSync(new URL("package.json", import.meta.url), "utf8"), -); +const testsPackage = z + .object({productName: z.string()}) + .parse( + JSON.parse( + fs.readFileSync(new URL("package.json", import.meta.url), "utf8"), + ), + ); // Runs Zulip Desktop. // Returns a promise that resolves to an Electron Application once the app has loaded. -export function createApp() { +export async function createApp(): Promise { return _electron.launch({ args: [import.meta.dirname], // Ensure this dir has a package.json file with a 'main' entry point }); } // Quit the app, end the test -export async function endTest(app) { +export async function endTest(app: ElectronApplication): Promise { await app.close(); } -function getAppDataDirectory() { +function getAppDataDirectory(): string { let base; switch (process.platform) { case "darwin": { - base = path.join(process.env.HOME, "Library", "Application Support"); + base = path.join(os.homedir(), "Library", "Application Support"); break; } case "linux": { - base = - process.env.XDG_CONFIG_HOME ?? path.join(process.env.HOME, ".config"); + base = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"); break; } case "win32": { base = process.env.APPDATA; + if (base === undefined) + throw new Error("Missing APPDATA environment variable."); break; } @@ -51,7 +58,7 @@ function getAppDataDirectory() { } // Resets the test directory, containing domain.json, window-state.json, etc -export function resetTestDataDirectory() { +export function resetTestDataDirectory(): void { const appDataDirectory = getAppDataDirectory(); fs.rmSync(appDataDirectory, {force: true, recursive: true}); } diff --git a/tests/test-add-organization.js b/tests/test-add-organization.ts similarity index 71% rename from tests/test-add-organization.js rename to tests/test-add-organization.ts index 6d7aef49..2b634a51 100644 --- a/tests/test-add-organization.js +++ b/tests/test-add-organization.ts @@ -1,16 +1,17 @@ import Fifo from "p-fifo"; +import type {Page} from "playwright-core"; import test from "tape"; -import * as setup from "./setup.js"; +import * as setup from "./setup.ts"; test("add-organization", async (t) => { t.timeoutAfter(50e3); setup.resetTestDataDirectory(); const app = await setup.createApp(); try { - const windows = new Fifo(); - for (const win of app.windows()) windows.push(win); - app.on("window", (win) => windows.push(win)); + const windows = new Fifo(); + for (const win of app.windows()) void windows.push(win); + app.on("window", async (win) => windows.push(win)); const mainWindow = await windows.shift(); t.equal(await mainWindow.title(), "Zulip"); diff --git a/tests/test-new-organization.js b/tests/test-new-organization.ts similarity index 66% rename from tests/test-new-organization.js rename to tests/test-new-organization.ts index 0c8ba81d..ca8f69fa 100644 --- a/tests/test-new-organization.js +++ b/tests/test-new-organization.ts @@ -1,7 +1,8 @@ import Fifo from "p-fifo"; +import type {Page} from "playwright-core"; import test from "tape"; -import * as setup from "./setup.js"; +import * as setup from "./setup.ts"; // Create new org link should open in the default browser [WIP] @@ -10,9 +11,9 @@ test("new-org-link", async (t) => { setup.resetTestDataDirectory(); const app = await setup.createApp(); try { - const windows = new Fifo(); - for (const win of app.windows()) windows.push(win); - app.on("window", (win) => windows.push(win)); + const windows = new Fifo(); + for (const win of app.windows()) void windows.push(win); + app.on("window", async (win) => windows.push(win)); const mainWindow = await windows.shift(); t.equal(await mainWindow.title(), "Zulip");