fuzzyworld-tools / files / tests / deploy.test.mjs
deploy.test.mjs
55e5fc3e 2026-11-04 Pavel Safronov | 1 | // node --test tests/deploy.test.mjs |
| 2 | import test from 'node:test'; | |
| 3 | import assert from 'node:assert/strict'; | |
| 4 | import fs from 'node:fs'; | |
| 5 | import os from 'node:os'; | |
| 6 | import path from 'node:path'; | |
| 7 | import { rsyncArgs, checkReplay, readConfig } from '../lib/deploy.mjs'; | |
| 8 | ||
| 9 | function configIn(fuzzyworld) { | |
| 10 | const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fw-deploy-test-')); | |
| 11 | fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'x', fuzzyworld: { app: 'x', ...fuzzyworld } })); | |
| 12 | return dir; | |
| 13 | } | |
| 14 | ||
| 15 | test('extra becomes protect filters, keep stays an exclude', () => { | |
| 16 | const args = rsyncArgs({ keep: ['app.apk'], extra: ['sim/*.js'] }, 'dist', 'dh:x/'); | |
| 17 | assert.deepEqual(args, ['-rlptz', '--delete', '--exclude', '/app.apk', '--filter', 'P /sim/*.js', 'dist/', 'dh:x/']); | |
| 18 | }); | |
| 19 | ||
| 20 | test('no keep or extra: plain rsync', () => { | |
| 21 | assert.deepEqual(rsyncArgs({}, 'dist', 'dh:x/'), ['-rlptz', '--delete', 'dist/', 'dh:x/']); | |
| 22 | }); | |
| 23 | ||
| 24 | test('extra entries are validated like keep', () => { | |
| 25 | for (const bad of ['/abs', '../up', 'a//b', '', 5]) { | |
| 26 | assert.throws(() => readConfig(configIn({ extra: [bad] })), /fuzzyworld\.extra/); | |
| 27 | } | |
| 28 | assert.ok(readConfig(configIn({ extra: ['sim/*.js', 'a/**/b'] }))); | |
| 29 | }); | |
| 30 | ||
| 31 | test('an entry in both keep and extra is refused', () => { | |
| 32 | assert.throws(() => readConfig(configIn({ keep: ['sim/*.js'], extra: ['sim/*.js'] })), /also in keep/); | |
| 33 | }); | |
| 34 | ||
| 35 | test('replay templates', () => { | |
| 36 | checkReplay('replay.html?report={record}'); | |
| 37 | checkReplay('r/replay.html?x=1&report={record}'); | |
| 38 | for (const bad of ['replay.html', '/replay.html?r={record}', '//evil.com/?r={record}', 'https://evil.com/?r={record}', | |
| 39 | '../x.html?r={record}', 'javascript:alert(1)//{record}', 'a\\b?r={record}', 'x'.repeat(201) + '{record}', 5, | |
| 40 | 'a%2e%2e/x.html?r={record}', 'a%00.html?r={record}', 'a b.html?r={record}', 'a\tb.html?r={record}', 'a\nb.html?r={record}']) { | |
| 41 | assert.throws(() => checkReplay(bad), /fuzzyworld\.replay/, String(bad)); | |
| 42 | } | |
| 43 | assert.throws(() => readConfig(configIn({ replay: 'nope' })), /fuzzyworld\.replay/); | |
| 44 | }); |