mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-27 15:02:59 +00:00
573 lines
24 KiB
TypeScript
573 lines
24 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
DEFAULT_SETTINGS,
|
|
REMOTE_COUCHDB,
|
|
REMOTE_P2P,
|
|
type ObsidianLiveSyncSettings,
|
|
} from "@vrtmrz/livesync-commonlib/compat/common/types";
|
|
import { SettingService } from "@vrtmrz/livesync-commonlib/compat/services/base/SettingService";
|
|
import { ServiceContext } from "@vrtmrz/livesync-commonlib/context";
|
|
import { createNewVaultSettings } from "@vrtmrz/livesync-commonlib/settings";
|
|
|
|
vi.mock("./SetupWizard/dialogs/Intro.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SelectMethodNewUser.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SelectMethodExisting.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/ScanQRCode.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/UseSetupURI.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/OutroNewUser.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/OutroExistingUser.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/OutroAskUserMode.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SetupRemote.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SetupRemoteCouchDB.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SetupRemoteBucket.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SetupRemoteP2P.svelte", () => ({ default: {} }));
|
|
vi.mock("./SetupWizard/dialogs/SetupRemoteE2EE.svelte", () => ({ default: {} }));
|
|
|
|
vi.mock("@vrtmrz/livesync-commonlib/compat/API/processSetting", () => ({
|
|
decodeSettingsFromQRCodeData: vi.fn(),
|
|
}));
|
|
|
|
import { decodeSettingsFromQRCodeData } from "@vrtmrz/livesync-commonlib/compat/API/processSetting";
|
|
import { SetupManager, UserMode } from "./SetupManager";
|
|
|
|
class TestSettingService extends SettingService<ServiceContext> {
|
|
protected setItem(_key: string, _value: string): void {}
|
|
protected getItem(_key: string): string {
|
|
return "";
|
|
}
|
|
protected deleteItem(_key: string): void {}
|
|
protected saveData(_setting: ObsidianLiveSyncSettings): Promise<void> {
|
|
return Promise.resolve();
|
|
}
|
|
protected loadData(): Promise<ObsidianLiveSyncSettings | undefined> {
|
|
return Promise.resolve(undefined);
|
|
}
|
|
}
|
|
|
|
function createLegacyRemoteSetting(): ObsidianLiveSyncSettings {
|
|
return {
|
|
...DEFAULT_SETTINGS,
|
|
remoteConfigurations: {},
|
|
activeConfigurationId: "",
|
|
remoteType: REMOTE_COUCHDB,
|
|
couchDB_URI: "http://localhost:5984",
|
|
couchDB_USER: "user",
|
|
couchDB_PASSWORD: "password",
|
|
couchDB_DBNAME: "vault",
|
|
};
|
|
}
|
|
|
|
function createSetupManager() {
|
|
const setting = new TestSettingService(new ServiceContext(), {
|
|
APIService: {
|
|
getSystemVaultName: vi.fn(() => "vault"),
|
|
getAppID: vi.fn(() => "app"),
|
|
confirm: {
|
|
askString: vi.fn(() => Promise.resolve("")),
|
|
},
|
|
addLog: vi.fn(),
|
|
addCommand: vi.fn(),
|
|
registerWindow: vi.fn(),
|
|
addRibbonIcon: vi.fn(),
|
|
registerProtocolHandler: vi.fn(),
|
|
} as any,
|
|
});
|
|
setting.settings = {
|
|
...DEFAULT_SETTINGS,
|
|
remoteConfigurations: {},
|
|
activeConfigurationId: "",
|
|
};
|
|
vi.spyOn(setting, "saveSettingData").mockResolvedValue();
|
|
|
|
const dialogManager = {
|
|
openWithExplicitCancel: vi.fn(),
|
|
open: vi.fn(),
|
|
};
|
|
const services = {
|
|
API: {
|
|
addLog: vi.fn(),
|
|
addCommand: vi.fn(),
|
|
registerWindow: vi.fn(),
|
|
addRibbonIcon: vi.fn(),
|
|
registerProtocolHandler: vi.fn(),
|
|
},
|
|
UI: {
|
|
dialogManager,
|
|
},
|
|
setting,
|
|
} as any;
|
|
const core: any = {
|
|
_services: services,
|
|
rebuilder: {
|
|
scheduleRebuild: vi.fn(async (prepareBeforeRestart?: () => Promise<void>) => {
|
|
await prepareBeforeRestart?.();
|
|
return true;
|
|
}),
|
|
scheduleFetch: vi.fn(async (prepareBeforeRestart?: () => Promise<void>) => {
|
|
await prepareBeforeRestart?.();
|
|
return true;
|
|
}),
|
|
},
|
|
};
|
|
Object.defineProperty(core, "services", {
|
|
get() {
|
|
return services;
|
|
},
|
|
});
|
|
Object.defineProperty(core, "settings", {
|
|
get() {
|
|
return setting.settings;
|
|
},
|
|
set(value: ObsidianLiveSyncSettings) {
|
|
setting.settings = value;
|
|
},
|
|
});
|
|
|
|
return {
|
|
manager: new SetupManager(core),
|
|
setting,
|
|
dialogManager,
|
|
core,
|
|
};
|
|
}
|
|
|
|
describe("SetupManager", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("starts manual new-user setup from the recommended new-Vault settings", async () => {
|
|
const { manager, dialogManager } = createSetupManager();
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce("configure-manually");
|
|
const configureManually = vi.spyOn(manager, "onConfigureManually").mockResolvedValue(true);
|
|
|
|
await manager.onOnboard(UserMode.NewUser);
|
|
|
|
expect(configureManually).toHaveBeenCalledWith(createNewVaultSettings(), UserMode.NewUser);
|
|
});
|
|
|
|
it("compatibility: normalises imported flat remote settings from a Setup URI before applying", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce(createLegacyRemoteSetting())
|
|
.mockResolvedValueOnce("compatible-existing-user");
|
|
|
|
const result = await manager.onUseSetupURI(UserMode.Unknown, "mock-config://settings");
|
|
|
|
expect(result).toBe(true);
|
|
expect(setting.currentSettings().remoteConfigurations["legacy-couchdb"]?.uri).toContain(
|
|
"sls+http://user:password@localhost:5984"
|
|
);
|
|
expect(setting.currentSettings().activeConfigurationId).toBe("legacy-couchdb");
|
|
});
|
|
|
|
it("compatibility: normalises imported flat remote settings from QR data before applying", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
vi.mocked(decodeSettingsFromQRCodeData).mockReturnValue(createLegacyRemoteSetting());
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce("compatible-existing-user");
|
|
|
|
const result = await manager.decodeQR("qr-data");
|
|
|
|
expect(result).toBe(true);
|
|
expect(decodeSettingsFromQRCodeData).toHaveBeenCalledWith("qr-data");
|
|
expect(setting.currentSettings().remoteConfigurations["legacy-couchdb"]?.uri).toContain(
|
|
"sls+http://user:password@localhost:5984"
|
|
);
|
|
expect(setting.currentSettings().activeConfigurationId).toBe("legacy-couchdb");
|
|
});
|
|
|
|
it("reserves Rebuild before saving a new-user configuration", async () => {
|
|
const { manager, setting, dialogManager, core } = createSetupManager();
|
|
setting.settings = { ...setting.currentSettings(), isConfigured: false };
|
|
const applyExternalSettings = vi.spyOn(setting, "applyExternalSettings");
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce(true);
|
|
|
|
await manager.onConfirmApplySettingsFromWizard(
|
|
{ ...createLegacyRemoteSetting(), isConfigured: true },
|
|
UserMode.NewUser
|
|
);
|
|
|
|
expect(core.rebuilder.scheduleRebuild).toHaveBeenCalledWith(expect.any(Function));
|
|
expect(core.rebuilder.scheduleRebuild.mock.invocationCallOrder[0]).toBeLessThan(
|
|
applyExternalSettings.mock.invocationCallOrder[0]
|
|
);
|
|
expect(setting.currentSettings().isConfigured).toBe(true);
|
|
});
|
|
|
|
it("identifies P2P when opening the new-user initialisation confirmation", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = { ...setting.currentSettings(), isConfigured: false };
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce(true);
|
|
const p2pProfileId = "p2p-profile";
|
|
|
|
await manager.onConfirmApplySettingsFromWizard(
|
|
{
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
// Imported profile settings can still carry the previous compatibility field
|
|
// until the selected profile is projected by the setting lifecycle.
|
|
remoteType: REMOTE_COUCHDB,
|
|
activeConfigurationId: p2pProfileId,
|
|
remoteConfigurations: {
|
|
[p2pProfileId]: {
|
|
id: p2pProfileId,
|
|
name: "P2P room",
|
|
uri: "sls+p2p://:secret@team-room?relays=wss%3A%2F%2Frelay.example",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
},
|
|
UserMode.NewUser
|
|
);
|
|
|
|
expect(dialogManager.openWithExplicitCancel).toHaveBeenCalledWith(expect.anything(), {
|
|
isP2P: true,
|
|
});
|
|
});
|
|
|
|
it("reserves Fetch when compatible imported settings activate an unconfigured device", async () => {
|
|
const { manager, setting, dialogManager, core } = createSetupManager();
|
|
setting.settings = { ...setting.currentSettings(), isConfigured: false };
|
|
const applyExternalSettings = vi.spyOn(setting, "applyExternalSettings");
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({ ...createLegacyRemoteSetting(), isConfigured: true })
|
|
.mockResolvedValueOnce("compatible-existing-user");
|
|
|
|
await manager.onUseSetupURI(UserMode.Unknown, "mock-config://settings");
|
|
|
|
expect(core.rebuilder.scheduleFetch).toHaveBeenCalledWith(expect.any(Function));
|
|
expect(core.rebuilder.scheduleFetch.mock.invocationCallOrder[0]).toBeLessThan(
|
|
applyExternalSettings.mock.invocationCallOrder[0]
|
|
);
|
|
expect(setting.currentSettings().isConfigured).toBe(true);
|
|
});
|
|
|
|
it("applies compatible settings to an already configured device without scheduling Fetch", async () => {
|
|
const { manager, setting, dialogManager, core } = createSetupManager();
|
|
setting.settings = { ...setting.currentSettings(), isConfigured: true };
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({ ...createLegacyRemoteSetting(), isConfigured: true })
|
|
.mockResolvedValueOnce("compatible-existing-user");
|
|
|
|
await manager.onUseSetupURI(UserMode.Unknown, "mock-config://settings");
|
|
|
|
expect(core.rebuilder.scheduleFetch).not.toHaveBeenCalled();
|
|
expect(setting.currentSettings().isConfigured).toBe(true);
|
|
});
|
|
|
|
it("does not enable imported settings when the initialisation flag cannot be reserved", async () => {
|
|
const { manager, setting, dialogManager, core } = createSetupManager();
|
|
setting.settings = { ...setting.currentSettings(), isConfigured: false };
|
|
const applyExternalSettings = vi.spyOn(setting, "applyExternalSettings");
|
|
core.rebuilder.scheduleRebuild.mockResolvedValueOnce(false);
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce(true);
|
|
|
|
await manager.onConfirmApplySettingsFromWizard(
|
|
{ ...createLegacyRemoteSetting(), isConfigured: true },
|
|
UserMode.NewUser
|
|
);
|
|
|
|
expect(core.rebuilder.scheduleRebuild).toHaveBeenCalledWith(expect.any(Function));
|
|
expect(applyExternalSettings).not.toHaveBeenCalled();
|
|
expect(setting.currentSettings().isConfigured).toBe(false);
|
|
});
|
|
|
|
it("preserves modern profiles, display names, and the active selection from a Setup URI", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
const imported = {
|
|
...DEFAULT_SETTINGS,
|
|
remoteConfigurations: {
|
|
couch: {
|
|
id: "couch",
|
|
name: "Office CouchDB",
|
|
uri: "sls+https://alice:secret@couch.example/?db=notes",
|
|
isEncrypted: false,
|
|
},
|
|
archive: {
|
|
id: "archive",
|
|
name: "Archive bucket",
|
|
uri: "sls+s3://key:secret@storage.example/?endpoint=https%3A%2F%2Fstorage.example&bucket=archive®ion=auto",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "archive",
|
|
} as ObsidianLiveSyncSettings;
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce(imported)
|
|
.mockResolvedValueOnce("compatible-existing-user");
|
|
|
|
await manager.onUseSetupURI(UserMode.Unknown, "mock-config://modern-settings");
|
|
|
|
const current = setting.currentSettings();
|
|
expect(current.remoteConfigurations).toEqual(imported.remoteConfigurations);
|
|
expect(current.activeConfigurationId).toBe("archive");
|
|
expect(Object.keys(current.remoteConfigurations).some((id) => id.startsWith("legacy-"))).toBe(false);
|
|
});
|
|
|
|
it("adds and activates a manually configured CouchDB without replacing existing profiles", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
remoteConfigurations: {
|
|
existing: {
|
|
id: "existing",
|
|
name: "Existing remote",
|
|
uri: "sls+http://old:secret@old.example/?db=old",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "existing",
|
|
};
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({
|
|
couchDB_URI: "https://couch.example",
|
|
couchDB_USER: "alice",
|
|
couchDB_PASSWORD: "secret",
|
|
couchDB_DBNAME: "notes",
|
|
couchDB_CustomHeaders: "",
|
|
useJWT: false,
|
|
jwtAlgorithm: "",
|
|
jwtKey: "",
|
|
jwtKid: "",
|
|
jwtSub: "",
|
|
jwtExpDuration: 5,
|
|
useRequestAPI: false,
|
|
})
|
|
.mockResolvedValueOnce(true);
|
|
|
|
await manager.onCouchDBManualSetup(UserMode.ExistingUser, setting.currentSettings());
|
|
|
|
const current = setting.currentSettings();
|
|
expect(current.remoteConfigurations.existing).toBeDefined();
|
|
expect(Object.keys(current.remoteConfigurations)).toHaveLength(2);
|
|
expect(current.activeConfigurationId).not.toBe("existing");
|
|
const activeProfile = current.remoteConfigurations[current.activeConfigurationId];
|
|
expect(activeProfile?.name).toBe("CouchDB couch.example");
|
|
expect(activeProfile?.uri).toContain("sls+https://alice:secret@couch.example");
|
|
});
|
|
|
|
it.each([
|
|
[UserMode.NewUser, "create-or-connect"],
|
|
[UserMode.ExistingUser, "connect-existing"],
|
|
[UserMode.Update, "settings"],
|
|
] as const)(
|
|
"passes the %s CouchDB database policy to the manual setup dialogue",
|
|
async (userMode, expectedMode) => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
const couchConf = {
|
|
couchDB_URI: "https://couch.example",
|
|
couchDB_USER: "alice",
|
|
couchDB_PASSWORD: "secret",
|
|
couchDB_DBNAME: "notes",
|
|
couchDB_CustomHeaders: "",
|
|
useJWT: false,
|
|
jwtAlgorithm: "",
|
|
jwtKey: "",
|
|
jwtKid: "",
|
|
jwtSub: "",
|
|
jwtExpDuration: 5,
|
|
useRequestAPI: false,
|
|
};
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce(couchConf).mockResolvedValueOnce("cancelled");
|
|
|
|
await manager.onCouchDBManualSetup(userMode, setting.currentSettings());
|
|
|
|
expect(dialogManager.openWithExplicitCancel).toHaveBeenNthCalledWith(1, expect.anything(), {
|
|
settings: setting.currentSettings(),
|
|
mode: expectedMode,
|
|
});
|
|
}
|
|
);
|
|
|
|
it("adds and activates a manually configured Object Storage profile without replacing existing profiles", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
remoteConfigurations: {
|
|
existing: {
|
|
id: "existing",
|
|
name: "Existing remote",
|
|
uri: "sls+http://old:secret@old.example/?db=old",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "existing",
|
|
};
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({
|
|
endpoint: "https://storage.example",
|
|
accessKey: "key",
|
|
secretKey: "secret",
|
|
bucket: "notes",
|
|
region: "auto",
|
|
bucketPrefix: "",
|
|
useCustomRequestHandler: false,
|
|
bucketCustomHeaders: "",
|
|
forcePathStyle: true,
|
|
})
|
|
.mockResolvedValueOnce(true);
|
|
|
|
await manager.onBucketManualSetup(UserMode.ExistingUser, setting.currentSettings());
|
|
|
|
const current = setting.currentSettings();
|
|
expect(current.remoteConfigurations.existing).toBeDefined();
|
|
expect(Object.keys(current.remoteConfigurations)).toHaveLength(2);
|
|
expect(current.activeConfigurationId).not.toBe("existing");
|
|
const activeProfile = current.remoteConfigurations[current.activeConfigurationId];
|
|
expect(activeProfile?.name).toBe("S3 notes");
|
|
expect(activeProfile?.uri).toContain("sls+s3://key:secret@storage.example");
|
|
});
|
|
|
|
it("creates and selects a P2P profile during fresh manual onboarding", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: false,
|
|
remoteConfigurations: {},
|
|
activeConfigurationId: "",
|
|
P2P_ActiveRemoteConfigurationId: "",
|
|
};
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({
|
|
P2P_Enabled: true,
|
|
P2P_roomID: "team-room",
|
|
P2P_passphrase: "secret",
|
|
P2P_relays: "wss://relay.example",
|
|
P2P_AppID: "self-hosted-livesync",
|
|
P2P_AutoStart: true,
|
|
P2P_AutoBroadcast: false,
|
|
P2P_turnServers: "",
|
|
P2P_turnUsername: "",
|
|
P2P_turnCredential: "",
|
|
})
|
|
.mockResolvedValueOnce(true);
|
|
|
|
await manager.onP2PManualSetup(UserMode.NewUser, setting.currentSettings());
|
|
|
|
const current = setting.currentSettings();
|
|
expect(Object.keys(current.remoteConfigurations)).toHaveLength(1);
|
|
expect(current.activeConfigurationId).not.toBe("");
|
|
expect(current.P2P_ActiveRemoteConfigurationId).toBe(current.activeConfigurationId);
|
|
const activeProfile = current.remoteConfigurations[current.activeConfigurationId];
|
|
expect(activeProfile?.name).toBe("P2P team-room");
|
|
expect(activeProfile?.uri).toContain("sls+p2p://");
|
|
});
|
|
|
|
it("selects a configured P2P profile without replacing the active main remote", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
remoteConfigurations: {
|
|
main: {
|
|
id: "main",
|
|
name: "Main CouchDB",
|
|
uri: "sls+http://old:secret@old.example/?db=old",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "main",
|
|
P2P_ActiveRemoteConfigurationId: "",
|
|
};
|
|
dialogManager.openWithExplicitCancel.mockResolvedValueOnce({
|
|
P2P_Enabled: true,
|
|
P2P_roomID: "team-room",
|
|
P2P_passphrase: "secret",
|
|
P2P_relays: "wss://relay.example",
|
|
P2P_AppID: "self-hosted-livesync",
|
|
P2P_AutoStart: true,
|
|
P2P_AutoBroadcast: false,
|
|
P2P_turnServers: "",
|
|
P2P_turnUsername: "",
|
|
P2P_turnCredential: "",
|
|
});
|
|
|
|
await manager.onP2PManualSetup(UserMode.Unknown, setting.currentSettings(), false);
|
|
|
|
const current = setting.currentSettings();
|
|
expect(Object.keys(current.remoteConfigurations)).toHaveLength(2);
|
|
expect(current.activeConfigurationId).toBe("main");
|
|
expect(current.P2P_ActiveRemoteConfigurationId).not.toBe("");
|
|
expect(current.P2P_ActiveRemoteConfigurationId).not.toBe("main");
|
|
expect(current.remoteConfigurations[current.P2P_ActiveRemoteConfigurationId]?.name).toBe("P2P team-room");
|
|
});
|
|
|
|
it("does not register Object Storage when final confirmation is cancelled", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
remoteConfigurations: {
|
|
existing: {
|
|
id: "existing",
|
|
name: "Existing remote",
|
|
uri: "sls+http://old:secret@old.example/?db=old",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "existing",
|
|
};
|
|
const before = structuredClone(setting.currentSettings().remoteConfigurations);
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({
|
|
endpoint: "https://storage.example",
|
|
accessKey: "key",
|
|
secretKey: "secret",
|
|
bucket: "notes",
|
|
region: "auto",
|
|
bucketPrefix: "",
|
|
useCustomRequestHandler: false,
|
|
bucketCustomHeaders: "",
|
|
forcePathStyle: true,
|
|
})
|
|
.mockResolvedValueOnce("cancelled");
|
|
|
|
await manager.onBucketManualSetup(UserMode.ExistingUser, setting.currentSettings());
|
|
|
|
expect(setting.currentSettings().remoteConfigurations).toEqual(before);
|
|
expect(setting.currentSettings().activeConfigurationId).toBe("existing");
|
|
});
|
|
|
|
it("does not mutate an existing P2P profile when final confirmation is cancelled", async () => {
|
|
const { manager, setting, dialogManager } = createSetupManager();
|
|
setting.settings = {
|
|
...setting.currentSettings(),
|
|
isConfigured: true,
|
|
remoteConfigurations: {
|
|
existing: {
|
|
id: "existing",
|
|
name: "Existing P2P remote",
|
|
uri: "sls+p2p://old-room?passphrase=old-secret",
|
|
isEncrypted: false,
|
|
},
|
|
},
|
|
activeConfigurationId: "existing",
|
|
P2P_ActiveRemoteConfigurationId: "existing",
|
|
};
|
|
const before = structuredClone(setting.currentSettings().remoteConfigurations);
|
|
dialogManager.openWithExplicitCancel
|
|
.mockResolvedValueOnce({
|
|
P2P_Enabled: true,
|
|
P2P_roomID: "new-room",
|
|
P2P_passphrase: "new-secret",
|
|
P2P_relays: "wss://relay.example",
|
|
P2P_AppID: "self-hosted-livesync",
|
|
P2P_AutoStart: true,
|
|
P2P_AutoBroadcast: false,
|
|
P2P_turnServers: "",
|
|
P2P_turnUsername: "",
|
|
P2P_turnCredential: "",
|
|
})
|
|
.mockResolvedValueOnce("cancelled");
|
|
|
|
await manager.onP2PManualSetup(UserMode.ExistingUser, setting.currentSettings());
|
|
|
|
expect(setting.currentSettings().remoteConfigurations).toEqual(before);
|
|
expect(setting.currentSettings().activeConfigurationId).toBe("existing");
|
|
expect(setting.currentSettings().P2P_ActiveRemoteConfigurationId).toBe("existing");
|
|
});
|
|
});
|