mirror of
https://github.com/sotashimozono/obsidian-remote-ssh.git
synced 2026-07-22 06:52:07 +00:00
Extract preSpawnPull's inline remote-path resolution into a pure `preSpawnRemotePath` (PathMapper.toRemote -> remote-base join) so the #450 CRITICAL redirect is unit-testable without standing up a standalone SftpClient. Behavior-preserving -- main.ts calls the extracted function. The four per-device config files (app/appearance/core-plugins/hotkeys) must resolve to `<configDir>/user/<clientId>/...`; joining the bare shared identity path clobbered per-device config on every shadow-window spawn. New tests pin: per-client redirect for the four files, identity for shared files (community-plugins.json, plugin binaries), "." base join, and cross-client isolation.
42 lines
1.9 KiB
TypeScript
42 lines
1.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { PathMapper } from '../src/path/PathMapper';
|
|
import { preSpawnRemotePath } from '../src/shadow/preSpawnPaths';
|
|
|
|
/**
|
|
* Pins the #450 CRITICAL fix: the pre-spawn config pull must resolve the
|
|
* four per-device config files to THIS client's `user/<id>/` subtree, not
|
|
* the dead shared identity path (reading which clobbered per-device config
|
|
* on every shadow-window spawn). A regression that dropped the
|
|
* `PathMapper.toRemote` redirect (bare base-join) would flip the config
|
|
* assertions below to the shared path and fail here.
|
|
*/
|
|
describe('preSpawnRemotePath', () => {
|
|
const mapper = new PathMapper('host-a', '.obsidian');
|
|
const base = '/home/u/vault';
|
|
|
|
it('redirects the four per-device config files to the per-client subtree', () => {
|
|
for (const f of ['app.json', 'appearance.json', 'core-plugins.json', 'hotkeys.json']) {
|
|
expect(preSpawnRemotePath(mapper, base, `.obsidian/${f}`))
|
|
.toBe(`${base}/.obsidian/user/host-a/${f}`);
|
|
}
|
|
});
|
|
|
|
it('leaves shared files (community-plugins.json, plugin binaries) at the identity path', () => {
|
|
expect(preSpawnRemotePath(mapper, base, '.obsidian/community-plugins.json'))
|
|
.toBe(`${base}/.obsidian/community-plugins.json`);
|
|
expect(preSpawnRemotePath(mapper, base, '.obsidian/plugins/dataview/main.js'))
|
|
.toBe(`${base}/.obsidian/plugins/dataview/main.js`);
|
|
});
|
|
|
|
it('joins onto a "." remote base (vault root) without a leading slash', () => {
|
|
expect(preSpawnRemotePath(mapper, '.', '.obsidian/app.json'))
|
|
.toBe('.obsidian/user/host-a/app.json');
|
|
});
|
|
|
|
it('isolates clients — two client ids never resolve to the same config path', () => {
|
|
const a = new PathMapper('host-a', '.obsidian');
|
|
const b = new PathMapper('host-b', '.obsidian');
|
|
expect(preSpawnRemotePath(a, base, '.obsidian/app.json'))
|
|
.not.toBe(preSpawnRemotePath(b, base, '.obsidian/app.json'));
|
|
});
|
|
});
|