271 lines
7.0 KiB
JavaScript
271 lines
7.0 KiB
JavaScript
/* eslint-env mocha */
|
|
const assert = require('assert')
|
|
const {
|
|
CucumberExpression,
|
|
ParameterTypeRegistry,
|
|
ParameterType,
|
|
} = require('../src/index')
|
|
|
|
describe('CucumberExpression', () => {
|
|
it('documents match arguments', () => {
|
|
const parameterTypeRegistry = new ParameterTypeRegistry()
|
|
|
|
/// [capture-match-arguments]
|
|
const expr = 'I have {int} cuke(s)'
|
|
const expression = new CucumberExpression(expr, parameterTypeRegistry)
|
|
const args = expression.match('I have 7 cukes')
|
|
assert.equal(7, args[0].getValue(null))
|
|
/// [capture-match-arguments]
|
|
})
|
|
|
|
it('matches word', () => {
|
|
assert.deepEqual(match('three {word} mice', 'three blind mice'), ['blind'])
|
|
})
|
|
|
|
it('matches double quoted string', () => {
|
|
assert.deepEqual(match('three {string} mice', 'three "blind" mice'), [
|
|
'blind',
|
|
])
|
|
})
|
|
|
|
it('matches multiple double quoted strings', () => {
|
|
assert.deepEqual(
|
|
match(
|
|
'three {string} and {string} mice',
|
|
'three "blind" and "crippled" mice'
|
|
),
|
|
['blind', 'crippled']
|
|
)
|
|
})
|
|
|
|
it('matches single quoted string', () => {
|
|
assert.deepEqual(match('three {string} mice', "three 'blind' mice"), [
|
|
'blind',
|
|
])
|
|
})
|
|
|
|
it('matches multiple single quoted strings', () => {
|
|
assert.deepEqual(
|
|
match(
|
|
'three {string} and {string} mice',
|
|
"three 'blind' and 'crippled' mice"
|
|
),
|
|
['blind', 'crippled']
|
|
)
|
|
})
|
|
|
|
it('does not match misquoted string', () => {
|
|
assert.deepEqual(match('three {string} mice', 'three "blind\' mice'), null)
|
|
})
|
|
|
|
it('matches single quoted string with double quotes', () => {
|
|
assert.deepEqual(match('three {string} mice', 'three \'"blind"\' mice'), [
|
|
'"blind"',
|
|
])
|
|
})
|
|
|
|
it('matches double quoted string with single quotes', () => {
|
|
assert.deepEqual(match('three {string} mice', 'three "\'blind\'" mice'), [
|
|
"'blind'",
|
|
])
|
|
})
|
|
|
|
it('matches double quoted string with escaped double quote', () => {
|
|
assert.deepEqual(match('three {string} mice', 'three "bl\\"nd" mice'), [
|
|
'bl"nd',
|
|
])
|
|
})
|
|
|
|
it('matches single quoted string with escaped single quote', () => {
|
|
assert.deepEqual(match('three {string} mice', "three 'bl\\'nd' mice"), [
|
|
"bl'nd",
|
|
])
|
|
})
|
|
|
|
it('matches single quoted string with escaped single quote', () => {
|
|
assert.deepEqual(match('three {string} mice', "three 'bl\\'nd' mice"), [
|
|
"bl'nd",
|
|
])
|
|
})
|
|
|
|
it('matches escaped parenthesis', () => {
|
|
assert.deepEqual(
|
|
match(
|
|
'three \\(exceptionally) {string} mice',
|
|
'three (exceptionally) "blind" mice'
|
|
),
|
|
['blind']
|
|
)
|
|
})
|
|
|
|
it('matches escaped slash', () => {
|
|
assert.deepEqual(match('12\\/2020', '12/2020'), [])
|
|
})
|
|
|
|
it('matches int', () => {
|
|
assert.deepEqual(match('{int}', '22'), [22])
|
|
})
|
|
|
|
it("doesn't match float as int", () => {
|
|
assert.deepEqual(match('{int}', '1.22'), null)
|
|
})
|
|
|
|
it('matches float', () => {
|
|
assert.deepEqual(match('{float}', '0.22'), [0.22])
|
|
assert.deepEqual(match('{float}', '.22'), [0.22])
|
|
})
|
|
|
|
it('matches anonymous', () => {
|
|
assert.deepEqual(match('{}', '0.22'), ['0.22'])
|
|
})
|
|
|
|
it('throws unknown parameter type', () => {
|
|
try {
|
|
match('{unknown}', 'something')
|
|
assert.fail()
|
|
} catch (expected) {
|
|
assert.equal(expected.message, 'Undefined parameter type {unknown}')
|
|
}
|
|
})
|
|
|
|
it('does not allow optional parameter types', () => {
|
|
try {
|
|
match('({int})', '3')
|
|
assert.fail()
|
|
} catch (expected) {
|
|
assert.equal(
|
|
expected.message,
|
|
'Parameter types cannot be optional: ({int})'
|
|
)
|
|
}
|
|
})
|
|
|
|
it('allows escaped optional parameter types', () => {
|
|
assert.deepEqual(match('\\({int})', '(3)'), [3])
|
|
})
|
|
|
|
it('does not allow text/parameter type alternation', () => {
|
|
try {
|
|
match('x/{int}', '3')
|
|
assert.fail()
|
|
} catch (expected) {
|
|
assert.equal(
|
|
expected.message,
|
|
'Parameter types cannot be alternative: x/{int}'
|
|
)
|
|
}
|
|
})
|
|
|
|
it('does not allow parameter type/text alternation', () => {
|
|
try {
|
|
match('{int}/x', '3')
|
|
assert.fail()
|
|
} catch (expected) {
|
|
assert.equal(
|
|
expected.message,
|
|
'Parameter types cannot be alternative: {int}/x'
|
|
)
|
|
}
|
|
})
|
|
|
|
for (const c of '[]()$.|?*+'.split('')) {
|
|
it(`does not allow parameter type with ${c}`, () => {
|
|
try {
|
|
match(`{${c}string}`, 'something')
|
|
assert.fail()
|
|
} catch (expected) {
|
|
assert.equal(
|
|
expected.message,
|
|
`Illegal character '${c}' in parameter name {${c}string}`
|
|
)
|
|
}
|
|
})
|
|
}
|
|
|
|
it('exposes source', () => {
|
|
const expr = 'I have {int} cuke(s)'
|
|
assert.equal(
|
|
new CucumberExpression(expr, new ParameterTypeRegistry()).source,
|
|
expr
|
|
)
|
|
})
|
|
|
|
// JavaScript-specific
|
|
|
|
it('delegates transform to custom object', () => {
|
|
const parameterTypeRegistry = new ParameterTypeRegistry()
|
|
parameterTypeRegistry.defineParameterType(
|
|
new ParameterType(
|
|
'widget',
|
|
/\w+/,
|
|
null,
|
|
function(s) {
|
|
return this.createWidget(s)
|
|
},
|
|
false,
|
|
true
|
|
)
|
|
)
|
|
const expression = new CucumberExpression(
|
|
'I have a {widget}',
|
|
parameterTypeRegistry
|
|
)
|
|
|
|
const world = {
|
|
createWidget(s) {
|
|
return `widget:${s}`
|
|
},
|
|
}
|
|
|
|
const args = expression.match(`I have a bolt`)
|
|
assert.equal(args[0].getValue(world), 'widget:bolt')
|
|
})
|
|
|
|
describe('escapes special characters', () => {
|
|
;['\\', '[', ']', '^', '$', '.', '|', '?', '*', '+'].forEach(character => {
|
|
it(`escapes ${character}`, () => {
|
|
const expr = `I have {int} cuke(s) and ${character}`
|
|
const expression = new CucumberExpression(
|
|
expr,
|
|
new ParameterTypeRegistry()
|
|
)
|
|
const arg1 = expression.match(`I have 800 cukes and ${character}`)[0]
|
|
assert.equal(arg1.getValue(null), 800)
|
|
})
|
|
})
|
|
|
|
it(`escapes .`, () => {
|
|
const expr = `I have {int} cuke(s) and .`
|
|
const expression = new CucumberExpression(
|
|
expr,
|
|
new ParameterTypeRegistry()
|
|
)
|
|
assert.equal(expression.match(`I have 800 cukes and 3`), null)
|
|
const arg1 = expression.match(`I have 800 cukes and .`)[0]
|
|
assert.equal(arg1.getValue(null), 800)
|
|
})
|
|
|
|
it(`escapes |`, () => {
|
|
const expr = `I have {int} cuke(s) and a|b`
|
|
const expression = new CucumberExpression(
|
|
expr,
|
|
new ParameterTypeRegistry()
|
|
)
|
|
assert.equal(expression.match(`I have 800 cukes and a`), null)
|
|
assert.equal(expression.match(`I have 800 cukes and b`), null)
|
|
const arg1 = expression.match(`I have 800 cukes and a|b`)[0]
|
|
assert.equal(arg1.getValue(null), 800)
|
|
})
|
|
})
|
|
})
|
|
|
|
const match = (expression, text) => {
|
|
const cucumberExpression = new CucumberExpression(
|
|
expression,
|
|
new ParameterTypeRegistry()
|
|
)
|
|
const args = cucumberExpression.match(text)
|
|
if (!args) return null
|
|
return args.map(arg => arg.getValue(null))
|
|
}
|