Files
NetMesh/domain/pluginSyncSidecar.test.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

259 lines
7.7 KiB
TypeScript

import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
collectPluginSyncSidecars,
excludeSecretPluginSettingsFromSidecars,
isCloudSyncablePluginSetting,
mergePluginSyncSidecars,
mergePluginSyncSidecarsThreeWay,
parseSettingsSidecarKey,
type PluginSettingFieldDescriptor,
type PluginSyncSidecarEntry,
} from './pluginSyncSidecar';
const pluginId = 'com.example.sidecar';
const declared = new Map<string, PluginSettingFieldDescriptor[]>([
[pluginId, [
{ id: `${pluginId}.theme`, sync: true, secret: false },
{ id: `${pluginId}.token`, sync: true, secret: true },
{ id: `${pluginId}.localOnly`, sync: false, secret: false },
]],
]);
describe('pluginSyncSidecar', () => {
it('rejects secret fields from cloud sync even when sync is true', () => {
assert.equal(isCloudSyncablePluginSetting({ sync: true, secret: true }), false);
assert.equal(isCloudSyncablePluginSetting({ sync: true, secret: false }), true);
assert.equal(isCloudSyncablePluginSetting({ sync: false, secret: false }), false);
});
it('collects only non-secret sync:true settings into the sidecar bundle', () => {
const bundle = collectPluginSyncSidecars({
declaredSettingsByPlugin: declared,
storedSettings: [
{
pluginId,
settingId: `${pluginId}.theme`,
scope: 'application',
scopeId: 'application',
value: 'dark',
updatedAt: 10,
},
{
pluginId,
settingId: `${pluginId}.token`,
scope: 'application',
scopeId: 'application',
value: 'should-not-sync',
updatedAt: 10,
},
{
pluginId,
settingId: `${pluginId}.localOnly`,
scope: 'application',
scopeId: 'application',
value: true,
updatedAt: 10,
},
],
now: 20,
});
assert.equal(bundle.version, 1);
assert.equal(bundle.entries.length, 1);
assert.equal(bundle.entries[0].kind, 'settings');
assert.equal(bundle.entries[0].value, 'dark');
assert.deepEqual(parseSettingsSidecarKey(bundle.entries[0].key), {
settingId: `${pluginId}.theme`,
scope: 'application',
scopeId: 'application',
});
});
it('preserves account and CRDT baselines when the plugin is missing', () => {
const existing: PluginSyncSidecarEntry[] = [
{
pluginId: 'com.missing.plugin',
kind: 'account_baseline',
key: 'account',
value: { accountId: 'acct-1' },
updatedAt: 5,
},
{
pluginId: 'com.missing.plugin',
kind: 'crdt_baseline',
key: 'replica',
value: { clock: 3 },
updatedAt: 5,
},
{
pluginId: 'com.missing.plugin',
kind: 'settings',
key: 'com.missing.plugin.theme\0application\0application',
value: 'light',
updatedAt: 5,
},
];
const bundle = collectPluginSyncSidecars({
declaredSettingsByPlugin: new Map(), // plugin not installed
storedSettings: [],
existingSidecars: existing,
now: 100,
});
assert.equal(bundle.entries.length, 3);
assert.ok(bundle.entries.some((entry) => entry.kind === 'account_baseline'));
assert.ok(bundle.entries.some((entry) => entry.kind === 'crdt_baseline'));
assert.ok(bundle.entries.some((entry) => entry.kind === 'settings' && entry.value === 'light'));
});
it('merges remote sidecars without dropping local baselines for missing remote plugins', () => {
const local: PluginSyncSidecarEntry[] = [
{
pluginId: 'com.local.only',
kind: 'account_baseline',
key: 'account',
value: { id: 'local' },
updatedAt: 1,
},
];
const remote = {
version: 1 as const,
entries: [
{
pluginId,
kind: 'settings' as const,
key: `${pluginId}.theme\0application\0application`,
value: 'dark',
updatedAt: 2,
},
],
};
const merged = mergePluginSyncSidecars({ local, remote, declaredSettingsByPlugin: declared });
assert.equal(merged.length, 2);
assert.ok(merged.some((entry) => entry.pluginId === 'com.local.only'));
assert.ok(merged.some((entry) => entry.value === 'dark'));
});
it('excludes secret settings when stripping sidecars with known declarations', () => {
const entries: PluginSyncSidecarEntry[] = [
{
pluginId,
kind: 'settings',
key: `${pluginId}.token\0application\0application`,
value: 'secret',
updatedAt: 1,
},
{
pluginId,
kind: 'settings',
key: `${pluginId}.theme\0application\0application`,
value: 'dark',
updatedAt: 1,
},
];
const filtered = excludeSecretPluginSettingsFromSidecars(entries, declared);
assert.equal(filtered.length, 1);
assert.equal(filtered[0].value, 'dark');
});
it('collect prefers newer retained sidecars over older stored settings', () => {
const bundle = collectPluginSyncSidecars({
declaredSettingsByPlugin: declared,
storedSettings: [{
pluginId,
settingId: `${pluginId}.theme`,
scope: 'application',
scopeId: 'application',
value: 'local-old',
updatedAt: 100,
}],
existingSidecars: [{
pluginId,
kind: 'settings',
key: `${pluginId}.theme\0application\0application`,
value: 'remote-new',
updatedAt: 200,
}],
now: 300,
});
assert.equal(bundle.entries.length, 1);
assert.equal(bundle.entries[0].value, 'remote-new');
assert.equal(bundle.entries[0].updatedAt, 200);
});
it('three-way merge propagates local settings deletions against an unchanged remote', () => {
const entry: PluginSyncSidecarEntry = {
pluginId,
kind: 'settings',
key: `${pluginId}.theme\0application\0application`,
value: 'dark',
updatedAt: 10,
};
const merged = mergePluginSyncSidecarsThreeWay({
base: [entry],
local: [],
remote: [entry],
});
assert.equal(merged.some((item) => item.key === entry.key), false);
});
it('three-way merge keeps a newer remote edit over a local deletion', () => {
const base: PluginSyncSidecarEntry = {
pluginId,
kind: 'settings',
key: `${pluginId}.theme\0application\0application`,
value: 'dark',
updatedAt: 10,
};
const remote: PluginSyncSidecarEntry = {
...base,
value: 'light',
updatedAt: 20,
};
const merged = mergePluginSyncSidecarsThreeWay({
base: [base],
local: [],
remote: [remote],
});
assert.equal(merged.length, 1);
assert.equal(merged[0].value, 'light');
});
it('preferCloud keeps local-only settings and baseline orphans', () => {
const localOnly: PluginSyncSidecarEntry = {
pluginId,
kind: 'settings',
key: `${pluginId}.theme\0application\0application`,
value: 'local-new',
updatedAt: 50,
};
const baseline: PluginSyncSidecarEntry = {
pluginId,
kind: 'account_baseline',
key: 'account',
value: { id: 'local-acct' },
updatedAt: 40,
};
const remoteBaseline: PluginSyncSidecarEntry = {
pluginId,
kind: 'crdt_baseline',
key: 'crdt',
value: { clock: 1 },
updatedAt: 30,
};
const merged = mergePluginSyncSidecarsThreeWay({
base: [],
local: [localOnly, baseline],
remote: [remoteBaseline],
strategy: 'preferCloud',
});
assert.equal(merged.some((item) => item.key === localOnly.key), true);
assert.equal(merged.some((item) => item.kind === 'account_baseline'), true);
assert.equal(merged.some((item) => item.kind === 'crdt_baseline'), true);
});
});