import { assert, describe, it } from "@effect/vitest";import * as Cause from "effect/Cause";import * as Effect from "effect/Effect";import { beforeEach, vi } from "vite-plus/test"; const { autoUpdaterMock } = vi.hoisted(() => ({ autoUpdaterMock: { allowDowngrade: false, allowPrerelease: false, autoDownload: true, autoInstallOnAppQuit: true, channel: "latest", disableDifferentialDownload: false, checkForUpdates: vi.fn(() => Promise.resolve(null)), downloadUpdate: vi.fn(() => Promise.resolve([])), on: vi.fn(), quitAndInstall: vi.fn(), removeListener: vi.fn(), setFeedURL: vi.fn(), },})); vi.mock("electron-updater", () => ({ autoUpdater: autoUpdaterMock,})); import * as ElectronUpdater from "./ElectronUpdater.ts"; describe("ElectronUpdater", () => { beforeEach(() => { autoUpdaterMock.allowDowngrade = false; autoUpdaterMock.allowPrerelease = false; autoUpdaterMock.autoDownload = true; autoUpdaterMock.autoInstallOnAppQuit = true; autoUpdaterMock.channel = "latest"; autoUpdaterMock.disableDifferentialDownload = false; autoUpdaterMock.checkForUpdates.mockClear(); autoUpdaterMock.checkForUpdates.mockImplementation(() => Promise.resolve(null)); autoUpdaterMock.downloadUpdate.mockClear(); autoUpdaterMock.downloadUpdate.mockImplementation(() => Promise.resolve([])); autoUpdaterMock.on.mockClear(); autoUpdaterMock.quitAndInstall.mockClear(); autoUpdaterMock.removeListener.mockClear(); autoUpdaterMock.setFeedURL.mockClear(); }); it.effect("scopes updater event listeners", () => Effect.gen(function* () { const listener = vi.fn(); yield* Effect.scoped( Effect.gen(function* () { const updater = yield* ElectronUpdater.ElectronUpdater; yield* updater.on("update-available", listener); }), ); assert.deepEqual(autoUpdaterMock.on.mock.calls, [["update-available", listener]]); assert.deepEqual(autoUpdaterMock.removeListener.mock.calls, [["update-available", listener]]); }).pipe(Effect.provide(ElectronUpdater.layer)), ); it.effect("wraps rejected update checks in the method-specific typed error", () => Effect.gen(function* () { const cause = new Error("network unavailable"); autoUpdaterMock.checkForUpdates.mockImplementationOnce(() => Promise.reject(cause)); const updater = yield* ElectronUpdater.ElectronUpdater; const exit = yield* Effect.exit(updater.checkForUpdates); assert.equal(exit._tag, "Failure"); if (exit._tag === "Failure") { const error = Cause.squash(exit.cause); assert.instanceOf(error, ElectronUpdater.ElectronUpdaterCheckForUpdatesError); assert.equal(error.cause, cause); assert.equal(error.message, "Electron updater failed to check for updates."); } }).pipe(Effect.provide(ElectronUpdater.layer)), );});
import { assert, describe, it } from "@effect/vitest";
import * as Cause from "effect/Cause";
import * as Effect from "effect/Effect";
import { beforeEach, vi } from "vite-plus/test";
const { autoUpdaterMock } = vi.hoisted(() => ({
autoUpdaterMock: {
allowDowngrade: false,
allowPrerelease: false,
autoDownload: true,
autoInstallOnAppQuit: true,
channel: "latest",
disableDifferentialDownload: false,
checkForUpdates: vi.fn(() => Promise.resolve(null)),
downloadUpdate: vi.fn(() => Promise.resolve([])),
on: vi.fn(),
quitAndInstall: vi.fn(),
removeListener: vi.fn(),
setFeedURL: vi.fn(),
},
}));
vi.mock("electron-updater", () => ({
autoUpdater: autoUpdaterMock,
}));
import * as ElectronUpdater from "./ElectronUpdater.ts";
describe("ElectronUpdater", () => {
beforeEach(() => {
autoUpdaterMock.allowDowngrade = false;
autoUpdaterMock.allowPrerelease = false;
autoUpdaterMock.autoDownload = true;
autoUpdaterMock.autoInstallOnAppQuit = true;
autoUpdaterMock.channel = "latest";
autoUpdaterMock.disableDifferentialDownload = false;
autoUpdaterMock.checkForUpdates.mockClear();
autoUpdaterMock.checkForUpdates.mockImplementation(() => Promise.resolve(null));
autoUpdaterMock.downloadUpdate.mockClear();
autoUpdaterMock.downloadUpdate.mockImplementation(() => Promise.resolve([]));
autoUpdaterMock.on.mockClear();
autoUpdaterMock.quitAndInstall.mockClear();
autoUpdaterMock.removeListener.mockClear();
autoUpdaterMock.setFeedURL.mockClear();
});
it.effect("scopes updater event listeners", () =>
Effect.gen(function* () {
const listener = vi.fn();
yield* Effect.scoped(
Effect.gen(function* () {
const updater = yield* ElectronUpdater.ElectronUpdater;
yield* updater.on("update-available", listener);
}),
);
assert.deepEqual(autoUpdaterMock.on.mock.calls, [["update-available", listener]]);
assert.deepEqual(autoUpdaterMock.removeListener.mock.calls, [["update-available", listener]]);
}).pipe(Effect.provide(ElectronUpdater.layer)),
);
it.effect("wraps rejected update checks in the method-specific typed error", () =>
Effect.gen(function* () {
const cause = new Error("network unavailable");
autoUpdaterMock.checkForUpdates.mockImplementationOnce(() => Promise.reject(cause));
const updater = yield* ElectronUpdater.ElectronUpdater;
const exit = yield* Effect.exit(updater.checkForUpdates);
assert.equal(exit._tag, "Failure");
if (exit._tag === "Failure") {
const error = Cause.squash(exit.cause);
assert.instanceOf(error, ElectronUpdater.ElectronUpdaterCheckForUpdatesError);
assert.equal(error.cause, cause);
assert.equal(error.message, "Electron updater failed to check for updates.");
}
}).pipe(Effect.provide(ElectronUpdater.layer)),
);
});