'use strict'; const test = require('node:test'); const assert = require('node:assert'); const U = require('./wsutil.js'); test('shellQuote keeps a path one literal word', () => { assert.strictEqual(U.shellQuote('/srv/a b'), "'/srv/a b'"); assert.strictEqual(U.shellQuote("/x/it's"), "'/x/it'\\''s'"); assert.strictEqual(U.shellQuote('/x/$HOME;rm'), "'/x/$HOME;rm'"); assert.strictEqual(U.shellQuoteAll(['/a', '/b c']), "'/a' '/b c'"); }); const m1 = {kind: 'agent', id: 'm1', label: 'web'}; const m2 = {kind: 'agent', id: 'm2', label: 'db'}; const s1 = {kind: 'ssh', id: 'm1|root@h:22', label: 'root@h'}; const item = {source: m1, paths: ['/etc/x'], dir: '/etc'}; test('dropAction: files into a file pane is a transfer', () => { assert.deepStrictEqual(U.dropAction(item, {kind: 'files', source: m2, dir: '/tmp'}), {kind: 'transfer'}); assert.deepStrictEqual(U.dropAction(item, {kind: 'folder', source: m1, dir: '/var'}), {kind: 'transfer'}); }); test('dropAction: into its own folder does nothing', () => { assert.deepStrictEqual(U.dropAction(item, {kind: 'files', source: m1, dir: '/etc'}), {kind: 'none'}); }); test('dropAction: terminal of the same place pastes, of another is denied', () => { assert.deepStrictEqual(U.dropAction(item, {kind: 'term', source: m1}), {kind: 'paste'}); const d = U.dropAction(item, {kind: 'term', source: m2}); assert.strictEqual(d.kind, 'deny'); assert.strictEqual(d.reason, 'Нельзя: файл на web, а терминал на db'); assert.strictEqual(U.dropAction({source: s1, paths: ['/a'], dir: '/'}, {kind: 'term', source: s1}).kind, 'paste'); }); test('fmtSize', () => { assert.strictEqual(U.fmtSize(10), '10 B'); assert.strictEqual(U.fmtSize(2048), '2.0 K'); }); test('dropAction: other SSH user on the same host is another place', () => { const a = {kind: 'ssh', id: 'm1|root@h:22', label: 'root@h'}; const b = {kind: 'ssh', id: 'm1|bob@h:22', label: 'bob@h'}; assert.strictEqual(U.dropAction({source: a, paths: ['/x'], dir: '/'}, {kind: 'term', source: b}).kind, 'deny'); }); test('scope: nothing new runs after it ended', async () => { const s = U.scope(); let n = 0; s.end(); s.timeout(() => n++, 1); s.interval(() => n++, 1); await new Promise(r => setTimeout(r, 20)); assert.strictEqual(n, 0); }); test('parseActions: run, read, ls and write blocks with or without a machine', () => { const text = 'Сделаю так:\n```run web\nuptime\n```\nи\n```read db:/etc/hosts\n```\n```ls /var/log\n```\n```write web:/tmp/a b.txt\nline 1\nline 2\n```\n```bash\nnot an action\n```\n```run\ndf -h\n```'; assert.deepStrictEqual(U.parseActions(text), [ {kind: 'run', machine: 'web', path: '', body: 'uptime'}, {kind: 'read', machine: 'db', path: '/etc/hosts', body: ''}, {kind: 'ls', machine: '', path: '/var/log', body: ''}, {kind: 'write', machine: 'web', path: '/tmp/a b.txt', body: 'line 1\nline 2'}, {kind: 'run', machine: '', path: '', body: 'df -h'} ]); // A block still being written is not an action yet. assert.strictEqual(U.parseActions('```run\nls').length, 0); }); test('md: the common marks, everything else escaped', () => { assert.strictEqual(U.md('**жирный** и *курсив*, `ls -la `'), '

жирный и курсив, ls -la <x>

'); assert.strictEqual(U.md('# Итог\n- раз\n- два\n\n1. первое\n2. второе'), '

Итог

  1. первое
  2. второе
'); assert.strictEqual(U.md('[док](https://ex.com/a?b=1&c=2) и [плохо](javascript:alert(1))'), '

док и плохо

'); assert.strictEqual(U.md('> цитата\n\nстрока 1\nстрока 2'), '
цитата

строка 1
строка 2

'); assert.strictEqual(U.md(''), '

<script>x</script>

'); // Inside code nothing is marked up. assert.strictEqual(U.md('`**a**`'), '

**a**

'); }); test('parseActions: search blocks', () => { assert.deepStrictEqual(U.parseActions('Ищу:\n```search\nnginx 1.27 changelog\n```'), [{kind: 'search', machine: '', path: '', body: 'nginx 1.27 changelog'}]); }); test('parseActions: fetch blocks', () => { assert.deepStrictEqual(U.parseActions('```fetch\nhttps://go.dev/doc/go1.24\n```'), [{kind: 'fetch', machine: '', path: '', body: 'https://go.dev/doc/go1.24'}]); }); test('parseActions: image blocks - a new picture, or an edit, with format, quality and file name in the first line', () => { assert.deepStrictEqual(U.parseActions('Рисую.\n```image\nкот в скафандре на луне\n```'), [{kind: 'image', machine: '', path: '', body: 'кот в скафандре на луне', edit: false, enhance: true, ratio: '', model: '', file: ''}]); assert.deepStrictEqual(U.parseActions('```image 16:9 artist\nзакат над морем\n```'), [{kind: 'image', machine: '', path: '', body: 'закат над морем', edit: false, enhance: true, ratio: '16:9', model: 'artist', file: ''}]); assert.deepStrictEqual(U.parseActions('```image edit my photo.jpg 0.2plus\nубери человека справа\n```'), [{kind: 'image', machine: '', path: '', body: 'убери человека справа', edit: true, enhance: true, ratio: '', model: '0.2plus', file: 'my photo.jpg'}]); assert.deepStrictEqual(U.parseActions('```image edit\nсделай ночь\n```')[0].file, ''); assert.strictEqual(U.parseActions('```image\nне закрыт').length, 0); }); test('parseActions: image blocks - noenhance asks for the description as it is', () => { assert.deepStrictEqual(U.parseActions('```image noenhance 3:2\nflat vector logo, white background\n```'), [{kind: 'image', machine: '', path: '', body: 'flat vector logo, white background', edit: false, enhance: false, ratio: '3:2', model: '', file: ''}]); assert.strictEqual(U.parseActions('```image enhance\nx\n```')[0].enhance, true); });