cucumber-expressions
Version:
Cucumber Expressions - a simpler alternative to Regular Expressions
254 lines (231 loc) • 7.38 kB
text/typescript
import assert from 'assert'
import assertThrows from './assert_throws'
import CucumberExpression from '../src/CucumberExpression'
import RegularExpression from '../src/RegularExpression'
import ParameterTypeRegistry from '../src/ParameterTypeRegistry'
import ParameterType from '../src/ParameterType'
class Color {
/// [color-constructor]
constructor(public readonly name: string) {}
/// [color-constructor]
}
class CssColor {
constructor(public readonly name: string) {}
}
describe('Custom parameter type', () => {
let parameterTypeRegistry: ParameterTypeRegistry
beforeEach(() => {
parameterTypeRegistry = new ParameterTypeRegistry()
/* eslint-disable prettier/prettier */
/// [add-color-parameter-type]
parameterTypeRegistry.defineParameterType(
new ParameterType(
'color', // name
/red|blue|yellow/, // regexp
Color, // type
s => new Color(s), // transformer
false, // useForSnippets
true // preferForRegexpMatch
)
)
/// [add-color-parameter-type]
/* eslint-enable prettier/prettier */
})
describe('CucumberExpression', () => {
it('throws exception for illegal character in parameter name', () => {
assertThrows(
() => new ParameterType('[string]', /.*/, String, s => s, false, true),
"Illegal character '[' in parameter name {[string]}"
)
})
it('matches parameters with custom parameter type', () => {
const expression = new CucumberExpression(
'I have a {color} ball',
parameterTypeRegistry
)
const value = expression.match('I have a red ball')[0].getValue(null)
assert.strictEqual(value.name, 'red')
})
it('matches parameters with multiple capture groups', () => {
class Coordinate {
constructor(
public readonly x: number,
public readonly y: number,
public readonly z: number
) {}
}
parameterTypeRegistry.defineParameterType(
new ParameterType(
'coordinate',
/(\d+),\s*(\d+),\s*(\d+)/,
Coordinate,
(x: string, y: string, z: string) =>
new Coordinate(Number(x), Number(y), Number(z)),
true,
true
)
)
const expression = new CucumberExpression(
'A {int} thick line from {coordinate} to {coordinate}',
parameterTypeRegistry
)
const args = expression.match('A 5 thick line from 10,20,30 to 40,50,60')
const thick = args[0].getValue(null)
assert.strictEqual(thick, 5)
const from = args[1].getValue(null)
assert.strictEqual(from.x, 10)
assert.strictEqual(from.y, 20)
assert.strictEqual(from.z, 30)
const to = args[2].getValue(null)
assert.strictEqual(to.x, 40)
assert.strictEqual(to.y, 50)
assert.strictEqual(to.z, 60)
})
it('matches parameters with custom parameter type using optional capture group', () => {
parameterTypeRegistry = new ParameterTypeRegistry()
parameterTypeRegistry.defineParameterType(
new ParameterType(
'color',
[/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/],
Color,
s => new Color(s),
false,
true
)
)
const expression = new CucumberExpression(
'I have a {color} ball',
parameterTypeRegistry
)
const value = expression.match('I have a dark red ball')[0].getValue(null)
assert.strictEqual(value.name, 'dark red')
})
it('defers transformation until queried from argument', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'throwing',
/bad/,
null,
s => {
throw new Error(`Can't transform [${s}]`)
},
false,
true
)
)
const expression = new CucumberExpression(
'I have a {throwing} parameter',
parameterTypeRegistry
)
const args = expression.match('I have a bad parameter')
assertThrows(() => args[0].getValue(null), "Can't transform [bad]")
})
describe('conflicting parameter type', () => {
it('is detected for type name', () => {
assertThrows(
() =>
parameterTypeRegistry.defineParameterType(
new ParameterType(
'color',
/.*/,
CssColor,
s => new CssColor(s),
false,
true
)
),
'There is already a parameter type with name color'
)
})
it('is not detected for type', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'whatever',
/.*/,
Color,
s => new Color(s),
false,
false
)
)
})
it('is not detected for regexp', () => {
parameterTypeRegistry.defineParameterType(
new ParameterType(
'css-color',
/red|blue|yellow/,
CssColor,
s => new CssColor(s),
true,
false
)
)
assert.strictEqual(
new CucumberExpression(
'I have a {css-color} ball',
parameterTypeRegistry
)
.match('I have a blue ball')[0]
.getValue(null).constructor,
CssColor
)
assert.strictEqual(
new CucumberExpression(
'I have a {css-color} ball',
parameterTypeRegistry
)
.match('I have a blue ball')[0]
.getValue(null).name,
'blue'
)
assert.strictEqual(
new CucumberExpression('I have a {color} ball', parameterTypeRegistry)
.match('I have a blue ball')[0]
.getValue(null).constructor,
Color
)
assert.strictEqual(
new CucumberExpression('I have a {color} ball', parameterTypeRegistry)
.match('I have a blue ball')[0]
.getValue(null).name,
'blue'
)
})
})
// JavaScript-specific
it('creates arguments using async transform', async () => {
parameterTypeRegistry = new ParameterTypeRegistry()
/// [add-async-parameter-type]
parameterTypeRegistry.defineParameterType(
new ParameterType(
'asyncColor',
/red|blue|yellow/,
Color,
async s => new Color(s),
false,
true
)
)
/// [add-async-parameter-type]
const expression = new CucumberExpression(
'I have a {asyncColor} ball',
parameterTypeRegistry
)
const args = await expression.match('I have a red ball')
const value = await args[0].getValue(null)
assert.strictEqual(value.name, 'red')
})
})
describe('RegularExpression', () => {
it('matches arguments with custom parameter type', () => {
const expression = new RegularExpression(
/I have a (red|blue|yellow) ball/,
parameterTypeRegistry
)
const value = expression.match('I have a red ball')[0].getValue(null)
assert.strictEqual(value.constructor, Color)
assert.strictEqual(value.name, 'red')
})
})
})