Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 1x 1x 1x 1x 78x 105x 78x 1x 77x 1x 1x 1x 78x 78x 78x 78x 77x 75x 64x 64x 78x 78x 23x 3x 20x 19x 77x 7x 7x 5x 10x 3x 2x 75x 78x 77x 77x 67x 67x 66x 66x 60x 6x 4x 30x 3x 66x 38x 28x 56x 28x 1x | const Argument = require('./argument') const TreeRegexp = require('./tree_regexp') const ParameterType = require('./parameter_type') const { UndefinedParameterTypeError, CucumberExpressionError, } = require('./errors') // RegExps with the g flag are stateful in JavaScript. In order to be able // to reuse them we have to wrap them in a function. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test // Does not include (){} characters because they have special meaning const ESCAPE_REGEXP = () => /([\\^[$.|?*+])/g const PARAMETER_REGEXP = () => /(\\\\)?{([^}]*)}/g const OPTIONAL_REGEXP = () => /(\\\\)?\(([^)]+)\)/g const ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP = () => /([^\s^/]+)((\/[^\s^/]+)+)/g const DOUBLE_ESCAPE = '\\\\' const PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE = 'Parameter types cannot be alternative: ' const PARAMETER_TYPES_CANNOT_BE_OPTIONAL = 'Parameter types cannot be optional: ' class CucumberExpression { /** * @param expression * @param parameterTypeRegistry */ constructor(expression, parameterTypeRegistry) { this._expression = expression this._parameterTypes = [] expression = this.processEscapes(expression) expression = this.processOptional(expression) expression = this.processAlternation(expression) expression = this.processParameters(expression, parameterTypeRegistry) expression = `^${expression}$` this._treeRegexp = new TreeRegexp(expression) } processEscapes(expression) { return expression.replace(ESCAPE_REGEXP(), '\\$1') } processOptional(expression) { return expression.replace(OPTIONAL_REGEXP(), (match, p1, p2) => { if (p1 === DOUBLE_ESCAPE) { return `\\(${p2}\\)` } this._checkNoParameterType(p2, PARAMETER_TYPES_CANNOT_BE_OPTIONAL) return `(?:${p2})?` }) } processAlternation(expression) { return expression.replace( ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP(), match => { // replace \/ with / // replace / with | const replacement = match.replace(/\//g, '|').replace(/\\\|/g, '/') if (replacement.indexOf('|') !== -1) { for (const part of replacement.split(/\|/)) { this._checkNoParameterType( part, PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE ) } return `(?:${replacement})` } else { return replacement } } ) } processParameters(expression, parameterTypeRegistry) { return expression.replace(PARAMETER_REGEXP(), (match, p1, p2) => { if (p1 === DOUBLE_ESCAPE) return `\\{${p2}\\}` const typeName = p2 ParameterType.checkParameterTypeName(typeName) const parameterType = parameterTypeRegistry.lookupByTypeName(typeName) if (!parameterType) throw new UndefinedParameterTypeError(typeName) this._parameterTypes.push(parameterType) return buildCaptureRegexp(parameterType.regexps) }) } match(text) { return Argument.build(this._treeRegexp, text, this._parameterTypes) } get regexp() { return this._treeRegexp.regexp } get source() { return this._expression } _checkNoParameterType(s, message) { if (s.match(PARAMETER_REGEXP())) { throw new CucumberExpressionError(message + this.source) } } } function buildCaptureRegexp(regexps) { if (regexps.length === 1) { return `(${regexps[0]})` } const captureGroups = regexps.map(group => { return `(?:${group})` }) return `(${captureGroups.join('|')})` } module.exports = CucumberExpression |