lifen-autotest/node_modules/cucumber-expressions/test/cucumber_expression_generator_test.js

249 lines
7.3 KiB
JavaScript

/* eslint-env mocha */
const assert = require('assert')
const CucumberExpressionGenerator = require('../src/cucumber_expression_generator')
const CucumberExpression = require('../src/cucumber_expression')
const ParameterType = require('../src/parameter_type')
const ParameterTypeRegistry = require('../src/parameter_type_registry')
class Currency {}
describe('CucumberExpressionGenerator', () => {
let parameterTypeRegistry, generator
function assertExpression(expectedExpression, expectedArgumentNames, text) {
const generatedExpression = generator.generateExpressions(text)[0]
assert.deepEqual(generatedExpression.parameterNames, expectedArgumentNames)
assert.equal(generatedExpression.source, expectedExpression)
const cucumberExpression = new CucumberExpression(
generatedExpression.source,
parameterTypeRegistry
)
const match = cucumberExpression.match(text)
if (match === null) {
assert.fail(
`Expected text '${text}' to match generated expression '${
generatedExpression.source
}'`
)
}
assert.equal(match.length, expectedArgumentNames.length)
}
beforeEach(() => {
parameterTypeRegistry = new ParameterTypeRegistry()
generator = new CucumberExpressionGenerator(parameterTypeRegistry)
})
it('documents expression generation', () => {
const parameterRegistry = new ParameterTypeRegistry()
/// [generate-expression]
const generator = new CucumberExpressionGenerator(parameterRegistry)
const undefinedStepText = 'I have 2 cucumbers and 1.5 tomato'
const generatedExpression = generator.generateExpressions(
undefinedStepText
)[0]
assert.equal(
generatedExpression.source,
'I have {int} cucumbers and {float} tomato'
)
assert.equal(generatedExpression.parameterNames[0], 'int')
assert.equal(generatedExpression.parameterTypes[1].name, 'float')
/// [generate-expression]
})
it('generates expression for no args', () => {
assertExpression('hello', [], 'hello')
})
it('generates expression with escaped left parenthesis', () => {
assertExpression('\\(iii)', [], '(iii)')
})
it('generates expression with escaped left curly brace', () => {
assertExpression('\\{iii}', [], '{iii}')
})
it('generates expression with escaped slashes', () => {
assertExpression(
'The {int}\\/{int}\\/{int} hey',
['int', 'int2', 'int3'],
'The 1814/05/17 hey'
)
})
it('generates expression for int float arg', () => {
assertExpression(
'I have {int} cukes and {float} euro',
['int', 'float'],
'I have 2 cukes and 1.5 euro'
)
})
it('generates expression for strings', () => {
assertExpression(
'I like {string} and {string}',
['string', 'string2'],
'I like "bangers" and \'mash\''
)
})
it('generates expression with % sign', () => {
assertExpression('I am {int}%% foobar', ['int'], 'I am 20%% foobar')
})
it('generates expression for just int', () => {
assertExpression('{int}', ['int'], '99999')
})
it('numbers only second argument when builtin type is not reserved keyword', () => {
assertExpression(
'I have {float} cukes and {float} euro',
['float', 'float2'],
'I have 2.5 cukes and 1.5 euro'
)
})
it('generates expression for custom type', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'currency',
/[A-Z]{3}/,
Currency,
s => new Currency(s),
true,
false
)
)
assertExpression(
'I have a {currency} account',
['currency'],
'I have a EUR account'
)
})
it('prefers leftmost match when there is overlap', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'currency',
/cd/,
Currency,
s => new Currency(s),
true,
false
)
)
parameterTypeRegistry.defineParameterType(
new ParameterType('date', /bc/, Date, s => new Date(s), true, false)
)
assertExpression('a{date}defg', ['date'], 'abcdefg')
})
// TODO: prefers widest match
it('generates all combinations of expressions when several parameter types match', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'currency',
/x/,
null,
s => new Currency(s),
true,
false
)
)
parameterTypeRegistry.defineParameterType(
new ParameterType('date', /x/, null, s => new Date(s), true, false)
)
const generatedExpressions = generator.generateExpressions(
'I have x and x and another x'
)
const expressions = generatedExpressions.map(e => e.source)
assert.deepEqual(expressions, [
'I have {currency} and {currency} and another {currency}',
'I have {currency} and {currency} and another {date}',
'I have {currency} and {date} and another {currency}',
'I have {currency} and {date} and another {date}',
'I have {date} and {currency} and another {currency}',
'I have {date} and {currency} and another {date}',
'I have {date} and {date} and another {currency}',
'I have {date} and {date} and another {date}',
])
})
it('exposes parameter type names in generated expression', () => {
const expression = generator.generateExpressions(
'I have 2 cukes and 1.5 euro'
)[0]
const typeNames = expression.parameterTypes.map(parameter => parameter.name)
assert.deepEqual(typeNames, ['int', 'float'])
})
it('matches parameter types with optional capture groups', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'optional-flight',
/(1st flight)?/,
null,
s => s,
true,
false
)
)
parameterTypeRegistry.defineParameterType(
new ParameterType(
'optional-hotel',
/(1st hotel)?/,
null,
s => s,
true,
false
)
)
const expression = generator.generateExpressions(
'I reach Stage4: 1st flight-1st hotel'
)[0]
// While you would expect this to be `I reach Stage{int}: {optional-flight}-{optional-hotel}` the `-1` causes
// {int} to match just before {optional-hotel}.
assert.equal(
expression.source,
'I reach Stage{int}: {optional-flight}{int}st hotel'
)
})
it('generates at most 256 expressions', () => {
for (let i = 0; i < 4; i++) {
parameterTypeRegistry.defineParameterType(
new ParameterType('my-type-' + i, /[a-z]/, null, s => s, true, false)
)
}
// This would otherwise generate 4^11=419430 expressions and consume just shy of 1.5GB.
const expressions = generator.generateExpressions('a simple step')
assert.equal(expressions.length, 256)
})
it('prefers expression with longest non empty match', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType('zero-or-more', /[a-z]*/, null, s => s, true, false)
)
parameterTypeRegistry.defineParameterType(
new ParameterType('exactly-one', /[a-z]/, null, s => s, true, false)
)
const expressions = generator.generateExpressions('a simple step')
assert.equal(expressions.length, 2)
assert.equal(
expressions[0].source,
'{exactly-one} {zero-or-more} {zero-or-more}'
)
assert.equal(
expressions[1].source,
'{zero-or-more} {zero-or-more} {zero-or-more}'
)
})
})