fx/npm/test.js
2023-09-07 16:36:21 +02:00

186 lines
6.1 KiB
JavaScript

async function test(name, fn) {
try {
await fn(await import('node:assert/strict'))
console.log(`${name}`)
} catch (err) {
console.error(`${name}`)
throw err
}
}
async function run(json, code = '') {
const {spawnSync} = await import('node:child_process')
return spawnSync(`echo '${typeof json === 'string' ? json : JSON.stringify(json)}' | node index.js ${code}`, {
stdio: 'pipe',
encoding: 'utf8',
shell: true
})
}
void async function main() {
await test('properly formatted', async t => {
const {stdout} = await run([{'greeting': 'hello world'}])
t.deepEqual(stdout, '[\n {\n "greeting": "hello world"\n }\n]\n')
})
await test('format - escape newline', async t => {
const {stdout} = await run(`{"foo": "bar\\\\nbaz"}`)
t.equal(stdout, '{\n "foo": "bar\\nbaz"\n}\n')
})
await test('parseJson - valid json', async t => {
const obj = {a: 2.3e100, b: 'str', c: null, d: false, e: [1, 2, 3]}
const {stdout, stderr} = await run(obj)
t.equal(stderr, '')
t.equal(stdout, JSON.stringify(obj, null, 2) + '\n')
})
await test('parseJson - invalid json', async t => {
const {stderr, status} = await run('{invalid}')
t.equal(status, 1)
t.ok(stderr.includes('SyntaxError'))
})
await test('parseJson - invalid number', async t => {
const {stderr, status} = await run('{"num": 12.3.4}')
t.equal(status, 1)
t.ok(stderr.includes('SyntaxError'))
})
await test('parseJson - string control chars', async t => {
const {stderr, status} = await run('"\t"')
t.equal(status, 1)
t.ok(stderr.includes('SyntaxError'))
})
await test('parseJson - numbers', async t => {
t.equal((await run('1.2e300')).stdout, '1.2e+300\n')
t.equal((await run('123456789012345678901234567890')).stdout, '123456789012345678901234567890\n')
t.equal((await run('23')).stdout, '23\n')
t.equal((await run('0')).stdout, '0\n')
t.equal((await run('0e+2')).stdout, '0\n')
t.equal((await run('0e+2')).stdout, '0\n')
t.equal((await run('0.0')).stdout, '0\n')
t.equal((await run('-0')).stdout, '0\n')
t.equal((await run('2.3')).stdout, '2.3\n')
t.equal((await run('2300e3')).stdout, '2300000\n')
t.equal((await run('2300e+3')).stdout, '2300000\n')
t.equal((await run('-2')).stdout, '-2\n')
t.equal((await run('2e-3')).stdout, '0.002\n')
t.equal((await run('2.3e-3')).stdout, '0.0023\n')
})
await test('parseJson - object tailing comma', async t => {
const {stdout} = await run('{"a": 1,}')
t.equal(stdout, '{\n "a": 1\n}\n')
})
await test('parseJson - array tailing comma', async t => {
const {stdout} = await run('[1,]')
t.equal(stdout, '[\n 1\n]\n')
})
await test('parseJson - comments', async t => {
const {stdout} = await run('/* comment */ [1 // comment\n]')
t.equal(stdout, '[\n 1\n]\n')
})
await test('transform - anonymous function', async t => {
const {stdout} = await run({'key': 'value'}, '\'function (x) { return x.key }\'')
t.equal(stdout, 'value\n')
})
await test('transform - arrow function', async t => {
const {stdout} = await run({'key': 'value'}, '\'x => x.key\'')
t.equal(stdout, 'value\n')
})
await test('transform - arrow function with param brackets', async t => {
const {stdout} = await run({'key': 'value'}, `'(x) => x.key'`)
t.equal(stdout, 'value\n')
})
await test('transform - this is json', async t => {
const {stdout} = await run([1, 2, 3, 4, 5], `'this.map(x => x * this.length)'`)
t.deepEqual(JSON.parse(stdout), [5, 10, 15, 20, 25])
})
await test('transform - chain works', async t => {
const {stdout} = await run({'items': ['foo', 'bar']}, `'this.items' '.' 'x => x[1]'`)
t.equal(stdout, 'bar\n')
})
await test('transform - map works', async t => {
const {stdout} = await run([1, 2, 3], `'map(x * 2)'`)
t.deepEqual(JSON.parse(stdout), [2, 4, 6])
})
await test('transform - map works with dot', async t => {
const {stdout} = await run([{foo: 'bar'}], `'map(.foo)'`)
t.deepEqual(JSON.parse(stdout), ['bar'])
})
await test('transform - map works with func', async t => {
const {stdout} = await run([{foo: 'bar'}], `'map(x => x.foo)'`)
t.deepEqual(JSON.parse(stdout), ['bar'])
})
await test('transform - map passes index', async t => {
const {stdout} = await run([1, 2, 3], `'map((x, i) => x * i)'`)
t.deepEqual(JSON.parse(stdout), [0, 2, 6])
})
await test('transform - flat map works', async t => {
const {stdout} = await run({master: {foo: [{bar: [{val: 1}]}]}}, '.master.foo[].bar[].val')
t.deepEqual(JSON.parse(stdout), [1])
})
await test('transform - flat map works on the first level', async t => {
const {stdout} = await run([{val: 1}, {val: 2}], '.[].val')
t.deepEqual(JSON.parse(stdout), [1, 2])
})
await test('transform - sort & uniq', async t => {
const {stdout} = await run([2, 2, 3, 1], `sort uniq`)
t.deepEqual(JSON.parse(stdout), [1, 2, 3])
})
await test('transform - skip', async t => {
const {stdout} = await run(42, `skip`)
t.equal(stdout, '')
})
await test('transform - invalid code argument', async t => {
const json = {foo: 'bar'}
const code = '".foo.toUpperCase("'
const {stderr, status} = await run(json, code)
t.equal(status, 1)
t.ok(stderr.includes(`SyntaxError: Unexpected token '}'`))
})
await test('stream - objects', async t => {
const {stdout} = await run('{"foo": "bar"}\n{"foo": "baz"}')
t.equal(stdout, '{\n "foo": "bar"\n}\n{\n "foo": "baz"\n}\n')
})
await test('stream - strings', async t => {
const {stdout} = await run('"foo"\n"bar"')
t.equal(stdout, 'foo\nbar\n')
})
await test('flags - raw flag', async t => {
const {stdout} = await run(123, `-r 'x => typeof x'`)
t.equal(stdout, 'string\n')
})
await test('flags - slurp flag', async t => {
const {stdout} = await run('{"foo": "bar"}\n{"foo": "baz"}', `-s '.[1].foo'`)
t.equal(stdout, 'baz\n')
})
await test('flags - slurp raw', async t => {
const {stdout} = await run('hello,\nworld!', `-rs '.join(" ")'`)
t.equal(stdout, 'hello, world!\n')
})
}()