blob: ce0fc0ce55a4579be631a1df7711915735161d02 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-env mocha */
'use strict'
const assert = require('assert')
const composer = require('../composer')
function check (combinator, n, p, name) {
if (n === undefined) {
it('variable argument count', function () {
for (let i = 0; i < 5; i++) composer[combinator](...Array(i).fill('foo'))
for (let i = 0; i < 5; i++) composer[combinator](...Array(i).fill(() => { }))
})
} else {
it('argument count', function () {
for (let i = n; i <= (p || n); i++) composer[combinator](...Array(i).fill('foo'))
})
it('too many arguments', function () {
try {
composer[combinator](...Array((p || n) + 1).fill('foo'))
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Too many arguments'))
}
})
if (n > 0) {
it('too few arguments', function () {
try {
composer[combinator](...Array(n - 1).fill('foo'))
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
}
}
it('combinator type', function () {
assert.ok(composer[combinator](...Array(n || 0).fill('foo')).type === name || combinator)
})
}
describe('composer', function () {
describe('composer.action', function () {
it('argument count', function () {
composer.action('foo')
})
it('too many arguments', function () {
try {
composer.action('foo', {}, 'foo')
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Too many arguments'))
}
})
it('too few arguments', function () {
try {
composer.action()
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Name must be a string'))
}
})
it('combinator type', function () {
assert.ok(composer.action('foo').type === 'action')
})
it('valid and invalid names', function () {
let combos = [
{ n: 42, s: false, e: 'Name must be a string' },
{ n: '', s: false, e: 'Name is not valid' },
{ n: ' ', s: false, e: 'Name is not valid' },
{ n: '/', s: false, e: 'Name is not valid' },
{ n: '//', s: false, e: 'Name is not valid' },
{ n: '/a', s: false, e: 'Name is not valid' },
{ n: '/a/b/c/d', s: false, e: 'Name is not valid' },
{ n: '/a/b/c/d/', s: false, e: 'Name is not valid' },
{ n: 'a/b/c/d', s: false, e: 'Name is not valid' },
{ n: '/a/ /b', s: false, e: 'Name is not valid' },
{ n: 'a', e: false, s: '/_/a' },
{ n: 'a/b', e: false, s: '/_/a/b' },
{ n: 'a/b/c', e: false, s: '/a/b/c' },
{ n: '/a/b', e: false, s: '/a/b' },
{ n: '/a/b/c', e: false, s: '/a/b/c' }
]
combos.forEach(({ n, s, e }) => {
if (s) {
// good cases
assert.ok(composer.action(n).name, s)
} else {
// error cases
try {
composer.action(n)
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith(e))
}
}
})
})
it('valid and invalid options', function () {
composer.action('foo', {})
try {
composer.action('foo', 42)
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
})
describe('composer.function', function () {
check('function', 1)
it('function', function () {
composer.function(() => { })
})
it('string', function () {
composer.function('() => {}')
})
it('number (invalid)', function () {
try {
composer.function(42)
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
})
describe('composer.literal', function () {
check('literal', 1)
it('boolean', function () {
composer.literal(true)
})
it('number', function () {
composer.literal(42)
})
it('string', function () {
composer.literal('foo')
})
it('dictionary', function () {
composer.literal({ foo: 42 })
})
it('function (invalid)', function () {
try {
composer.literal(() => { })
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
})
describe('composer.value', function () {
check('value', 1)
it('boolean', function () {
composer.value(true)
})
it('number', function () {
composer.value(42)
})
it('string', function () {
composer.value('foo')
})
it('dictionary', function () {
composer.value({ foo: 42 })
})
it('function (invalid)', function () {
try {
composer.value(() => { })
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
})
describe('composer.parse', function () {
it('argument count', function () {
composer.parse({ 'type': 'sequence', 'components': [] })
})
it('too many arguments', function () {
try {
composer.parse({ 'type': 'sequence', 'components': [] }, 'foo')
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Too many arguments'))
}
})
it('too few arguments', function () {
try {
composer.parse()
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('combinator type', function () {
assert.ok(composer.parse({
'type': 'sequence',
'components': [{
'type': 'action',
'name': 'echo'
}, {
'type': 'action',
'name': 'echo'
}]
}).type === 'sequence')
})
})
describe('composer.task', function () {
check('task', 1, 1, 'action')
it('string', function () {
composer.task('isNotOne')
})
it('function', function () {
composer.task(() => { })
})
it('null', function () {
composer.task(null)
})
it('boolean (invalid)', function () {
try {
composer.task(false)
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('number (invalid)', function () {
try {
composer.task(42)
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('dictionary (invalid)', function () {
try {
composer.task({ foo: 42 })
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
})
describe('composer.let', function () {
it('variable argument count', function () {
composer.let({})
composer.let({}, 'foo')
composer.let({}, 'foo', 'foo')
})
it('too few arguments', function () {
try {
composer.let()
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('combinator type', function () {
assert.ok(composer.let({}).type === 'let')
})
})
describe('composer.repeat', function () {
it('variable argument count', function () {
composer.repeat(42)
composer.repeat(42, 'foo')
composer.repeat(42, 'foo', 'foo')
})
it('too few arguments', function () {
try {
composer.repeat()
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('combinator type', function () {
assert.ok(composer.repeat(42).type === 'repeat')
})
})
describe('composer.retry', function () {
it('variable argument count', function () {
composer.retry(42)
composer.retry(42, 'foo')
composer.retry(42, 'foo', 'foo')
})
it('too few arguments', function () {
try {
composer.retry()
assert.fail()
} catch (error) {
assert.ok(error.message.startsWith('Invalid argument'))
}
})
it('combinator type', function () {
assert.ok(composer.retry(42).type === 'retry')
})
})
describe('composer.if', function () {
check('if', 2, 3)
})
describe('composer.if_nosave', function () {
check('if_nosave', 2, 3)
})
describe('composer.while', function () {
check('while', 2)
})
describe('composer.while_nosave', function () {
check('while_nosave', 2)
})
describe('composer.dowhile', function () {
check('dowhile', 2)
})
describe('composer.dowhile_nosave', function () {
check('dowhile_nosave', 2)
})
describe('composer.try', function () {
check('try', 2)
})
describe('composer.finally', function () {
check('finally', 2)
})
describe('composer.empty', function () {
check('empty', 0)
})
describe('composer.mask', function () {
check('mask')
})
describe('composer.async', function () {
check('async')
})
describe('composer.retain', function () {
check('retain')
})
describe('composer.retain_catch', function () {
check('retain_catch')
})
describe('composer.sequence', function () {
check('sequence')
})
describe('composer.seq', function () {
check('seq')
})
describe('composer.merge', function () {
check('merge')
})
describe('composer.parallel', function () {
check('parallel')
})
describe('composer.par', function () {
check('par')
})
describe('composer.map', function () {
check('map')
})
describe('composer.dynamic', function () {
check('dynamic', 0)
})
})