fuzzyworld

fuzzyworld-tools / files / tests / deploy.test.mjs

deploy.test.mjs

Blame: the commit that last changed each line · file · history

55e5fc3e 2026-11-04 Pavel Safronov1// node --test tests/deploy.test.mjs
2import test from 'node:test';
3import assert from 'node:assert/strict';
4import fs from 'node:fs';
5import os from 'node:os';
6import path from 'node:path';
7import { rsyncArgs, checkReplay, readConfig } from '../lib/deploy.mjs';
8
9function 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
15test('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
20test('no keep or extra: plain rsync', () => {
21 assert.deepEqual(rsyncArgs({}, 'dist', 'dh:x/'), ['-rlptz', '--delete', 'dist/', 'dh:x/']);
22});
23
24test('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
31test('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
35test('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});