Files
obsidian-livesync/src/serviceFeatures/setupObsidian/qrCode.unit.spec.ts
T

187 lines
6.6 KiB
TypeScript

import { describe, expect, it, vi, afterEach } from "vitest";
import { EVENT_REQUEST_SHOW_SETUP_QR } from "@vrtmrz/livesync-commonlib/compat/events/coreEvents";
import { createServiceContext } from "@vrtmrz/livesync-commonlib/context";
import { encodeSetupSettingsAsQR, useSetupQRCodeFeature } from "./qrCode";
import { encodeQR, encodeSettingsToQRCodeData } from "@vrtmrz/livesync-commonlib/compat/API/processSetting";
import { copySetupURI } from "./setupUri";
vi.mock("./setupUri", () => ({ copySetupURI: vi.fn() }));
vi.mock("@vrtmrz/livesync-commonlib/compat/API/processSetting", () => {
return {
encodeQR: vi.fn(),
encodeSettingsToQRCodeData: vi.fn(),
OutputFormat: {
SVG: "svg",
},
};
});
describe("setupObsidian/qrCode", () => {
it("shows managed TURN settings and inactive profiles through the ordinary QR dialogue", async () => {
const settings = {
remoteConfigurations: {
managed: { uri: "sls+p2p://room?managedType=CF&managedId=turn-key&token=private-token" },
},
};
const confirmWithMessage = vi.fn();
const translate = vi.fn(() => "qr-message");
const host = {
services: {
API: { addLog: vi.fn() },
context: createServiceContext({ translate }),
setting: { currentSettings: () => settings },
UI: { confirm: { confirmWithMessage } },
},
} as any;
vi.mocked(encodeSettingsToQRCodeData).mockReturnValue("encoded-settings");
vi.mocked(encodeQR).mockReturnValue("<svg/>");
expect(await encodeSetupSettingsAsQR(host)).toBe("<svg/>");
expect(encodeSettingsToQRCodeData).toHaveBeenCalledWith(settings);
expect(translate).toHaveBeenCalledWith("Setup.QRCode", { qr_image: "<svg/>" });
expect(confirmWithMessage).toHaveBeenCalledWith("Settings QR Code", "qr-message", ["OK"], "OK");
expect(copySetupURI).not.toHaveBeenCalled();
});
afterEach(() => {
vi.restoreAllMocks();
vi.clearAllMocks();
});
it("encodeSetupSettingsAsQR should return empty string when QR generation fails", async () => {
const confirmWithMessage = vi.fn();
const host = {
services: {
context: createServiceContext(),
setting: {
currentSettings: vi.fn(() => ({ any: "settings" })),
},
UI: {
confirm: {
confirmWithMessage,
},
},
},
} as any;
vi.mocked(encodeSettingsToQRCodeData).mockReturnValue("encoded-settings");
vi.mocked(encodeQR).mockReturnValue("");
const result = await encodeSetupSettingsAsQR(host);
expect(result).toBe("");
expect(confirmWithMessage).not.toHaveBeenCalled();
});
it("encodeSetupSettingsAsQR should show confirm dialog when QR is generated", async () => {
const confirmWithMessage = vi.fn(() => true);
const translate = vi.fn(() => "qr-message");
const host = {
services: {
context: createServiceContext({ translate }),
setting: {
currentSettings: vi.fn(() => ({ any: "settings" })),
},
UI: {
confirm: {
confirmWithMessage,
},
},
},
} as any;
vi.mocked(encodeSettingsToQRCodeData).mockReturnValue("encoded-settings");
vi.mocked(encodeQR).mockReturnValue("<svg/>");
const result = await encodeSetupSettingsAsQR(host);
expect(result).toBe("<svg/>");
expect(translate).toHaveBeenCalledWith("Setup.QRCode", { qr_image: "<svg/>" });
expect(confirmWithMessage).toHaveBeenCalledWith("Settings QR Code", "qr-message", ["OK"], "OK");
});
it("useSetupQRCodeFeature should register onLoaded handler that wires command and event", async () => {
const addHandler = vi.fn();
const addCommand = vi.fn();
const context = createServiceContext();
const onEventSpy = vi.spyOn(context.events, "onEvent");
const host = {
services: {
context,
API: {
addCommand,
},
appLifecycle: {
onLoaded: {
addHandler,
},
},
setting: {
currentSettings: vi.fn(() => ({ any: "settings" })),
},
UI: {
confirm: {
confirmWithMessage: vi.fn(),
},
},
},
} as any;
useSetupQRCodeFeature(host);
expect(addHandler).toHaveBeenCalledTimes(1);
const loadedHandler = addHandler.mock.calls[0][0] as () => Promise<boolean>;
await loadedHandler();
expect(addCommand).toHaveBeenCalledWith(
expect.objectContaining({
id: "livesync-setting-qr",
name: "Show settings as a QR code",
})
);
expect(onEventSpy).toHaveBeenCalledWith(EVENT_REQUEST_SHOW_SETUP_QR, expect.any(Function));
});
it("keeps the QR command out of the palette until setup is complete", async () => {
const addHandler = vi.fn();
const commands: Array<{
id: string;
checkCallback?: (checking: boolean) => boolean | void;
}> = [];
const settings = { isConfigured: false };
const host = {
services: {
context: createServiceContext(),
API: {
addCommand: vi.fn((command) => commands.push(command)),
},
appLifecycle: {
onLoaded: {
addHandler,
},
},
setting: {
currentSettings: vi.fn(() => settings),
},
UI: {
confirm: {
confirmWithMessage: vi.fn(),
},
},
},
} as any;
useSetupQRCodeFeature(host);
const loadedHandler = addHandler.mock.calls[0][0] as () => Promise<boolean>;
await loadedHandler();
const command = commands.find((candidate) => candidate.id === "livesync-setting-qr")!;
expect(command.checkCallback?.(true)).toBe(false);
settings.isConfigured = true;
expect(command.checkCallback?.(true)).toBe(true);
});
});