const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { expandHomePath, ensureInclude, resolveGeneratedSshConfigPath, shellQuote, sshBlock, sshConfigPathWord, sshIncludeTarget, sshConfigWord, upsertBlock, windowsCommandWord } = require('./extension'); test('posix ssh config words use shell quoting', () => { assert.equal( sshConfigWord('/Users/palav/My App/dosh', 'darwin'), "'/Users/palav/My App/dosh'" ); assert.equal(shellQuote("say 'hi'"), "'say '\\''hi'\\'''"); }); test('windows ssh config words use Windows command quoting', () => { assert.equal( sshConfigWord('C:\\Program Files\\Dosh\\dosh.exe', 'win32'), '"C:\\Program Files\\Dosh\\dosh.exe"' ); assert.equal( windowsCommandWord('C:\\path\\before"quote'), '"C:\\path\\before\\"quote"' ); assert.equal( windowsCommandWord('C:\\Program Files\\Dosh\\'), '"C:\\Program Files\\Dosh\\\\"' ); }); test('ssh block quotes proxy command for the target platform', () => { const block = sshBlock({ alias: 'dosh-work', host: 'work host', executable: 'C:\\Program Files\\Dosh\\dosh.exe', targetHost: '127.0.0.1', targetPort: 22, doshPort: 50000, platform: 'win32' }); assert.match( block, /ProxyCommand "C:\\Program Files\\Dosh\\dosh\.exe" --dosh-port 50000 proxy-stdio "work host" %h %p/ ); assert.doesNotMatch(block, /'C:\\Program Files\\Dosh\\dosh\.exe'/); }); test('ssh include target stays relative for generated config beside main config', () => { assert.equal( sshIncludeTarget('/Users/palav/.ssh/config', '/Users/palav/.ssh/config.dosh', 'darwin'), 'config.dosh' ); }); test('ssh include target uses absolute path for custom generated config location', () => { assert.equal( sshIncludeTarget( '/Users/palav/.ssh/config', '/Users/palav/Library/Application Support/Dosh/config.dosh', 'darwin' ), '"/Users/palav/Library/Application Support/Dosh/config.dosh"' ); }); test('ssh include target handles Windows custom generated config paths', () => { assert.equal( sshIncludeTarget( 'C:\\Users\\palav\\.ssh\\config', 'C:\\Users\\palav\\AppData\\Roaming\\Dosh Remote\\config.dosh', 'win32' ), '"C:/Users/palav/AppData/Roaming/Dosh Remote/config.dosh"' ); assert.equal( sshConfigPathWord('C:\\Users\\palav\\.ssh\\config.dosh', 'win32'), 'C:/Users/palav/.ssh/config.dosh' ); }); test('home-relative generated config paths expand for POSIX and Windows', () => { assert.equal( expandHomePath('~/Library/Application Support/Dosh/config.dosh', '/Users/palav', 'darwin'), '/Users/palav/Library/Application Support/Dosh/config.dosh' ); assert.equal( expandHomePath('~\\.ssh\\config.dosh', 'C:\\Users\\palav', 'win32'), 'C:\\Users\\palav\\.ssh\\config.dosh' ); }); test('relative generated config paths resolve beside the main ssh config', () => { assert.equal( resolveGeneratedSshConfigPath( '/Users/palav/.ssh/config', 'config.dosh', '/Users/palav', 'darwin' ), '/Users/palav/.ssh/config.dosh' ); assert.equal( resolveGeneratedSshConfigPath( 'C:\\Users\\palav\\.ssh\\config', 'dosh\\config.dosh', 'C:\\Users\\palav', 'win32' ), 'C:\\Users\\palav\\.ssh\\dosh\\config.dosh' ); }); test('config writers create missing parent directories', () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'dosh-vscode-')); const mainConfig = path.join(root, 'ssh', 'config'); const generatedConfig = path.join(root, 'generated', 'config.dosh'); ensureInclude(mainConfig, '../generated/config.dosh'); upsertBlock( generatedConfig, 'dosh-test', [ '# BEGIN DOSH dosh-test', 'Host dosh-test', ' ProxyCommand dosh proxy-stdio test %h %p', '# END DOSH dosh-test' ].join('\n') ); assert.equal(fs.readFileSync(mainConfig, 'utf8'), 'Include ../generated/config.dosh\n'); assert.match(fs.readFileSync(generatedConfig, 'utf8'), /Host dosh-test/); });