cucumber-expressions
Advanced tools
Comparing version 7.0.1 to 7.0.2
@@ -1,4 +0,4 @@ | ||
import TreeRegexp from "./TreeRegexp"; | ||
import ParameterType from "./ParameterType"; | ||
import Group from "./Group"; | ||
import TreeRegexp from './TreeRegexp'; | ||
import ParameterType from './ParameterType'; | ||
import Group from './Group'; | ||
export default class Argument<T> { | ||
@@ -5,0 +5,0 @@ readonly group: Group; |
@@ -1,3 +0,3 @@ | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import ParameterType from "./ParameterType"; | ||
import GeneratedExpression from './GeneratedExpression'; | ||
import ParameterType from './ParameterType'; | ||
export default class CombinatorialGeneratedExpressionFactory { | ||
@@ -4,0 +4,0 @@ private readonly expressionTemplate; |
@@ -1,3 +0,3 @@ | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import Argument from "./Argument"; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry'; | ||
import Argument from './Argument'; | ||
export default class CucumberExpression { | ||
@@ -4,0 +4,0 @@ private readonly expression; |
@@ -30,5 +30,5 @@ "use strict"; | ||
}; | ||
var DOUBLE_ESCAPE = "\\\\"; | ||
var PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE = "Parameter types cannot be alternative: "; | ||
var PARAMETER_TYPES_CANNOT_BE_OPTIONAL = "Parameter types cannot be optional: "; | ||
var DOUBLE_ESCAPE = '\\\\'; | ||
var PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE = 'Parameter types cannot be alternative: '; | ||
var PARAMETER_TYPES_CANNOT_BE_OPTIONAL = 'Parameter types cannot be optional: '; | ||
var CucumberExpression = /** @class */ (function () { | ||
@@ -51,3 +51,3 @@ /** | ||
CucumberExpression.prototype.processEscapes = function (expression) { | ||
return expression.replace(ESCAPE_REGEXP(), "\\$1"); | ||
return expression.replace(ESCAPE_REGEXP(), '\\$1'); | ||
}; | ||
@@ -70,4 +70,4 @@ CucumberExpression.prototype.processOptional = function (expression) { | ||
// replace / with | | ||
var replacement = match.replace(/\//g, "|").replace(/\\\|/g, "/"); | ||
if (replacement.indexOf("|") !== -1) { | ||
var replacement = match.replace(/\//g, '|').replace(/\\\|/g, '/'); | ||
if (replacement.indexOf('|') !== -1) { | ||
try { | ||
@@ -141,4 +141,4 @@ for (var _b = __values(replacement.split(/\|/)), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
}); | ||
return "(" + captureGroups.join("|") + ")"; | ||
return "(" + captureGroups.join('|') + ")"; | ||
} | ||
//# sourceMappingURL=CucumberExpression.js.map |
@@ -1,4 +0,4 @@ | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import ParameterTypeMatcher from "./ParameterTypeMatcher"; | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry'; | ||
import ParameterTypeMatcher from './ParameterTypeMatcher'; | ||
import GeneratedExpression from './GeneratedExpression'; | ||
export default class CucumberExpressionGenerator { | ||
@@ -5,0 +5,0 @@ private readonly parameterTypeRegistry; |
@@ -27,3 +27,3 @@ "use strict"; | ||
var parameterTypeMatchers = this._createParameterTypeMatchers(text); | ||
var expressionTemplate = ""; | ||
var expressionTemplate = ''; | ||
var pos = 0; | ||
@@ -34,3 +34,3 @@ var _loop_1 = function () { | ||
try { | ||
for (var parameterTypeMatchers_1 = __values(parameterTypeMatchers), parameterTypeMatchers_1_1 = parameterTypeMatchers_1.next(); !parameterTypeMatchers_1_1.done; parameterTypeMatchers_1_1 = parameterTypeMatchers_1.next()) { | ||
for (var parameterTypeMatchers_1 = (e_1 = void 0, __values(parameterTypeMatchers)), parameterTypeMatchers_1_1 = parameterTypeMatchers_1.next(); !parameterTypeMatchers_1_1.done; parameterTypeMatchers_1_1 = parameterTypeMatchers_1.next()) { | ||
var parameterTypeMatcher = parameterTypeMatchers_1_1.value; | ||
@@ -63,3 +63,3 @@ var advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo(pos); | ||
try { | ||
for (var bestParameterTypeMatchers_1 = __values(bestParameterTypeMatchers), bestParameterTypeMatchers_1_1 = bestParameterTypeMatchers_1.next(); !bestParameterTypeMatchers_1_1.done; bestParameterTypeMatchers_1_1 = bestParameterTypeMatchers_1.next()) { | ||
for (var bestParameterTypeMatchers_1 = (e_2 = void 0, __values(bestParameterTypeMatchers)), bestParameterTypeMatchers_1_1 = bestParameterTypeMatchers_1.next(); !bestParameterTypeMatchers_1_1.done; bestParameterTypeMatchers_1_1 = bestParameterTypeMatchers_1.next()) { | ||
var parameterTypeMatcher = bestParameterTypeMatchers_1_1.value; | ||
@@ -81,6 +81,5 @@ if (parameterTypes.indexOf(parameterTypeMatcher.parameterType) === -1) { | ||
expressionTemplate += escape(text.slice(pos, bestParameterTypeMatcher_1.start)); | ||
expressionTemplate += "{%s}"; | ||
expressionTemplate += '{%s}'; | ||
pos = | ||
bestParameterTypeMatcher_1.start + | ||
bestParameterTypeMatcher_1.group.length; | ||
bestParameterTypeMatcher_1.start + bestParameterTypeMatcher_1.group.length; | ||
} | ||
@@ -108,3 +107,3 @@ else { | ||
var _this = this; | ||
return util_1.default.deprecate(function () { return _this.generateExpressions(text)[0]; }, "CucumberExpressionGenerator.generateExpression: Use CucumberExpressionGenerator.generateExpressions instead")(); | ||
return util_1.default.deprecate(function () { return _this.generateExpressions(text)[0]; }, 'CucumberExpressionGenerator.generateExpression: Use CucumberExpressionGenerator.generateExpressions instead')(); | ||
}; | ||
@@ -155,8 +154,8 @@ CucumberExpressionGenerator.prototype._createParameterTypeMatchers = function (text) { | ||
return s | ||
.replace(/%/g, "%%") // for util.format | ||
.replace(/\(/g, "\\(") | ||
.replace(/{/g, "\\{") | ||
.replace(/\//g, "\\/"); | ||
.replace(/%/g, '%%') // for util.format | ||
.replace(/\(/g, '\\(') | ||
.replace(/{/g, '\\{') | ||
.replace(/\//g, '\\/'); | ||
} | ||
module.exports = CucumberExpressionGenerator; | ||
//# sourceMappingURL=CucumberExpressionGenerator.js.map |
@@ -1,3 +0,3 @@ | ||
import ParameterType from "./ParameterType"; | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import ParameterType from './ParameterType'; | ||
import GeneratedExpression from './GeneratedExpression'; | ||
declare class CucumberExpressionError extends Error { | ||
@@ -14,2 +14,2 @@ } | ||
} | ||
export { AmbiguousParameterTypeError, UndefinedParameterTypeError, CucumberExpressionError }; | ||
export { AmbiguousParameterTypeError, UndefinedParameterTypeError, CucumberExpressionError, }; |
@@ -36,6 +36,6 @@ "use strict"; | ||
AmbiguousParameterTypeError._parameterTypeNames = function (parameterTypes) { | ||
return parameterTypes.map(function (p) { return "{" + p.name + "}"; }).join("\n "); | ||
return parameterTypes.map(function (p) { return "{" + p.name + "}"; }).join('\n '); | ||
}; | ||
AmbiguousParameterTypeError._expressions = function (generatedExpressions) { | ||
return generatedExpressions.map(function (e) { return e.source; }).join("\n "); | ||
return generatedExpressions.map(function (e) { return e.source; }).join('\n '); | ||
}; | ||
@@ -42,0 +42,0 @@ return AmbiguousParameterTypeError; |
@@ -1,2 +0,2 @@ | ||
import ParameterType from "./ParameterType"; | ||
import ParameterType from './ParameterType'; | ||
export default class GeneratedExpression { | ||
@@ -3,0 +3,0 @@ private readonly expressionTemplate; |
@@ -1,3 +0,3 @@ | ||
import Group from "./Group"; | ||
import RegexExecArray from "./RegexExecArray"; | ||
import Group from './Group'; | ||
import RegexExecArray from './RegexExecArray'; | ||
export default class GroupBuilder { | ||
@@ -4,0 +4,0 @@ source: string; |
@@ -20,3 +20,3 @@ "use strict"; | ||
}); | ||
return new Group_1.default(match[groupIndex] || null, match.index[groupIndex], match.index[groupIndex] + (match[groupIndex] || "").length, children); | ||
return new Group_1.default(match[groupIndex] || null, match.index[groupIndex], match.index[groupIndex] + (match[groupIndex] || '').length, children); | ||
}; | ||
@@ -23,0 +23,0 @@ GroupBuilder.prototype.setNonCapturing = function () { |
@@ -1,6 +0,6 @@ | ||
import CucumberExpression from "./CucumberExpression"; | ||
import RegularExpression from "./RegularExpression"; | ||
import CucumberExpressionGenerator from "./CucumberExpressionGenerator"; | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import ParameterType from "./ParameterType"; | ||
import CucumberExpression from './CucumberExpression'; | ||
import RegularExpression from './RegularExpression'; | ||
import CucumberExpressionGenerator from './CucumberExpressionGenerator'; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry'; | ||
import ParameterType from './ParameterType'; | ||
declare const _default: { | ||
@@ -7,0 +7,0 @@ CucumberExpression: typeof CucumberExpression; |
@@ -15,4 +15,4 @@ "use strict"; | ||
ParameterTypeRegistry: ParameterTypeRegistry_1.default, | ||
ParameterType: ParameterType_1.default | ||
ParameterType: ParameterType_1.default, | ||
}; | ||
//# sourceMappingURL=index.js.map |
@@ -55,3 +55,3 @@ "use strict"; | ||
ParameterType.checkParameterTypeName = function (typeName) { | ||
var unescapedTypeName = typeName.replace(UNESCAPE_PATTERN(), "$2"); | ||
var unescapedTypeName = typeName.replace(UNESCAPE_PATTERN(), '$2'); | ||
var match = unescapedTypeName.match(ILLEGAL_PARAMETER_NAME_PATTERN); | ||
@@ -79,3 +79,3 @@ if (match) { | ||
try { | ||
for (var _b = __values(["g", "i", "m", "y"]), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
for (var _b = __values(['g', 'i', 'm', 'y']), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var flag = _c.value; | ||
@@ -101,11 +101,11 @@ if (flags.indexOf(flag) !== -1) { | ||
if (flags === undefined) { | ||
flags = ""; | ||
flags = ''; | ||
if (regexp.ignoreCase) { | ||
flags += "i"; | ||
flags += 'i'; | ||
} | ||
if (regexp.global) { | ||
flags += "g"; | ||
flags += 'g'; | ||
} | ||
if (regexp.multiline) { | ||
flags += "m"; | ||
flags += 'm'; | ||
} | ||
@@ -112,0 +112,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import ParameterType from "./ParameterType"; | ||
import ParameterType from './ParameterType'; | ||
export default class ParameterTypeMatcher { | ||
@@ -3,0 +3,0 @@ readonly parameterType: ParameterType<any>; |
@@ -24,3 +24,3 @@ "use strict"; | ||
get: function () { | ||
return this.match && this.group !== ""; | ||
return this.match && this.group !== ''; | ||
}, | ||
@@ -27,0 +27,0 @@ enumerable: true, |
@@ -1,2 +0,2 @@ | ||
import ParameterType from "./ParameterType"; | ||
import ParameterType from './ParameterType'; | ||
export default class ParameterTypeRegistry { | ||
@@ -3,0 +3,0 @@ private readonly parameterTypeByName; |
@@ -28,7 +28,7 @@ "use strict"; | ||
this.parameterTypesByRegexp = new Map(); | ||
this.defineParameterType(new ParameterType_1.default("int", INTEGER_REGEXPS, Number, function (s) { return (s === undefined ? null : Number(s)); }, true, true)); | ||
this.defineParameterType(new ParameterType_1.default("float", FLOAT_REGEXP, Number, function (s) { return (s === undefined ? null : parseFloat(s)); }, true, false)); | ||
this.defineParameterType(new ParameterType_1.default("word", WORD_REGEXP, String, function (s) { return s; }, false, false)); | ||
this.defineParameterType(new ParameterType_1.default("string", STRING_REGEXP, String, function (s) { return s.replace(/\\"/g, '"').replace(/\\'/g, "'"); }, true, false)); | ||
this.defineParameterType(new ParameterType_1.default("", ANONYMOUS_REGEXP, String, function (s) { return s; }, false, true)); | ||
this.defineParameterType(new ParameterType_1.default('int', INTEGER_REGEXPS, Number, function (s) { return (s === undefined ? null : Number(s)); }, true, true)); | ||
this.defineParameterType(new ParameterType_1.default('float', FLOAT_REGEXP, Number, function (s) { return (s === undefined ? null : parseFloat(s)); }, true, false)); | ||
this.defineParameterType(new ParameterType_1.default('word', WORD_REGEXP, String, function (s) { return s; }, false, false)); | ||
this.defineParameterType(new ParameterType_1.default('string', STRING_REGEXP, String, function (s) { return s.replace(/\\"/g, '"').replace(/\\'/g, "'"); }, true, false)); | ||
this.defineParameterType(new ParameterType_1.default('', ANONYMOUS_REGEXP, String, function (s) { return s; }, false, true)); | ||
} | ||
@@ -83,3 +83,3 @@ Object.defineProperty(ParameterTypeRegistry.prototype, "parameterTypes", { | ||
parameterType.preferForRegexpMatch) { | ||
throw new Errors_1.CucumberExpressionError("There can only be one preferential parameter type per regexp. " + | ||
throw new Errors_1.CucumberExpressionError('There can only be one preferential parameter type per regexp. ' + | ||
("The regexp /" + parameterTypeRegexp + "/ is used for two preferential parameter types, {" + existingParameterType.name + "} and {" + parameterType.name + "}")); | ||
@@ -86,0 +86,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import Argument from "./Argument"; | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import Argument from './Argument'; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry'; | ||
export default class RegularExpression { | ||
@@ -4,0 +4,0 @@ readonly regexp: RegExp; |
@@ -1,2 +0,2 @@ | ||
import GroupBuilder from "./GroupBuilder"; | ||
import GroupBuilder from './GroupBuilder'; | ||
export default class TreeRegexp { | ||
@@ -3,0 +3,0 @@ regexp: RegExp; |
@@ -12,3 +12,3 @@ "use strict"; | ||
var _this = this; | ||
this.regexp = "string" === typeof regexp ? new RegExp(regexp) : regexp; | ||
this.regexp = 'string' === typeof regexp ? new RegExp(regexp) : regexp; | ||
this.regex = new becke_ch__regex__s0_0_v1__base__pl__lib_1.default(this.regexp.source, this.regexp.flags); | ||
@@ -21,10 +21,10 @@ var stack = [new GroupBuilder_1.default()]; | ||
var charClass = false; | ||
this.regexp.source.split("").forEach(function (c, n) { | ||
if (c === "[" && !escaping) { | ||
this.regexp.source.split('').forEach(function (c, n) { | ||
if (c === '[' && !escaping) { | ||
charClass = true; | ||
} | ||
else if (c === "]" && !escaping) { | ||
else if (c === ']' && !escaping) { | ||
charClass = false; | ||
} | ||
else if (c === "(" && !escaping && !charClass) { | ||
else if (c === '(' && !escaping && !charClass) { | ||
stack.push(new GroupBuilder_1.default()); | ||
@@ -34,3 +34,3 @@ groupStartStack.push(n + 1); | ||
} | ||
else if (c === ")" && !escaping && !charClass) { | ||
else if (c === ')' && !escaping && !charClass) { | ||
var gb = stack.pop(); | ||
@@ -47,10 +47,10 @@ var groupStart = groupStartStack.pop(); | ||
} | ||
else if (c === "?" && last === "(") { | ||
else if (c === '?' && last === '(') { | ||
nonCapturingMaybe = true; | ||
} | ||
else if (c === ":" && nonCapturingMaybe) { | ||
else if (c === ':' && nonCapturingMaybe) { | ||
stack[stack.length - 1].setNonCapturing(); | ||
nonCapturingMaybe = false; | ||
} | ||
escaping = c === "\\" && !escaping; | ||
escaping = c === '\\' && !escaping; | ||
last = c; | ||
@@ -57,0 +57,0 @@ }); |
@@ -9,5 +9,5 @@ "use strict"; | ||
exports.default = (function (fn, message) { | ||
var regexp = new RegExp(message.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&")); | ||
var regexp = new RegExp(message.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')); | ||
assert_1.default.throws(fn, regexp); | ||
}); | ||
//# sourceMappingURL=assert_throws.js.map |
@@ -9,24 +9,24 @@ "use strict"; | ||
var CombinatorialGeneratedExpressionFactory_1 = __importDefault(require("../src/CombinatorialGeneratedExpressionFactory")); | ||
describe("CucumberExpressionGenerator", function () { | ||
it("generates multiple expressions", function () { | ||
describe('CucumberExpressionGenerator', function () { | ||
it('generates multiple expressions', function () { | ||
var parameterTypeCombinations = [ | ||
[ | ||
new ParameterType_1.default("color", /red|blue|yellow/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default("csscolor", /red|blue|yellow/, null, function (s) { return s; }, false, true) | ||
new ParameterType_1.default('color', /red|blue|yellow/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default('csscolor', /red|blue|yellow/, null, function (s) { return s; }, false, true), | ||
], | ||
[ | ||
new ParameterType_1.default("date", /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default("datetime", /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default("timestamp", /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true) | ||
] | ||
new ParameterType_1.default('date', /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default('datetime', /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true), | ||
new ParameterType_1.default('timestamp', /\d{4}-\d{2}-\d{2}/, null, function (s) { return s; }, false, true), | ||
], | ||
]; | ||
var factory = new CombinatorialGeneratedExpressionFactory_1.default("I bought a {%s} ball on {%s}", parameterTypeCombinations); | ||
var factory = new CombinatorialGeneratedExpressionFactory_1.default('I bought a {%s} ball on {%s}', parameterTypeCombinations); | ||
var expressions = factory.generateExpressions().map(function (ge) { return ge.source; }); | ||
assert_1.default.deepStrictEqual(expressions, [ | ||
"I bought a {color} ball on {date}", | ||
"I bought a {color} ball on {datetime}", | ||
"I bought a {color} ball on {timestamp}", | ||
"I bought a {csscolor} ball on {date}", | ||
"I bought a {csscolor} ball on {datetime}", | ||
"I bought a {csscolor} ball on {timestamp}" | ||
'I bought a {color} ball on {date}', | ||
'I bought a {color} ball on {datetime}', | ||
'I bought a {color} ball on {timestamp}', | ||
'I bought a {csscolor} ball on {date}', | ||
'I bought a {csscolor} ball on {datetime}', | ||
'I bought a {csscolor} ball on {timestamp}', | ||
]); | ||
@@ -33,0 +33,0 @@ }); |
@@ -17,3 +17,3 @@ "use strict"; | ||
}()); | ||
describe("CucumberExpressionGenerator", function () { | ||
describe('CucumberExpressionGenerator', function () { | ||
var parameterTypeRegistry; | ||
@@ -36,94 +36,94 @@ var generator; | ||
}); | ||
it("documents expression generation", function () { | ||
it('documents expression generation', function () { | ||
parameterTypeRegistry = new ParameterTypeRegistry_1.default(); | ||
generator = new CucumberExpressionGenerator_1.default(parameterTypeRegistry); | ||
var undefinedStepText = "I have 2 cucumbers and 1.5 tomato"; | ||
var undefinedStepText = 'I have 2 cucumbers and 1.5 tomato'; | ||
var generatedExpression = generator.generateExpressions(undefinedStepText)[0]; | ||
assert_1.default.strictEqual(generatedExpression.source, "I have {int} cucumbers and {float} tomato"); | ||
assert_1.default.strictEqual(generatedExpression.parameterNames[0], "int"); | ||
assert_1.default.strictEqual(generatedExpression.parameterTypes[1].name, "float"); | ||
assert_1.default.strictEqual(generatedExpression.source, 'I have {int} cucumbers and {float} tomato'); | ||
assert_1.default.strictEqual(generatedExpression.parameterNames[0], 'int'); | ||
assert_1.default.strictEqual(generatedExpression.parameterTypes[1].name, 'float'); | ||
}); | ||
it("generates expression for no args", function () { | ||
assertExpression("hello", [], "hello"); | ||
it('generates expression for no args', function () { | ||
assertExpression('hello', [], 'hello'); | ||
}); | ||
it("generates expression with escaped left parenthesis", function () { | ||
assertExpression("\\(iii)", [], "(iii)"); | ||
it('generates expression with escaped left parenthesis', function () { | ||
assertExpression('\\(iii)', [], '(iii)'); | ||
}); | ||
it("generates expression with escaped left curly brace", function () { | ||
assertExpression("\\{iii}", [], "{iii}"); | ||
it('generates expression with escaped left curly brace', function () { | ||
assertExpression('\\{iii}', [], '{iii}'); | ||
}); | ||
it("generates expression with escaped slashes", function () { | ||
assertExpression("The {int}\\/{int}\\/{int} hey", ["int", "int2", "int3"], "The 1814/05/17 hey"); | ||
it('generates expression with escaped slashes', function () { | ||
assertExpression('The {int}\\/{int}\\/{int} hey', ['int', 'int2', 'int3'], 'The 1814/05/17 hey'); | ||
}); | ||
it("generates expression for int float arg", function () { | ||
assertExpression("I have {int} cukes and {float} euro", ["int", "float"], "I have 2 cukes and 1.5 euro"); | ||
it('generates expression for int float arg', function () { | ||
assertExpression('I have {int} cukes and {float} euro', ['int', 'float'], 'I have 2 cukes and 1.5 euro'); | ||
}); | ||
it("generates expression for strings", function () { | ||
assertExpression("I like {string} and {string}", ["string", "string2"], "I like \"bangers\" and 'mash'"); | ||
it('generates expression for strings', function () { | ||
assertExpression('I like {string} and {string}', ['string', 'string2'], 'I like "bangers" and \'mash\''); | ||
}); | ||
it("generates expression with % sign", function () { | ||
assertExpression("I am {int}%% foobar", ["int"], "I am 20%% foobar"); | ||
it('generates expression with % sign', function () { | ||
assertExpression('I am {int}%% foobar', ['int'], 'I am 20%% foobar'); | ||
}); | ||
it("generates expression for just int", function () { | ||
assertExpression("{int}", ["int"], "99999"); | ||
it('generates expression for just int', function () { | ||
assertExpression('{int}', ['int'], '99999'); | ||
}); | ||
it("numbers only second argument when builtin type is not reserved keyword", function () { | ||
assertExpression("I have {float} cukes and {float} euro", ["float", "float2"], "I have 2.5 cukes and 1.5 euro"); | ||
it('numbers only second argument when builtin type is not reserved keyword', function () { | ||
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", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("currency", /[A-Z]{3}/, Currency, function (s) { return new Currency(s); }, true, false)); | ||
assertExpression("I have a {currency} account", ["currency"], "I have a EUR account"); | ||
it('generates expression for custom type', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('currency', /[A-Z]{3}/, Currency, function (s) { return 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", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("currency", /cd/, Currency, function (s) { return new Currency(s); }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("date", /bc/, Date, function (s) { return new Date(s); }, true, false)); | ||
assertExpression("a{date}defg", ["date"], "abcdefg"); | ||
it('prefers leftmost match when there is overlap', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('currency', /cd/, Currency, function (s) { return new Currency(s); }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('date', /bc/, Date, function (s) { return 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", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("currency", /x/, null, function (s) { return new Currency(s); }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("date", /x/, null, function (s) { return new Date(s); }, true, false)); | ||
var generatedExpressions = generator.generateExpressions("I have x and x and another x"); | ||
it('generates all combinations of expressions when several parameter types match', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('currency', /x/, null, function (s) { return new Currency(s); }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('date', /x/, null, function (s) { return new Date(s); }, true, false)); | ||
var generatedExpressions = generator.generateExpressions('I have x and x and another x'); | ||
var expressions = generatedExpressions.map(function (e) { return e.source; }); | ||
assert_1.default.deepStrictEqual(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}" | ||
'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", function () { | ||
var expression = generator.generateExpressions("I have 2 cukes and 1.5 euro")[0]; | ||
it('exposes parameter type names in generated expression', function () { | ||
var expression = generator.generateExpressions('I have 2 cukes and 1.5 euro')[0]; | ||
var typeNames = expression.parameterTypes.map(function (parameter) { return parameter.name; }); | ||
assert_1.default.deepStrictEqual(typeNames, ["int", "float"]); | ||
assert_1.default.deepStrictEqual(typeNames, ['int', 'float']); | ||
}); | ||
it("matches parameter types with optional capture groups", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("optional-flight", /(1st flight)?/, null, function (s) { return s; }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("optional-hotel", /(1st hotel)?/, null, function (s) { return s; }, true, false)); | ||
var expression = generator.generateExpressions("I reach Stage4: 1st flight-1st hotel")[0]; | ||
it('matches parameter types with optional capture groups', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('optional-flight', /(1st flight)?/, null, function (s) { return s; }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('optional-hotel', /(1st hotel)?/, null, function (s) { return s; }, true, false)); | ||
var 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_1.default.strictEqual(expression.source, "I reach Stage{int}: {optional-flight}{int}st hotel"); | ||
assert_1.default.strictEqual(expression.source, 'I reach Stage{int}: {optional-flight}{int}st hotel'); | ||
}); | ||
it("generates at most 256 expressions", function () { | ||
it('generates at most 256 expressions', function () { | ||
for (var i = 0; i < 4; i++) { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("my-type-" + i, /[a-z]/, null, function (s) { return s; }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('my-type-' + i, /[a-z]/, null, function (s) { return s; }, true, false)); | ||
} | ||
// This would otherwise generate 4^11=419430 expressions and consume just shy of 1.5GB. | ||
var expressions = generator.generateExpressions("a simple step"); | ||
var expressions = generator.generateExpressions('a simple step'); | ||
assert_1.default.strictEqual(expressions.length, 256); | ||
}); | ||
it("prefers expression with longest non empty match", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("zero-or-more", /[a-z]*/, null, function (s) { return s; }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("exactly-one", /[a-z]/, null, function (s) { return s; }, true, false)); | ||
var expressions = generator.generateExpressions("a simple step"); | ||
it('prefers expression with longest non empty match', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('zero-or-more', /[a-z]*/, null, function (s) { return s; }, true, false)); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('exactly-one', /[a-z]/, null, function (s) { return s; }, true, false)); | ||
var expressions = generator.generateExpressions('a simple step'); | ||
assert_1.default.strictEqual(expressions.length, 2); | ||
assert_1.default.strictEqual(expressions[0].source, "{exactly-one} {zero-or-more} {zero-or-more}"); | ||
assert_1.default.strictEqual(expressions[1].source, "{zero-or-more} {zero-or-more} {zero-or-more}"); | ||
assert_1.default.strictEqual(expressions[0].source, '{exactly-one} {zero-or-more} {zero-or-more}'); | ||
assert_1.default.strictEqual(expressions[1].source, '{zero-or-more} {zero-or-more} {zero-or-more}'); | ||
}); | ||
}); | ||
//# sourceMappingURL=CucumberExpressionGeneratorTest.js.map |
@@ -9,21 +9,21 @@ "use strict"; | ||
var ParameterTypeRegistry_1 = __importDefault(require("../src/ParameterTypeRegistry")); | ||
describe("CucumberExpression", function () { | ||
describe("RegExp translation", function () { | ||
it("translates no arguments", function () { | ||
assertRegexp("I have 10 cukes in my belly now", /^I have 10 cukes in my belly now$/); | ||
describe('CucumberExpression', function () { | ||
describe('RegExp translation', function () { | ||
it('translates no arguments', function () { | ||
assertRegexp('I have 10 cukes in my belly now', /^I have 10 cukes in my belly now$/); | ||
}); | ||
it("translates alternation", function () { | ||
assertRegexp("I had/have a great/nice/charming friend", /^I (?:had|have) a (?:great|nice|charming) friend$/); | ||
it('translates alternation', function () { | ||
assertRegexp('I had/have a great/nice/charming friend', /^I (?:had|have) a (?:great|nice|charming) friend$/); | ||
}); | ||
it("translates alternation with non-alpha", function () { | ||
assertRegexp("I said Alpha1/Beta1", /^I said (?:Alpha1|Beta1)$/); | ||
it('translates alternation with non-alpha', function () { | ||
assertRegexp('I said Alpha1/Beta1', /^I said (?:Alpha1|Beta1)$/); | ||
}); | ||
it("translates parameters", function () { | ||
it('translates parameters', function () { | ||
assertRegexp("I have {float} cukes at {int} o'clock", /^I have (-?\d*\.?\d+) cukes at ((?:-?\d+)|(?:\d+)) o'clock$/); | ||
}); | ||
it("translates parenthesis to non-capturing optional capture group", function () { | ||
assertRegexp("I have many big(ish) cukes", /^I have many big(?:ish)? cukes$/); | ||
it('translates parenthesis to non-capturing optional capture group', function () { | ||
assertRegexp('I have many big(ish) cukes', /^I have many big(?:ish)? cukes$/); | ||
}); | ||
it("translates parenthesis with alpha unicode", function () { | ||
assertRegexp("Привет, Мир(ы)!", /^Привет, Мир(?:ы)?!$/); | ||
it('translates parenthesis with alpha unicode', function () { | ||
assertRegexp('Привет, Мир(ы)!', /^Привет, Мир(?:ы)?!$/); | ||
}); | ||
@@ -30,0 +30,0 @@ }); |
@@ -20,108 +20,108 @@ "use strict"; | ||
var ParameterType_1 = __importDefault(require("../src/ParameterType")); | ||
describe("CucumberExpression", function () { | ||
describe('CucumberExpression', function () { | ||
var e_1, _a; | ||
it("documents match arguments", function () { | ||
it('documents match arguments', function () { | ||
var parameterTypeRegistry = new ParameterTypeRegistry_1.default(); | ||
/// [capture-match-arguments] | ||
var expr = "I have {int} cuke(s)"; | ||
var expr = 'I have {int} cuke(s)'; | ||
var expression = new CucumberExpression_1.default(expr, parameterTypeRegistry); | ||
var args = expression.match("I have 7 cukes"); | ||
var args = expression.match('I have 7 cukes'); | ||
assert_1.default.strictEqual(7, args[0].getValue(null)); | ||
/// [capture-match-arguments] | ||
}); | ||
it("matches word", function () { | ||
assert_1.default.deepStrictEqual(match("three {word} mice", "three blind mice"), [ | ||
"blind" | ||
it('matches word', function () { | ||
assert_1.default.deepStrictEqual(match('three {word} mice', 'three blind mice'), [ | ||
'blind', | ||
]); | ||
}); | ||
it("matches double quoted string", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", 'three "blind" mice'), [ | ||
"blind" | ||
it('matches double quoted string', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', 'three "blind" mice'), [ | ||
'blind', | ||
]); | ||
}); | ||
it("matches multiple double quoted strings", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} and {string} mice", 'three "blind" and "crippled" mice'), ["blind", "crippled"]); | ||
it('matches multiple double quoted strings', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} and {string} mice', 'three "blind" and "crippled" mice'), ['blind', 'crippled']); | ||
}); | ||
it("matches single quoted string", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three 'blind' mice"), [ | ||
"blind" | ||
it('matches single quoted string', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', "three 'blind' mice"), [ | ||
'blind', | ||
]); | ||
}); | ||
it("matches multiple single quoted strings", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} and {string} mice", "three 'blind' and 'crippled' mice"), ["blind", "crippled"]); | ||
it('matches multiple single quoted strings', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} and {string} mice', "three 'blind' and 'crippled' mice"), ['blind', 'crippled']); | ||
}); | ||
it("does not match misquoted string", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three \"blind' mice"), null); | ||
it('does not match misquoted string', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', 'three "blind\' mice'), null); | ||
}); | ||
it("matches single quoted string with double quotes", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three '\"blind\"' mice"), ['"blind"']); | ||
it('matches single quoted string with double quotes', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', 'three \'"blind"\' mice'), ['"blind"']); | ||
}); | ||
it("matches double quoted string with single quotes", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three \"'blind'\" mice"), ["'blind'"]); | ||
it('matches double quoted string with single quotes', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', 'three "\'blind\'" mice'), ["'blind'"]); | ||
}); | ||
it("matches double quoted string with escaped double quote", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", 'three "bl\\"nd" mice'), ['bl"nd']); | ||
it('matches double quoted string with escaped double quote', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', 'three "bl\\"nd" mice'), ['bl"nd']); | ||
}); | ||
it("matches single quoted string with escaped single quote", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three 'bl\\'nd' mice"), ["bl'nd"]); | ||
it('matches single quoted string with escaped single quote', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', "three 'bl\\'nd' mice"), ["bl'nd"]); | ||
}); | ||
it("matches single quoted string with escaped single quote", function () { | ||
assert_1.default.deepStrictEqual(match("three {string} mice", "three 'bl\\'nd' mice"), ["bl'nd"]); | ||
it('matches single quoted string with escaped single quote', function () { | ||
assert_1.default.deepStrictEqual(match('three {string} mice', "three 'bl\\'nd' mice"), ["bl'nd"]); | ||
}); | ||
it("matches escaped parenthesis", function () { | ||
assert_1.default.deepStrictEqual(match("three \\(exceptionally) {string} mice", 'three (exceptionally) "blind" mice'), ["blind"]); | ||
it('matches escaped parenthesis', function () { | ||
assert_1.default.deepStrictEqual(match('three \\(exceptionally) {string} mice', 'three (exceptionally) "blind" mice'), ['blind']); | ||
}); | ||
it("matches escaped slash", function () { | ||
assert_1.default.deepStrictEqual(match("12\\/2020", "12/2020"), []); | ||
it('matches escaped slash', function () { | ||
assert_1.default.deepStrictEqual(match('12\\/2020', '12/2020'), []); | ||
}); | ||
it("matches int", function () { | ||
assert_1.default.deepStrictEqual(match("{int}", "22"), [22]); | ||
it('matches int', function () { | ||
assert_1.default.deepStrictEqual(match('{int}', '22'), [22]); | ||
}); | ||
it("doesn't match float as int", function () { | ||
assert_1.default.deepStrictEqual(match("{int}", "1.22"), null); | ||
assert_1.default.deepStrictEqual(match('{int}', '1.22'), null); | ||
}); | ||
it("matches float", function () { | ||
assert_1.default.deepStrictEqual(match("{float}", "0.22"), [0.22]); | ||
assert_1.default.deepStrictEqual(match("{float}", ".22"), [0.22]); | ||
it('matches float', function () { | ||
assert_1.default.deepStrictEqual(match('{float}', '0.22'), [0.22]); | ||
assert_1.default.deepStrictEqual(match('{float}', '.22'), [0.22]); | ||
}); | ||
it("matches anonymous", function () { | ||
assert_1.default.deepStrictEqual(match("{}", "0.22"), ["0.22"]); | ||
it('matches anonymous', function () { | ||
assert_1.default.deepStrictEqual(match('{}', '0.22'), ['0.22']); | ||
}); | ||
it("throws unknown parameter type", function () { | ||
it('throws unknown parameter type', function () { | ||
try { | ||
match("{unknown}", "something"); | ||
match('{unknown}', 'something'); | ||
assert_1.default.fail(); | ||
} | ||
catch (expected) { | ||
assert_1.default.strictEqual(expected.message, "Undefined parameter type {unknown}"); | ||
assert_1.default.strictEqual(expected.message, 'Undefined parameter type {unknown}'); | ||
} | ||
}); | ||
it("does not allow optional parameter types", function () { | ||
it('does not allow optional parameter types', function () { | ||
try { | ||
match("({int})", "3"); | ||
match('({int})', '3'); | ||
assert_1.default.fail(); | ||
} | ||
catch (expected) { | ||
assert_1.default.strictEqual(expected.message, "Parameter types cannot be optional: ({int})"); | ||
assert_1.default.strictEqual(expected.message, 'Parameter types cannot be optional: ({int})'); | ||
} | ||
}); | ||
it("allows escaped optional parameter types", function () { | ||
assert_1.default.deepStrictEqual(match("\\({int})", "(3)"), [3]); | ||
it('allows escaped optional parameter types', function () { | ||
assert_1.default.deepStrictEqual(match('\\({int})', '(3)'), [3]); | ||
}); | ||
it("does not allow text/parameter type alternation", function () { | ||
it('does not allow text/parameter type alternation', function () { | ||
try { | ||
match("x/{int}", "3"); | ||
match('x/{int}', '3'); | ||
assert_1.default.fail(); | ||
} | ||
catch (expected) { | ||
assert_1.default.strictEqual(expected.message, "Parameter types cannot be alternative: x/{int}"); | ||
assert_1.default.strictEqual(expected.message, 'Parameter types cannot be alternative: x/{int}'); | ||
} | ||
}); | ||
it("does not allow parameter type/text alternation", function () { | ||
it('does not allow parameter type/text alternation', function () { | ||
try { | ||
match("{int}/x", "3"); | ||
match('{int}/x', '3'); | ||
assert_1.default.fail(); | ||
} | ||
catch (expected) { | ||
assert_1.default.strictEqual(expected.message, "Parameter types cannot be alternative: {int}/x"); | ||
assert_1.default.strictEqual(expected.message, 'Parameter types cannot be alternative: {int}/x'); | ||
} | ||
@@ -132,3 +132,3 @@ }); | ||
try { | ||
match("{" + c + "string}", "something"); | ||
match("{" + c + "string}", 'something'); | ||
assert_1.default.fail(); | ||
@@ -142,3 +142,3 @@ } | ||
try { | ||
for (var _b = __values("[]()$.|?*+".split("")), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
for (var _b = __values('[]()$.|?*+'.split('')), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var c = _c.value; | ||
@@ -155,23 +155,24 @@ _loop_1(c); | ||
} | ||
it("exposes source", function () { | ||
var expr = "I have {int} cuke(s)"; | ||
it('exposes source', function () { | ||
var expr = 'I have {int} cuke(s)'; | ||
assert_1.default.strictEqual(new CucumberExpression_1.default(expr, new ParameterTypeRegistry_1.default()).source, expr); | ||
}); | ||
// JavaScript-specific | ||
it("delegates transform to custom object", function () { | ||
it('delegates transform to custom object', function () { | ||
var parameterTypeRegistry = new ParameterTypeRegistry_1.default(); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("widget", /\w+/, null, function (s) { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('widget', /\w+/, null, function (s) { | ||
return this.createWidget(s); | ||
}, false, true)); | ||
var expression = new CucumberExpression_1.default("I have a {widget}", parameterTypeRegistry); | ||
var expression = new CucumberExpression_1.default('I have a {widget}', parameterTypeRegistry); | ||
var world = { | ||
createWidget: function (s) { | ||
return "widget:" + s; | ||
} | ||
}, | ||
}; | ||
var args = expression.match("I have a bolt"); | ||
assert_1.default.strictEqual(args[0].getValue(world), "widget:bolt"); | ||
assert_1.default.strictEqual(args[0].getValue(world), 'widget:bolt'); | ||
}); | ||
describe("escapes special characters", function () { | ||
["\\", "[", "]", "^", "$", ".", "|", "?", "*", "+"].forEach(function (character) { | ||
describe('escapes special characters', function () { | ||
; | ||
['\\', '[', ']', '^', '$', '.', '|', '?', '*', '+'].forEach(function (character) { | ||
it("escapes " + character, function () { | ||
@@ -178,0 +179,0 @@ var expr = "I have {int} cuke(s) and " + character; |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -61,3 +61,3 @@ return new (P || (P = Promise))(function (resolve, reject) { | ||
}()); | ||
describe("Custom parameter type", function () { | ||
describe('Custom parameter type', function () { | ||
var parameterTypeRegistry; | ||
@@ -68,3 +68,3 @@ beforeEach(function () { | ||
/// [add-color-parameter-type] | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("color", // name | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('color', // name | ||
/red|blue|yellow/, // regexp | ||
@@ -80,12 +80,12 @@ Color, // type | ||
}); | ||
describe("CucumberExpression", function () { | ||
it("throws exception for illegal character in parameter name", function () { | ||
assert_throws_1.default(function () { return new ParameterType_1.default("[string]", /.*/, String, function (s) { return s; }, false, true); }, "Illegal character '[' in parameter name {[string]}"); | ||
describe('CucumberExpression', function () { | ||
it('throws exception for illegal character in parameter name', function () { | ||
assert_throws_1.default(function () { return new ParameterType_1.default('[string]', /.*/, String, function (s) { return s; }, false, true); }, "Illegal character '[' in parameter name {[string]}"); | ||
}); | ||
it("matches parameters with custom parameter type", function () { | ||
var expression = new CucumberExpression_1.default("I have a {color} ball", parameterTypeRegistry); | ||
var value = expression.match("I have a red ball")[0].getValue(null); | ||
assert_1.default.strictEqual(value.name, "red"); | ||
it('matches parameters with custom parameter type', function () { | ||
var expression = new CucumberExpression_1.default('I have a {color} ball', parameterTypeRegistry); | ||
var value = expression.match('I have a red ball')[0].getValue(null); | ||
assert_1.default.strictEqual(value.name, 'red'); | ||
}); | ||
it("matches parameters with multiple capture groups", function () { | ||
it('matches parameters with multiple capture groups', function () { | ||
var Coordinate = /** @class */ (function () { | ||
@@ -99,7 +99,7 @@ function Coordinate(x, y, z) { | ||
}()); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("coordinate", /(\d+),\s*(\d+),\s*(\d+)/, Coordinate, function (x, y, z) { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('coordinate', /(\d+),\s*(\d+),\s*(\d+)/, Coordinate, function (x, y, z) { | ||
return new Coordinate(Number(x), Number(y), Number(z)); | ||
}, true, true)); | ||
var expression = new CucumberExpression_1.default("A {int} thick line from {coordinate} to {coordinate}", parameterTypeRegistry); | ||
var args = expression.match("A 5 thick line from 10,20,30 to 40,50,60"); | ||
var expression = new CucumberExpression_1.default('A {int} thick line from {coordinate} to {coordinate}', parameterTypeRegistry); | ||
var args = expression.match('A 5 thick line from 10,20,30 to 40,50,60'); | ||
var thick = args[0].getValue(null); | ||
@@ -116,46 +116,44 @@ assert_1.default.strictEqual(thick, 5); | ||
}); | ||
it("matches parameters with custom parameter type using optional capture group", function () { | ||
it('matches parameters with custom parameter type using optional capture group', function () { | ||
parameterTypeRegistry = new ParameterTypeRegistry_1.default(); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("color", [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/], Color, function (s) { return new Color(s); }, false, true)); | ||
var expression = new CucumberExpression_1.default("I have a {color} ball", parameterTypeRegistry); | ||
var value = expression | ||
.match("I have a dark red ball")[0] | ||
.getValue(null); | ||
assert_1.default.strictEqual(value.name, "dark red"); | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('color', [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/], Color, function (s) { return new Color(s); }, false, true)); | ||
var expression = new CucumberExpression_1.default('I have a {color} ball', parameterTypeRegistry); | ||
var value = expression.match('I have a dark red ball')[0].getValue(null); | ||
assert_1.default.strictEqual(value.name, 'dark red'); | ||
}); | ||
it("defers transformation until queried from argument", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("throwing", /bad/, null, function (s) { | ||
it('defers transformation until queried from argument', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('throwing', /bad/, null, function (s) { | ||
throw new Error("Can't transform [" + s + "]"); | ||
}, false, true)); | ||
var expression = new CucumberExpression_1.default("I have a {throwing} parameter", parameterTypeRegistry); | ||
var args = expression.match("I have a bad parameter"); | ||
var expression = new CucumberExpression_1.default('I have a {throwing} parameter', parameterTypeRegistry); | ||
var args = expression.match('I have a bad parameter'); | ||
assert_throws_1.default(function () { return args[0].getValue(null); }, "Can't transform [bad]"); | ||
}); | ||
describe("conflicting parameter type", function () { | ||
it("is detected for type name", function () { | ||
describe('conflicting parameter type', function () { | ||
it('is detected for type name', function () { | ||
assert_throws_1.default(function () { | ||
return parameterTypeRegistry.defineParameterType(new ParameterType_1.default("color", /.*/, CssColor, function (s) { return new CssColor(s); }, false, true)); | ||
}, "There is already a parameter type with name color"); | ||
return parameterTypeRegistry.defineParameterType(new ParameterType_1.default('color', /.*/, CssColor, function (s) { return new CssColor(s); }, false, true)); | ||
}, 'There is already a parameter type with name color'); | ||
}); | ||
it("is not detected for type", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("whatever", /.*/, Color, function (s) { return new Color(s); }, false, false)); | ||
it('is not detected for type', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('whatever', /.*/, Color, function (s) { return new Color(s); }, false, false)); | ||
}); | ||
it("is not detected for regexp", function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("css-color", /red|blue|yellow/, CssColor, function (s) { return new CssColor(s); }, true, false)); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default("I have a {css-color} ball", parameterTypeRegistry) | ||
.match("I have a blue ball")[0] | ||
it('is not detected for regexp', function () { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('css-color', /red|blue|yellow/, CssColor, function (s) { return new CssColor(s); }, true, false)); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default('I have a {css-color} ball', parameterTypeRegistry) | ||
.match('I have a blue ball')[0] | ||
.getValue(null).constructor, CssColor); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default("I have a {css-color} ball", parameterTypeRegistry) | ||
.match("I have a blue ball")[0] | ||
.getValue(null).name, "blue"); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default("I have a {color} ball", parameterTypeRegistry) | ||
.match("I have a blue ball")[0] | ||
assert_1.default.strictEqual(new CucumberExpression_1.default('I have a {css-color} ball', parameterTypeRegistry) | ||
.match('I have a blue ball')[0] | ||
.getValue(null).name, 'blue'); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default('I have a {color} ball', parameterTypeRegistry) | ||
.match('I have a blue ball')[0] | ||
.getValue(null).constructor, Color); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default("I have a {color} ball", parameterTypeRegistry) | ||
.match("I have a blue ball")[0] | ||
.getValue(null).name, "blue"); | ||
assert_1.default.strictEqual(new CucumberExpression_1.default('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", function () { return __awaiter(_this, void 0, void 0, function () { | ||
it('creates arguments using async transform', function () { return __awaiter(_this, void 0, void 0, function () { | ||
var expression, args, value; | ||
@@ -168,7 +166,7 @@ var _this = this; | ||
/// [add-async-parameter-type] | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default("asyncColor", /red|blue|yellow/, Color, function (s) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { | ||
parameterTypeRegistry.defineParameterType(new ParameterType_1.default('asyncColor', /red|blue|yellow/, Color, function (s) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { | ||
return [2 /*return*/, new Color(s)]; | ||
}); }); }, false, true)); | ||
expression = new CucumberExpression_1.default("I have a {asyncColor} ball", parameterTypeRegistry); | ||
return [4 /*yield*/, expression.match("I have a red ball")]; | ||
expression = new CucumberExpression_1.default('I have a {asyncColor} ball', parameterTypeRegistry); | ||
return [4 /*yield*/, expression.match('I have a red ball')]; | ||
case 1: | ||
@@ -179,3 +177,3 @@ args = _a.sent(); | ||
value = _a.sent(); | ||
assert_1.default.strictEqual(value.name, "red"); | ||
assert_1.default.strictEqual(value.name, 'red'); | ||
return [2 /*return*/]; | ||
@@ -186,8 +184,8 @@ } | ||
}); | ||
describe("RegularExpression", function () { | ||
it("matches arguments with custom parameter type", function () { | ||
describe('RegularExpression', function () { | ||
it('matches arguments with custom parameter type', function () { | ||
var expression = new RegularExpression_1.default(/I have a (red|blue|yellow) ball/, parameterTypeRegistry); | ||
var value = expression.match("I have a red ball")[0].getValue(null); | ||
var value = expression.match('I have a red ball')[0].getValue(null); | ||
assert_1.default.strictEqual(value.constructor, Color); | ||
assert_1.default.strictEqual(value.name, "red"); | ||
assert_1.default.strictEqual(value.name, 'red'); | ||
}); | ||
@@ -194,0 +192,0 @@ }); |
@@ -37,3 +37,3 @@ "use strict"; | ||
var ParameterTypeRegistry_1 = __importDefault(require("../src/ParameterTypeRegistry")); | ||
describe("examples.txt", function () { | ||
describe('examples.txt', function () { | ||
var e_1, _a; | ||
@@ -51,3 +51,3 @@ var match = function (expressionText, text) { | ||
}; | ||
var examples = fs_1.default.readFileSync("examples.txt", "utf-8"); | ||
var examples = fs_1.default.readFileSync('examples.txt', 'utf-8'); | ||
var chunks = examples.split(/^---/m); | ||
@@ -54,0 +54,0 @@ var _loop_1 = function (chunk) { |
@@ -28,3 +28,3 @@ "use strict"; | ||
var CAPITALISED_WORD = /[A-Z]+\w+/; | ||
describe("ParameterTypeRegistry", function () { | ||
describe('ParameterTypeRegistry', function () { | ||
var registry; | ||
@@ -34,8 +34,8 @@ beforeEach(function () { | ||
}); | ||
it("does not allow more than one preferential parameter type for each regexp", function () { | ||
registry.defineParameterType(new ParameterType_1.default("name", CAPITALISED_WORD, Name, function (s) { return new Name(s); }, true, true)); | ||
registry.defineParameterType(new ParameterType_1.default("person", CAPITALISED_WORD, Person, function (s) { return new Person(s); }, true, false)); | ||
it('does not allow more than one preferential parameter type for each regexp', function () { | ||
registry.defineParameterType(new ParameterType_1.default('name', CAPITALISED_WORD, Name, function (s) { return new Name(s); }, true, true)); | ||
registry.defineParameterType(new ParameterType_1.default('person', CAPITALISED_WORD, Person, function (s) { return new Person(s); }, true, false)); | ||
try { | ||
registry.defineParameterType(new ParameterType_1.default("place", CAPITALISED_WORD, Place, function (s) { return new Place(s); }, true, true)); | ||
throw new Error("Should have failed"); | ||
registry.defineParameterType(new ParameterType_1.default('place', CAPITALISED_WORD, Place, function (s) { return new Place(s); }, true, true)); | ||
throw new Error('Should have failed'); | ||
} | ||
@@ -46,12 +46,12 @@ catch (err) { | ||
}); | ||
it("looks up preferential parameter type by regexp", function () { | ||
var name = new ParameterType_1.default("name", /[A-Z]+\w+/, null, function (s) { return new Name(s); }, true, false); | ||
var person = new ParameterType_1.default("person", /[A-Z]+\w+/, null, function (s) { return new Person(s); }, true, true); | ||
var place = new ParameterType_1.default("place", /[A-Z]+\w+/, null, function (s) { return new Place(s); }, true, false); | ||
it('looks up preferential parameter type by regexp', function () { | ||
var name = new ParameterType_1.default('name', /[A-Z]+\w+/, null, function (s) { return new Name(s); }, true, false); | ||
var person = new ParameterType_1.default('person', /[A-Z]+\w+/, null, function (s) { return new Person(s); }, true, true); | ||
var place = new ParameterType_1.default('place', /[A-Z]+\w+/, null, function (s) { return new Place(s); }, true, false); | ||
registry.defineParameterType(name); | ||
registry.defineParameterType(person); | ||
registry.defineParameterType(place); | ||
assert_1.default.strictEqual(registry.lookupByRegexp("[A-Z]+\\w+", /([A-Z]+\w+) and ([A-Z]+\w+)/, "Lisa and Bob"), person); | ||
assert_1.default.strictEqual(registry.lookupByRegexp('[A-Z]+\\w+', /([A-Z]+\w+) and ([A-Z]+\w+)/, 'Lisa and Bob'), person); | ||
}); | ||
}); | ||
//# sourceMappingURL=ParameterTypeRegistryTest.js.map |
@@ -8,6 +8,6 @@ "use strict"; | ||
var ParameterType_1 = __importDefault(require("../src/ParameterType")); | ||
describe("ParameterType", function () { | ||
it("does not allow ignore flag on regexp", function () { | ||
describe('ParameterType', function () { | ||
it('does not allow ignore flag on regexp', function () { | ||
assert_throws_1.default(function () { | ||
return new ParameterType_1.default("case-insensitive", /[a-z]+/i, String, function (s) { return s; }, true, true); | ||
return new ParameterType_1.default('case-insensitive', /[a-z]+/i, String, function (s) { return s; }, true, true); | ||
}, "ParameterType Regexps can't use flag 'i'"); | ||
@@ -14,0 +14,0 @@ }); |
@@ -9,4 +9,4 @@ "use strict"; | ||
var ParameterTypeRegistry_1 = __importDefault(require("../src/ParameterTypeRegistry")); | ||
describe("RegularExpression", function () { | ||
it("documents match arguments", function () { | ||
describe('RegularExpression', function () { | ||
it('documents match arguments', function () { | ||
var parameterRegistry = new ParameterTypeRegistry_1.default(); | ||
@@ -16,52 +16,52 @@ /// [capture-match-arguments] | ||
var expression = new RegularExpression_1.default(expr, parameterRegistry); | ||
var args = expression.match("I have 7 cukes in my belly now"); | ||
var args = expression.match('I have 7 cukes in my belly now'); | ||
assert_1.default.strictEqual(7, args[0].getValue(null)); | ||
assert_1.default.strictEqual("belly", args[1].getValue(null)); | ||
assert_1.default.strictEqual('belly', args[1].getValue(null)); | ||
/// [capture-match-arguments] | ||
}); | ||
it("does no transform by default", function () { | ||
assert_1.default.deepStrictEqual(match(/(\d\d)/, "22")[0], "22"); | ||
it('does no transform by default', function () { | ||
assert_1.default.deepStrictEqual(match(/(\d\d)/, '22')[0], '22'); | ||
}); | ||
it("does not transform anonymous", function () { | ||
assert_1.default.deepStrictEqual(match(/(.*)/, "22")[0], "22"); | ||
it('does not transform anonymous', function () { | ||
assert_1.default.deepStrictEqual(match(/(.*)/, '22')[0], '22'); | ||
}); | ||
it("transforms negative int", function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d+)/, "-22")[0], -22); | ||
it('transforms negative int', function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d+)/, '-22')[0], -22); | ||
}); | ||
it("transforms positive int", function () { | ||
assert_1.default.deepStrictEqual(match(/(\d+)/, "22")[0], 22); | ||
it('transforms positive int', function () { | ||
assert_1.default.deepStrictEqual(match(/(\d+)/, '22')[0], 22); | ||
}); | ||
it("transforms float without integer part", function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d*\.?\d+)/, ".22")[0], 0.22); | ||
it('transforms float without integer part', function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d*\.?\d+)/, '.22')[0], 0.22); | ||
}); | ||
it("transforms float with sign", function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d*\.?\d+)/, "-1.22")[0], -1.22); | ||
it('transforms float with sign', function () { | ||
assert_1.default.deepStrictEqual(match(/(-?\d*\.?\d+)/, '-1.22')[0], -1.22); | ||
}); | ||
it("returns null when there is no match", function () { | ||
assert_1.default.strictEqual(match(/hello/, "world"), null); | ||
it('returns null when there is no match', function () { | ||
assert_1.default.strictEqual(match(/hello/, 'world'), null); | ||
}); | ||
it("matches nested capture group without match", function () { | ||
assert_1.default.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, "a user"), [ | ||
null | ||
it('matches nested capture group without match', function () { | ||
assert_1.default.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, 'a user'), [ | ||
null, | ||
]); | ||
}); | ||
it("matches nested capture group with match", function () { | ||
assert_1.default.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, 'a user named "Charlie"'), ["Charlie"]); | ||
it('matches nested capture group with match', function () { | ||
assert_1.default.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, 'a user named "Charlie"'), ['Charlie']); | ||
}); | ||
it("matches capture group nested in optional one", function () { | ||
it('matches capture group nested in optional one', function () { | ||
var regexp = /^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/; | ||
assert_1.default.deepStrictEqual(match(regexp, "a purchase"), [null, null]); | ||
assert_1.default.deepStrictEqual(match(regexp, "a purchase for $33"), [null, 33]); | ||
assert_1.default.deepStrictEqual(match(regexp, "a pre buyer fee model purchase"), [ | ||
"pre buyer fee model ", | ||
null | ||
assert_1.default.deepStrictEqual(match(regexp, 'a purchase'), [null, null]); | ||
assert_1.default.deepStrictEqual(match(regexp, 'a purchase for $33'), [null, 33]); | ||
assert_1.default.deepStrictEqual(match(regexp, 'a pre buyer fee model purchase'), [ | ||
'pre buyer fee model ', | ||
null, | ||
]); | ||
}); | ||
it("ignores non capturing groups", function () { | ||
assert_1.default.deepStrictEqual(match(/(\S+) ?(can|cannot)? (?:delete|cancel) the (\d+)(?:st|nd|rd|th) (attachment|slide) ?(?:upload)?/, "I can cancel the 1st slide upload"), ["I", "can", 1, "slide"]); | ||
it('ignores non capturing groups', function () { | ||
assert_1.default.deepStrictEqual(match(/(\S+) ?(can|cannot)? (?:delete|cancel) the (\d+)(?:st|nd|rd|th) (attachment|slide) ?(?:upload)?/, 'I can cancel the 1st slide upload'), ['I', 'can', 1, 'slide']); | ||
}); | ||
it("works with escaped parenthesis", function () { | ||
assert_1.default.deepStrictEqual(match(/Across the line\(s\)/, "Across the line(s)"), []); | ||
it('works with escaped parenthesis', function () { | ||
assert_1.default.deepStrictEqual(match(/Across the line\(s\)/, 'Across the line(s)'), []); | ||
}); | ||
it("exposes regexp and source", function () { | ||
it('exposes regexp and source', function () { | ||
var regexp = /I have (\d+) cukes? in my (.+) now/; | ||
@@ -72,6 +72,6 @@ var expression = new RegularExpression_1.default(regexp, new ParameterTypeRegistry_1.default()); | ||
}); | ||
it("does not take consider parenthesis in character class as group", function () { | ||
it('does not take consider parenthesis in character class as group', function () { | ||
var expression = new RegularExpression_1.default(/^drawings: ([A-Z_, ()]+)$/, new ParameterTypeRegistry_1.default()); | ||
var args = expression.match("drawings: ONE, TWO(ABC)"); | ||
assert_1.default.strictEqual(args[0].getValue(this), "ONE, TWO(ABC)"); | ||
var args = expression.match('drawings: ONE, TWO(ABC)'); | ||
assert_1.default.strictEqual(args[0].getValue(this), 'ONE, TWO(ABC)'); | ||
}); | ||
@@ -78,0 +78,0 @@ }); |
@@ -8,55 +8,55 @@ "use strict"; | ||
var TreeRegexp_1 = __importDefault(require("../src/TreeRegexp")); | ||
describe("TreeRegexp", function () { | ||
it("exposes group source", function () { | ||
describe('TreeRegexp', function () { | ||
it('exposes group source', function () { | ||
var tr = new TreeRegexp_1.default(/(a(?:b)?)(c)/); | ||
assert_1.default.deepStrictEqual(tr.groupBuilder.children.map(function (gb) { return gb.source; }), [ | ||
"a(?:b)?", | ||
"c" | ||
'a(?:b)?', | ||
'c', | ||
]); | ||
}); | ||
it("builds tree", function () { | ||
it('builds tree', function () { | ||
var tr = new TreeRegexp_1.default(/(a(?:b)?)(c)/); | ||
var group = tr.match("ac"); | ||
assert_1.default.strictEqual(group.value, "ac"); | ||
assert_1.default.strictEqual(group.children[0].value, "a"); | ||
var group = tr.match('ac'); | ||
assert_1.default.strictEqual(group.value, 'ac'); | ||
assert_1.default.strictEqual(group.children[0].value, 'a'); | ||
assert_1.default.deepStrictEqual(group.children[0].children, []); | ||
assert_1.default.strictEqual(group.children[1].value, "c"); | ||
assert_1.default.strictEqual(group.children[1].value, 'c'); | ||
}); | ||
it("ignores non-capturing groups", function () { | ||
it('ignores non-capturing groups', function () { | ||
var tr = new TreeRegexp_1.default(/(a(?:b)?)(c)/); | ||
var group = tr.match("ac"); | ||
assert_1.default.strictEqual(group.value, "ac"); | ||
assert_1.default.strictEqual(group.children[0].value, "a"); | ||
var group = tr.match('ac'); | ||
assert_1.default.strictEqual(group.value, 'ac'); | ||
assert_1.default.strictEqual(group.children[0].value, 'a'); | ||
assert_1.default.deepStrictEqual(group.children[0].children, []); | ||
assert_1.default.strictEqual(group.children[1].value, "c"); | ||
assert_1.default.strictEqual(group.children[1].value, 'c'); | ||
}); | ||
it("matches optional group", function () { | ||
it('matches optional group', function () { | ||
var tr = new TreeRegexp_1.default(/^Something( with an optional argument)?/); | ||
var group = tr.match("Something"); | ||
var group = tr.match('Something'); | ||
assert_1.default.strictEqual(group.children[0].value, null); | ||
}); | ||
it("matches nested groups", function () { | ||
it('matches nested groups', function () { | ||
var tr = new TreeRegexp_1.default(/^A (\d+) thick line from ((\d+),\s*(\d+),\s*(\d+)) to ((\d+),\s*(\d+),\s*(\d+))/); | ||
var group = tr.match("A 5 thick line from 10,20,30 to 40,50,60"); | ||
assert_1.default.strictEqual(group.children[0].value, "5"); | ||
assert_1.default.strictEqual(group.children[1].value, "10,20,30"); | ||
assert_1.default.strictEqual(group.children[1].children[0].value, "10"); | ||
assert_1.default.strictEqual(group.children[1].children[1].value, "20"); | ||
assert_1.default.strictEqual(group.children[1].children[2].value, "30"); | ||
assert_1.default.strictEqual(group.children[2].value, "40,50,60"); | ||
assert_1.default.strictEqual(group.children[2].children[0].value, "40"); | ||
assert_1.default.strictEqual(group.children[2].children[1].value, "50"); | ||
assert_1.default.strictEqual(group.children[2].children[2].value, "60"); | ||
var group = tr.match('A 5 thick line from 10,20,30 to 40,50,60'); | ||
assert_1.default.strictEqual(group.children[0].value, '5'); | ||
assert_1.default.strictEqual(group.children[1].value, '10,20,30'); | ||
assert_1.default.strictEqual(group.children[1].children[0].value, '10'); | ||
assert_1.default.strictEqual(group.children[1].children[1].value, '20'); | ||
assert_1.default.strictEqual(group.children[1].children[2].value, '30'); | ||
assert_1.default.strictEqual(group.children[2].value, '40,50,60'); | ||
assert_1.default.strictEqual(group.children[2].children[0].value, '40'); | ||
assert_1.default.strictEqual(group.children[2].children[1].value, '50'); | ||
assert_1.default.strictEqual(group.children[2].children[2].value, '60'); | ||
}); | ||
it("detects multiple non capturing groups", function () { | ||
it('detects multiple non capturing groups', function () { | ||
var tr = new TreeRegexp_1.default(/(?:a)(:b)(\?c)(d)/); | ||
var group = tr.match("a:b?cd"); | ||
var group = tr.match('a:b?cd'); | ||
assert_1.default.strictEqual(group.children.length, 3); | ||
}); | ||
it("works with escaped backslash", function () { | ||
it('works with escaped backslash', function () { | ||
var tr = new TreeRegexp_1.default(/foo\\(bar|baz)/); | ||
var group = tr.match("foo\\bar"); | ||
var group = tr.match('foo\\bar'); | ||
assert_1.default.strictEqual(group.children.length, 1); | ||
}); | ||
it("works with escaped slash", function () { | ||
it('works with escaped slash', function () { | ||
var tr = new TreeRegexp_1.default(/^I go to '\/(.+)'$/); | ||
@@ -66,27 +66,27 @@ var group = tr.match("I go to '/hello'"); | ||
}); | ||
it("works with digit and word", function () { | ||
it('works with digit and word', function () { | ||
var tr = new TreeRegexp_1.default(/^(\d) (\w+)$/); | ||
var group = tr.match("2 you"); | ||
var group = tr.match('2 you'); | ||
assert_1.default.strictEqual(group.children.length, 2); | ||
}); | ||
it("captures non capturing groups with capturing groups inside", function () { | ||
it('captures non capturing groups with capturing groups inside', function () { | ||
var tr = new TreeRegexp_1.default('the stdout(?: from "(.*?)")?'); | ||
var group = tr.match("the stdout"); | ||
assert_1.default.strictEqual(group.value, "the stdout"); | ||
var group = tr.match('the stdout'); | ||
assert_1.default.strictEqual(group.value, 'the stdout'); | ||
assert_1.default.strictEqual(group.children[0].value, null); | ||
assert_1.default.strictEqual(group.children.length, 1); | ||
}); | ||
it("works with flags", function () { | ||
it('works with flags', function () { | ||
var tr = new TreeRegexp_1.default(/HELLO/i); | ||
var group = tr.match("hello"); | ||
assert_1.default.strictEqual(group.value, "hello"); | ||
var group = tr.match('hello'); | ||
assert_1.default.strictEqual(group.value, 'hello'); | ||
}); | ||
it("does not consider parenthesis in character class as group", function () { | ||
it('does not consider parenthesis in character class as group', function () { | ||
var tr = new TreeRegexp_1.default(/^drawings: ([A-Z, ()]+)$/); | ||
var group = tr.match("drawings: ONE(TWO)"); | ||
assert_1.default.strictEqual(group.value, "drawings: ONE(TWO)"); | ||
var group = tr.match('drawings: ONE(TWO)'); | ||
assert_1.default.strictEqual(group.value, 'drawings: ONE(TWO)'); | ||
assert_1.default.strictEqual(group.children.length, 1); | ||
assert_1.default.strictEqual(group.children[0].value, "ONE(TWO)"); | ||
assert_1.default.strictEqual(group.children[0].value, 'ONE(TWO)'); | ||
}); | ||
}); | ||
//# sourceMappingURL=TreeRegexpTest.js.map |
{ | ||
"name": "cucumber-expressions", | ||
"version": "7.0.1", | ||
"version": "7.0.2", | ||
"description": "Cucumber Expressions - a simpler alternative to Regular Expressions", | ||
@@ -5,0 +5,0 @@ "main": "dist/src/index.js", |
@@ -1,5 +0,5 @@ | ||
import TreeRegexp from "./TreeRegexp"; | ||
import ParameterType from "./ParameterType"; | ||
import Group from "./Group"; | ||
import { CucumberExpressionError } from "./Errors"; | ||
import TreeRegexp from './TreeRegexp' | ||
import ParameterType from './ParameterType' | ||
import Group from './Group' | ||
import { CucumberExpressionError } from './Errors' | ||
@@ -12,8 +12,8 @@ export default class Argument<T> { | ||
): Array<Argument<any>> { | ||
const group = treeRegexp.match(text); | ||
const group = treeRegexp.match(text) | ||
if (!group) { | ||
return null; | ||
return null | ||
} | ||
const argGroups = group.children; | ||
const argGroups = group.children | ||
@@ -27,3 +27,3 @@ if (argGroups.length !== parameterTypes.length) { | ||
} parameter types (${parameterTypes.map(p => p.name)})` | ||
); | ||
) | ||
} | ||
@@ -33,3 +33,3 @@ | ||
(parameterType, i) => new Argument(argGroups[i], parameterType) | ||
); | ||
) | ||
} | ||
@@ -41,4 +41,4 @@ | ||
) { | ||
this.group = group; | ||
this.parameterType = parameterType; | ||
this.group = group | ||
this.parameterType = parameterType | ||
} | ||
@@ -52,7 +52,7 @@ | ||
public getValue(thisObj: any): T { | ||
const groupValues = this.group ? this.group.values : null; | ||
return this.parameterType.transform(thisObj, groupValues); | ||
const groupValues = this.group ? this.group.values : null | ||
return this.parameterType.transform(thisObj, groupValues) | ||
} | ||
} | ||
module.exports = Argument; | ||
module.exports = Argument |
@@ -1,6 +0,6 @@ | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import ParameterType from "./ParameterType"; | ||
import GeneratedExpression from './GeneratedExpression' | ||
import ParameterType from './ParameterType' | ||
// 256 generated expressions ought to be enough for anybody | ||
const MAX_EXPRESSIONS = 256; | ||
const MAX_EXPRESSIONS = 256 | ||
@@ -12,9 +12,9 @@ export default class CombinatorialGeneratedExpressionFactory { | ||
) { | ||
this.expressionTemplate = expressionTemplate; | ||
this.expressionTemplate = expressionTemplate | ||
} | ||
public generateExpressions() { | ||
const generatedExpressions: GeneratedExpression[] = []; | ||
this._generatePermutations(generatedExpressions, 0, []); | ||
return generatedExpressions; | ||
const generatedExpressions: GeneratedExpression[] = [] | ||
this._generatePermutations(generatedExpressions, 0, []) | ||
return generatedExpressions | ||
} | ||
@@ -28,3 +28,3 @@ | ||
if (generatedExpressions.length >= MAX_EXPRESSIONS) { | ||
return; | ||
return | ||
} | ||
@@ -35,4 +35,4 @@ | ||
new GeneratedExpression(this.expressionTemplate, currentParameterTypes) | ||
); | ||
return; | ||
) | ||
return | ||
} | ||
@@ -44,7 +44,7 @@ | ||
if (generatedExpressions.length >= MAX_EXPRESSIONS) { | ||
return; | ||
return | ||
} | ||
const newCurrentParameterTypes = currentParameterTypes.slice(); // clone | ||
newCurrentParameterTypes.push(this.parameterTypeCombinations[depth][i]); | ||
const newCurrentParameterTypes = currentParameterTypes.slice() // clone | ||
newCurrentParameterTypes.push(this.parameterTypeCombinations[depth][i]) | ||
this._generatePermutations( | ||
@@ -54,5 +54,5 @@ generatedExpressions, | ||
newCurrentParameterTypes | ||
); | ||
) | ||
} | ||
} | ||
} |
@@ -1,6 +0,6 @@ | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import ParameterType from "./ParameterType"; | ||
import TreeRegexp from "./TreeRegexp"; | ||
import Argument from "./Argument"; | ||
import { CucumberExpressionError, UndefinedParameterTypeError } from "./Errors"; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry' | ||
import ParameterType from './ParameterType' | ||
import TreeRegexp from './TreeRegexp' | ||
import Argument from './Argument' | ||
import { CucumberExpressionError, UndefinedParameterTypeError } from './Errors' | ||
@@ -12,16 +12,16 @@ // RegExps with the g flag are stateful in JavaScript. In order to be able | ||
// Does not include (){} characters because they have special meaning | ||
const ESCAPE_REGEXP = () => /([\\^[$.|?*+])/g; | ||
const PARAMETER_REGEXP = () => /(\\\\)?{([^}]*)}/g; | ||
const OPTIONAL_REGEXP = () => /(\\\\)?\(([^)]+)\)/g; | ||
const ESCAPE_REGEXP = () => /([\\^[$.|?*+])/g | ||
const PARAMETER_REGEXP = () => /(\\\\)?{([^}]*)}/g | ||
const OPTIONAL_REGEXP = () => /(\\\\)?\(([^)]+)\)/g | ||
const ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP = () => | ||
/([^\s^/]+)((\/[^\s^/]+)+)/g; | ||
const DOUBLE_ESCAPE = "\\\\"; | ||
/([^\s^/]+)((\/[^\s^/]+)+)/g | ||
const DOUBLE_ESCAPE = '\\\\' | ||
const PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE = | ||
"Parameter types cannot be alternative: "; | ||
'Parameter types cannot be alternative: ' | ||
const PARAMETER_TYPES_CANNOT_BE_OPTIONAL = | ||
"Parameter types cannot be optional: "; | ||
'Parameter types cannot be optional: ' | ||
export default class CucumberExpression { | ||
private parameterTypes: Array<ParameterType<any>> = []; | ||
private treeRegexp: TreeRegexp; | ||
private parameterTypes: Array<ParameterType<any>> = [] | ||
private treeRegexp: TreeRegexp | ||
@@ -36,13 +36,13 @@ /** | ||
) { | ||
let expr = this.processEscapes(expression); | ||
expr = this.processOptional(expr); | ||
expr = this.processAlternation(expr); | ||
expr = this.processParameters(expr, parameterTypeRegistry); | ||
expr = `^${expr}$`; | ||
let expr = this.processEscapes(expression) | ||
expr = this.processOptional(expr) | ||
expr = this.processAlternation(expr) | ||
expr = this.processParameters(expr, parameterTypeRegistry) | ||
expr = `^${expr}$` | ||
this.treeRegexp = new TreeRegexp(expr); | ||
this.treeRegexp = new TreeRegexp(expr) | ||
} | ||
public processEscapes(expression: string) { | ||
return expression.replace(ESCAPE_REGEXP(), "\\$1"); | ||
return expression.replace(ESCAPE_REGEXP(), '\\$1') | ||
} | ||
@@ -53,7 +53,7 @@ | ||
if (p1 === DOUBLE_ESCAPE) { | ||
return `\\(${p2}\\)`; | ||
return `\\(${p2}\\)` | ||
} | ||
this._checkNoParameterType(p2, PARAMETER_TYPES_CANNOT_BE_OPTIONAL); | ||
return `(?:${p2})?`; | ||
}); | ||
this._checkNoParameterType(p2, PARAMETER_TYPES_CANNOT_BE_OPTIONAL) | ||
return `(?:${p2})?` | ||
}) | ||
} | ||
@@ -67,4 +67,4 @@ | ||
// replace / with | | ||
const replacement = match.replace(/\//g, "|").replace(/\\\|/g, "/"); | ||
if (replacement.indexOf("|") !== -1) { | ||
const replacement = match.replace(/\//g, '|').replace(/\\\|/g, '/') | ||
if (replacement.indexOf('|') !== -1) { | ||
for (const part of replacement.split(/\|/)) { | ||
@@ -74,10 +74,10 @@ this._checkNoParameterType( | ||
PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE | ||
); | ||
) | ||
} | ||
return `(?:${replacement})`; | ||
return `(?:${replacement})` | ||
} else { | ||
return replacement; | ||
return replacement | ||
} | ||
} | ||
); | ||
) | ||
} | ||
@@ -91,26 +91,26 @@ | ||
if (p1 === DOUBLE_ESCAPE) { | ||
return `\\{${p2}\\}`; | ||
return `\\{${p2}\\}` | ||
} | ||
const typeName = p2; | ||
ParameterType.checkParameterTypeName(typeName); | ||
const parameterType = parameterTypeRegistry.lookupByTypeName(typeName); | ||
const typeName = p2 | ||
ParameterType.checkParameterTypeName(typeName) | ||
const parameterType = parameterTypeRegistry.lookupByTypeName(typeName) | ||
if (!parameterType) { | ||
throw new UndefinedParameterTypeError(typeName); | ||
throw new UndefinedParameterTypeError(typeName) | ||
} | ||
this.parameterTypes.push(parameterType); | ||
return buildCaptureRegexp(parameterType.regexpStrings); | ||
}); | ||
this.parameterTypes.push(parameterType) | ||
return buildCaptureRegexp(parameterType.regexpStrings) | ||
}) | ||
} | ||
public match(text: string): Array<Argument<any>> { | ||
return Argument.build(this.treeRegexp, text, this.parameterTypes); | ||
return Argument.build(this.treeRegexp, text, this.parameterTypes) | ||
} | ||
get regexp(): RegExp { | ||
return this.treeRegexp.regexp; | ||
return this.treeRegexp.regexp | ||
} | ||
get source() { | ||
return this.expression; | ||
return this.expression | ||
} | ||
@@ -120,3 +120,3 @@ | ||
if (s.match(PARAMETER_REGEXP())) { | ||
throw new CucumberExpressionError(message + this.source); | ||
throw new CucumberExpressionError(message + this.source) | ||
} | ||
@@ -128,10 +128,10 @@ } | ||
if (regexps.length === 1) { | ||
return `(${regexps[0]})`; | ||
return `(${regexps[0]})` | ||
} | ||
const captureGroups = regexps.map(group => { | ||
return `(?:${group})`; | ||
}); | ||
return `(?:${group})` | ||
}) | ||
return `(${captureGroups.join("|")})`; | ||
return `(${captureGroups.join('|')})` | ||
} |
@@ -1,8 +0,8 @@ | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import ParameterTypeMatcher from "./ParameterTypeMatcher"; | ||
import ParameterType from "./ParameterType"; | ||
import ParameterTypeRegistry from './ParameterTypeRegistry' | ||
import ParameterTypeMatcher from './ParameterTypeMatcher' | ||
import ParameterType from './ParameterType' | ||
import util from "util"; | ||
import CombinatorialGeneratedExpressionFactory from "./CombinatorialGeneratedExpressionFactory"; | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import util from 'util' | ||
import CombinatorialGeneratedExpressionFactory from './CombinatorialGeneratedExpressionFactory' | ||
import GeneratedExpression from './GeneratedExpression' | ||
@@ -13,17 +13,15 @@ export default class CucumberExpressionGenerator { | ||
public generateExpressions(text: string): GeneratedExpression[] { | ||
const parameterTypeCombinations: Array<Array<ParameterType<any>>> = []; | ||
const parameterTypeMatchers = this._createParameterTypeMatchers(text); | ||
let expressionTemplate = ""; | ||
let pos = 0; | ||
const parameterTypeCombinations: Array<Array<ParameterType<any>>> = [] | ||
const parameterTypeMatchers = this._createParameterTypeMatchers(text) | ||
let expressionTemplate = '' | ||
let pos = 0 | ||
// eslint-disable-next-line no-constant-condition | ||
while (true) { | ||
let matchingParameterTypeMatchers = []; | ||
let matchingParameterTypeMatchers = [] | ||
for (const parameterTypeMatcher of parameterTypeMatchers) { | ||
const advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo( | ||
pos | ||
); | ||
const advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo(pos) | ||
if (advancedParameterTypeMatcher.find) { | ||
matchingParameterTypeMatchers.push(advancedParameterTypeMatcher); | ||
matchingParameterTypeMatchers.push(advancedParameterTypeMatcher) | ||
} | ||
@@ -35,9 +33,9 @@ } | ||
ParameterTypeMatcher.compare | ||
); | ||
) | ||
// Find all the best parameter type matchers, they are all candidates. | ||
const bestParameterTypeMatcher = matchingParameterTypeMatchers[0]; | ||
const bestParameterTypeMatcher = matchingParameterTypeMatchers[0] | ||
const bestParameterTypeMatchers = matchingParameterTypeMatchers.filter( | ||
m => ParameterTypeMatcher.compare(m, bestParameterTypeMatcher) === 0 | ||
); | ||
) | ||
@@ -50,3 +48,3 @@ // Build a list of parameter types without duplicates. The reason there | ||
// Users are most likely to want these, so they should be listed at the top. | ||
let parameterTypes = []; | ||
let parameterTypes = [] | ||
for (const parameterTypeMatcher of bestParameterTypeMatchers) { | ||
@@ -56,31 +54,30 @@ if ( | ||
) { | ||
parameterTypes.push(parameterTypeMatcher.parameterType); | ||
parameterTypes.push(parameterTypeMatcher.parameterType) | ||
} | ||
} | ||
parameterTypes = parameterTypes.sort(ParameterType.compare); | ||
parameterTypes = parameterTypes.sort(ParameterType.compare) | ||
parameterTypeCombinations.push(parameterTypes); | ||
parameterTypeCombinations.push(parameterTypes) | ||
expressionTemplate += escape( | ||
text.slice(pos, bestParameterTypeMatcher.start) | ||
); | ||
expressionTemplate += "{%s}"; | ||
) | ||
expressionTemplate += '{%s}' | ||
pos = | ||
bestParameterTypeMatcher.start + | ||
bestParameterTypeMatcher.group.length; | ||
bestParameterTypeMatcher.start + bestParameterTypeMatcher.group.length | ||
} else { | ||
break; | ||
break | ||
} | ||
if (pos >= text.length) { | ||
break; | ||
break | ||
} | ||
} | ||
expressionTemplate += escape(text.slice(pos)); | ||
expressionTemplate += escape(text.slice(pos)) | ||
return new CombinatorialGeneratedExpressionFactory( | ||
expressionTemplate, | ||
parameterTypeCombinations | ||
).generateExpressions(); | ||
).generateExpressions() | ||
} | ||
@@ -94,8 +91,8 @@ | ||
() => this.generateExpressions(text)[0], | ||
"CucumberExpressionGenerator.generateExpression: Use CucumberExpressionGenerator.generateExpressions instead" | ||
)(); | ||
'CucumberExpressionGenerator.generateExpression: Use CucumberExpressionGenerator.generateExpressions instead' | ||
)() | ||
} | ||
public _createParameterTypeMatchers(text: string): ParameterTypeMatcher[] { | ||
let parameterMatchers: ParameterTypeMatcher[] = []; | ||
let parameterMatchers: ParameterTypeMatcher[] = [] | ||
for (const parameterType of this.parameterTypeRegistry.parameterTypes) { | ||
@@ -108,6 +105,6 @@ if (parameterType.useForSnippets) { | ||
) | ||
); | ||
) | ||
} | ||
} | ||
return parameterMatchers; | ||
return parameterMatchers | ||
} | ||
@@ -120,7 +117,7 @@ | ||
// TODO: [].map | ||
const result = []; | ||
const result = [] | ||
for (const regexp of parameterType.regexpStrings) { | ||
result.push(new ParameterTypeMatcher(parameterType, regexp, text)); | ||
result.push(new ParameterTypeMatcher(parameterType, regexp, text)) | ||
} | ||
return result; | ||
return result | ||
} | ||
@@ -131,8 +128,8 @@ } | ||
return s | ||
.replace(/%/g, "%%") // for util.format | ||
.replace(/\(/g, "\\(") | ||
.replace(/{/g, "\\{") | ||
.replace(/\//g, "\\/"); | ||
.replace(/%/g, '%%') // for util.format | ||
.replace(/\(/g, '\\(') | ||
.replace(/{/g, '\\{') | ||
.replace(/\//g, '\\/') | ||
} | ||
module.exports = CucumberExpressionGenerator; | ||
module.exports = CucumberExpressionGenerator |
@@ -1,3 +0,3 @@ | ||
import ParameterType from "./ParameterType"; | ||
import GeneratedExpression from "./GeneratedExpression"; | ||
import ParameterType from './ParameterType' | ||
import GeneratedExpression from './GeneratedExpression' | ||
@@ -15,3 +15,3 @@ class CucumberExpressionError extends Error {} | ||
`parameter type with ${keyName}=${keyValue} is used by several parameter types: ${parameterTypes}, ${generatedExpressions}` | ||
); | ||
) | ||
} | ||
@@ -37,11 +37,11 @@ | ||
` | ||
); | ||
) | ||
} | ||
public static _parameterTypeNames(parameterTypes: Array<ParameterType<any>>) { | ||
return parameterTypes.map(p => `{${p.name}}`).join("\n "); | ||
return parameterTypes.map(p => `{${p.name}}`).join('\n ') | ||
} | ||
public static _expressions(generatedExpressions: GeneratedExpression[]) { | ||
return generatedExpressions.map(e => e.source).join("\n "); | ||
return generatedExpressions.map(e => e.source).join('\n ') | ||
} | ||
@@ -52,3 +52,3 @@ } | ||
constructor(typeName: string) { | ||
super(`Undefined parameter type {${typeName}}`); | ||
super(`Undefined parameter type {${typeName}}`) | ||
} | ||
@@ -60,3 +60,3 @@ } | ||
UndefinedParameterTypeError, | ||
CucumberExpressionError | ||
}; | ||
CucumberExpressionError, | ||
} |
@@ -1,3 +0,3 @@ | ||
import util from "util"; | ||
import ParameterType from "./ParameterType"; | ||
import util from 'util' | ||
import ParameterType from './ParameterType' | ||
@@ -14,3 +14,3 @@ export default class GeneratedExpression { | ||
...this.parameterTypes.map(t => t.name) | ||
); | ||
) | ||
} | ||
@@ -24,6 +24,6 @@ | ||
get parameterNames() { | ||
const usageByTypeName: { [key: string]: number } = {}; | ||
const usageByTypeName: { [key: string]: number } = {} | ||
return this.parameterTypes.map(t => | ||
getParameterName(t.name, usageByTypeName) | ||
); | ||
) | ||
} | ||
@@ -36,7 +36,7 @@ } | ||
) { | ||
let count = usageByTypeName[typeName]; | ||
count = count ? count + 1 : 1; | ||
usageByTypeName[typeName] = count; | ||
let count = usageByTypeName[typeName] | ||
count = count ? count + 1 : 1 | ||
usageByTypeName[typeName] = count | ||
return count === 1 ? typeName : `${typeName}${count}`; | ||
return count === 1 ? typeName : `${typeName}${count}` | ||
} |
@@ -12,4 +12,4 @@ export default class Group { | ||
.map(g => g.value) | ||
.filter(v => v !== null); | ||
.filter(v => v !== null) | ||
} | ||
} |
@@ -1,37 +0,37 @@ | ||
import Group from "./Group"; | ||
import RegexExecArray from "./RegexExecArray"; | ||
import Group from './Group' | ||
import RegexExecArray from './RegexExecArray' | ||
export default class GroupBuilder { | ||
public source: string; | ||
public capturing = true; | ||
private groupBuilders: GroupBuilder[] = []; | ||
public source: string | ||
public capturing = true | ||
private groupBuilders: GroupBuilder[] = [] | ||
public add(groupBuilder: GroupBuilder) { | ||
this.groupBuilders.push(groupBuilder); | ||
this.groupBuilders.push(groupBuilder) | ||
} | ||
public build(match: RegexExecArray, nextGroupIndex: () => number): Group { | ||
const groupIndex = nextGroupIndex(); | ||
const groupIndex = nextGroupIndex() | ||
const children = this.groupBuilders.map(gb => | ||
gb.build(match, nextGroupIndex) | ||
); | ||
) | ||
return new Group( | ||
match[groupIndex] || null, | ||
match.index[groupIndex], | ||
match.index[groupIndex] + (match[groupIndex] || "").length, | ||
match.index[groupIndex] + (match[groupIndex] || '').length, | ||
children | ||
); | ||
) | ||
} | ||
public setNonCapturing() { | ||
this.capturing = false; | ||
this.capturing = false | ||
} | ||
get children() { | ||
return this.groupBuilders; | ||
return this.groupBuilders | ||
} | ||
public moveChildrenTo(groupBuilder: GroupBuilder) { | ||
this.groupBuilders.forEach(child => groupBuilder.add(child)); | ||
this.groupBuilders.forEach(child => groupBuilder.add(child)) | ||
} | ||
} |
@@ -1,6 +0,6 @@ | ||
import CucumberExpression from "./CucumberExpression"; | ||
import RegularExpression from "./RegularExpression"; | ||
import CucumberExpressionGenerator from "./CucumberExpressionGenerator"; | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import ParameterType from "./ParameterType"; | ||
import CucumberExpression from './CucumberExpression' | ||
import RegularExpression from './RegularExpression' | ||
import CucumberExpressionGenerator from './CucumberExpressionGenerator' | ||
import ParameterTypeRegistry from './ParameterTypeRegistry' | ||
import ParameterType from './ParameterType' | ||
@@ -12,3 +12,3 @@ export = { | ||
ParameterTypeRegistry, | ||
ParameterType | ||
}; | ||
ParameterType, | ||
} |
@@ -1,32 +0,30 @@ | ||
import { CucumberExpressionError } from "./Errors"; | ||
import { CucumberExpressionError } from './Errors' | ||
const ILLEGAL_PARAMETER_NAME_PATTERN = /([[\]()$.|?*+])/; | ||
const UNESCAPE_PATTERN = () => /(\\([[$.|?*+\]]))/g; | ||
const ILLEGAL_PARAMETER_NAME_PATTERN = /([[\]()$.|?*+])/ | ||
const UNESCAPE_PATTERN = () => /(\\([[$.|?*+\]]))/g | ||
export default class ParameterType<T> { | ||
private transformFn: (match: string) => T; | ||
private transformFn: (match: string) => T | ||
public static compare(pt1: ParameterType<any>, pt2: ParameterType<any>) { | ||
if (pt1.preferForRegexpMatch && !pt2.preferForRegexpMatch) { | ||
return -1; | ||
return -1 | ||
} | ||
if (pt2.preferForRegexpMatch && !pt1.preferForRegexpMatch) { | ||
return 1; | ||
return 1 | ||
} | ||
return pt1.name.localeCompare(pt2.name); | ||
return pt1.name.localeCompare(pt2.name) | ||
} | ||
public static checkParameterTypeName(typeName: string) { | ||
const unescapedTypeName = typeName.replace(UNESCAPE_PATTERN(), "$2"); | ||
const match = unescapedTypeName.match(ILLEGAL_PARAMETER_NAME_PATTERN); | ||
const unescapedTypeName = typeName.replace(UNESCAPE_PATTERN(), '$2') | ||
const match = unescapedTypeName.match(ILLEGAL_PARAMETER_NAME_PATTERN) | ||
if (match) { | ||
throw new CucumberExpressionError( | ||
`Illegal character '${ | ||
match[1] | ||
}' in parameter name {${unescapedTypeName}}` | ||
); | ||
`Illegal character '${match[1]}' in parameter name {${unescapedTypeName}}` | ||
) | ||
} | ||
} | ||
public regexpStrings: string[]; | ||
public regexpStrings: string[] | ||
@@ -50,22 +48,22 @@ /** | ||
if (transform === undefined) { | ||
transform = s => (s as unknown) as T; | ||
transform = s => (s as unknown) as T | ||
} | ||
if (useForSnippets === undefined) { | ||
this.useForSnippets = true; | ||
this.useForSnippets = true | ||
} | ||
if (preferForRegexpMatch === undefined) { | ||
this.preferForRegexpMatch = false; | ||
this.preferForRegexpMatch = false | ||
} | ||
if (name) { | ||
ParameterType.checkParameterTypeName(name); | ||
ParameterType.checkParameterTypeName(name) | ||
} | ||
this.regexpStrings = stringArray(regexps); | ||
this.transformFn = transform; | ||
this.regexpStrings = stringArray(regexps) | ||
this.transformFn = transform | ||
} | ||
public transform(thisObj: any, groupValues: string[]) { | ||
const result = this.transformFn.apply(thisObj, groupValues); | ||
return result; | ||
const result = this.transformFn.apply(thisObj, groupValues) | ||
return result | ||
} | ||
@@ -75,19 +73,19 @@ } | ||
function stringArray(regexps: RegExp[] | string[] | RegExp | string): string[] { | ||
const array = Array.isArray(regexps) ? regexps : [regexps]; | ||
const array = Array.isArray(regexps) ? regexps : [regexps] | ||
return array.map((r: RegExp | string) => | ||
r instanceof RegExp ? regexpSource(r) : r | ||
); | ||
) | ||
} | ||
function regexpSource(regexp: RegExp): string { | ||
const flags = regexpFlags(regexp); | ||
const flags = regexpFlags(regexp) | ||
for (const flag of ["g", "i", "m", "y"]) { | ||
for (const flag of ['g', 'i', 'm', 'y']) { | ||
if (flags.indexOf(flag) !== -1) { | ||
throw new CucumberExpressionError( | ||
`ParameterType Regexps can't use flag '${flag}'` | ||
); | ||
) | ||
} | ||
} | ||
return regexp.source; | ||
return regexp.source | ||
} | ||
@@ -98,16 +96,16 @@ | ||
function regexpFlags(regexp: RegExp) { | ||
let flags = regexp.flags; | ||
let flags = regexp.flags | ||
if (flags === undefined) { | ||
flags = ""; | ||
flags = '' | ||
if (regexp.ignoreCase) { | ||
flags += "i"; | ||
flags += 'i' | ||
} | ||
if (regexp.global) { | ||
flags += "g"; | ||
flags += 'g' | ||
} | ||
if (regexp.multiline) { | ||
flags += "m"; | ||
flags += 'm' | ||
} | ||
} | ||
return flags; | ||
return flags | ||
} |
@@ -1,5 +0,5 @@ | ||
import ParameterType from "./ParameterType"; | ||
import ParameterType from './ParameterType' | ||
export default class ParameterTypeMatcher { | ||
private readonly match: RegExpExecArray; | ||
private readonly match: RegExpExecArray | ||
@@ -12,4 +12,4 @@ constructor( | ||
) { | ||
const captureGroupRegexp = new RegExp(`(${regexpString})`); | ||
this.match = captureGroupRegexp.exec(text.slice(this.matchPosition)); | ||
const captureGroupRegexp = new RegExp(`(${regexpString})`) | ||
this.match = captureGroupRegexp.exec(text.slice(this.matchPosition)) | ||
} | ||
@@ -28,6 +28,6 @@ | ||
advancedPos | ||
); | ||
) | ||
if (matcher.find) { | ||
return matcher; | ||
return matcher | ||
} | ||
@@ -41,30 +41,30 @@ } | ||
this.text.length | ||
); | ||
) | ||
} | ||
get find() { | ||
return this.match && this.group !== ""; | ||
return this.match && this.group !== '' | ||
} | ||
get start() { | ||
return this.matchPosition + this.match.index; | ||
return this.matchPosition + this.match.index | ||
} | ||
get group() { | ||
return this.match[0]; | ||
return this.match[0] | ||
} | ||
public static compare(a: ParameterTypeMatcher, b: ParameterTypeMatcher) { | ||
const posComparison = a.start - b.start; | ||
const posComparison = a.start - b.start | ||
if (posComparison !== 0) { | ||
return posComparison; | ||
return posComparison | ||
} | ||
const lengthComparison = b.group.length - a.group.length; | ||
const lengthComparison = b.group.length - a.group.length | ||
if (lengthComparison !== 0) { | ||
return lengthComparison; | ||
return lengthComparison | ||
} | ||
return 0; | ||
return 0 | ||
} | ||
} | ||
module.exports = ParameterTypeMatcher; | ||
module.exports = ParameterTypeMatcher |
@@ -1,18 +0,18 @@ | ||
import ParameterType from "./ParameterType"; | ||
import ParameterType from './ParameterType' | ||
import CucumberExpressionGenerator from "./CucumberExpressionGenerator"; | ||
import { AmbiguousParameterTypeError, CucumberExpressionError } from "./Errors"; | ||
import CucumberExpressionGenerator from './CucumberExpressionGenerator' | ||
import { AmbiguousParameterTypeError, CucumberExpressionError } from './Errors' | ||
const INTEGER_REGEXPS = [/-?\d+/, /\d+/]; | ||
const FLOAT_REGEXP = /-?\d*\.?\d+/; | ||
const WORD_REGEXP = /[^\s]+/; | ||
const STRING_REGEXP = /"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/; | ||
const ANONYMOUS_REGEXP = /.*/; | ||
const INTEGER_REGEXPS = [/-?\d+/, /\d+/] | ||
const FLOAT_REGEXP = /-?\d*\.?\d+/ | ||
const WORD_REGEXP = /[^\s]+/ | ||
const STRING_REGEXP = /"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/ | ||
const ANONYMOUS_REGEXP = /.*/ | ||
export default class ParameterTypeRegistry { | ||
private readonly parameterTypeByName = new Map<string, ParameterType<any>>(); | ||
private readonly parameterTypeByName = new Map<string, ParameterType<any>>() | ||
private readonly parameterTypesByRegexp = new Map< | ||
string, | ||
Array<ParameterType<any>> | ||
>(); | ||
>() | ||
@@ -22,3 +22,3 @@ constructor() { | ||
new ParameterType( | ||
"int", | ||
'int', | ||
INTEGER_REGEXPS, | ||
@@ -30,6 +30,6 @@ Number, | ||
) | ||
); | ||
) | ||
this.defineParameterType( | ||
new ParameterType( | ||
"float", | ||
'float', | ||
FLOAT_REGEXP, | ||
@@ -41,9 +41,9 @@ Number, | ||
) | ||
); | ||
) | ||
this.defineParameterType( | ||
new ParameterType("word", WORD_REGEXP, String, s => s, false, false) | ||
); | ||
new ParameterType('word', WORD_REGEXP, String, s => s, false, false) | ||
) | ||
this.defineParameterType( | ||
new ParameterType( | ||
"string", | ||
'string', | ||
STRING_REGEXP, | ||
@@ -55,14 +55,14 @@ String, | ||
) | ||
); | ||
) | ||
this.defineParameterType( | ||
new ParameterType("", ANONYMOUS_REGEXP, String, s => s, false, true) | ||
); | ||
new ParameterType('', ANONYMOUS_REGEXP, String, s => s, false, true) | ||
) | ||
} | ||
get parameterTypes() { | ||
return this.parameterTypeByName.values(); | ||
return this.parameterTypeByName.values() | ||
} | ||
public lookupByTypeName(typeName: string) { | ||
return this.parameterTypeByName.get(typeName); | ||
return this.parameterTypeByName.get(typeName) | ||
} | ||
@@ -75,5 +75,5 @@ | ||
): ParameterType<any> { | ||
const parameterTypes = this.parameterTypesByRegexp.get(parameterTypeRegexp); | ||
const parameterTypes = this.parameterTypesByRegexp.get(parameterTypeRegexp) | ||
if (!parameterTypes) { | ||
return null; | ||
return null | ||
} | ||
@@ -86,3 +86,3 @@ if (parameterTypes.length > 1 && !parameterTypes[0].preferForRegexpMatch) { | ||
this | ||
).generateExpressions(text); | ||
).generateExpressions(text) | ||
throw AmbiguousParameterTypeError.forRegExp( | ||
@@ -93,5 +93,5 @@ parameterTypeRegexp, | ||
generatedExpressions | ||
); | ||
) | ||
} | ||
return parameterTypes[0]; | ||
return parameterTypes[0] | ||
} | ||
@@ -105,10 +105,10 @@ | ||
`The anonymous parameter type has already been defined` | ||
); | ||
) | ||
} else { | ||
throw new Error( | ||
`There is already a parameter type with name ${parameterType.name}` | ||
); | ||
) | ||
} | ||
} | ||
this.parameterTypeByName.set(parameterType.name, parameterType); | ||
this.parameterTypeByName.set(parameterType.name, parameterType) | ||
} | ||
@@ -118,8 +118,8 @@ | ||
if (!this.parameterTypesByRegexp.has(parameterTypeRegexp)) { | ||
this.parameterTypesByRegexp.set(parameterTypeRegexp, []); | ||
this.parameterTypesByRegexp.set(parameterTypeRegexp, []) | ||
} | ||
const parameterTypes = this.parameterTypesByRegexp.get( | ||
parameterTypeRegexp | ||
); | ||
const existingParameterType = parameterTypes[0]; | ||
) | ||
const existingParameterType = parameterTypes[0] | ||
if ( | ||
@@ -131,14 +131,12 @@ parameterTypes.length > 0 && | ||
throw new CucumberExpressionError( | ||
"There can only be one preferential parameter type per regexp. " + | ||
`The regexp /${parameterTypeRegexp}/ is used for two preferential parameter types, {${ | ||
existingParameterType.name | ||
}} and {${parameterType.name}}` | ||
); | ||
'There can only be one preferential parameter type per regexp. ' + | ||
`The regexp /${parameterTypeRegexp}/ is used for two preferential parameter types, {${existingParameterType.name}} and {${parameterType.name}}` | ||
) | ||
} | ||
if (parameterTypes.indexOf(parameterType) === -1) { | ||
parameterTypes.push(parameterType); | ||
parameterTypes.push(parameterType) | ||
this.parameterTypesByRegexp.set( | ||
parameterTypeRegexp, | ||
parameterTypes.sort(ParameterType.compare) | ||
); | ||
) | ||
} | ||
@@ -149,2 +147,2 @@ } | ||
module.exports = ParameterTypeRegistry; | ||
module.exports = ParameterTypeRegistry |
export default interface RegexExecArray extends Array<string> { | ||
index: number[]; | ||
input: string; | ||
index: number[] | ||
input: string | ||
} |
@@ -1,8 +0,8 @@ | ||
import Argument from "./Argument"; | ||
import TreeRegexp from "./TreeRegexp"; | ||
import ParameterType from "./ParameterType"; | ||
import ParameterTypeRegistry from "./ParameterTypeRegistry"; | ||
import Argument from './Argument' | ||
import TreeRegexp from './TreeRegexp' | ||
import ParameterType from './ParameterType' | ||
import ParameterTypeRegistry from './ParameterTypeRegistry' | ||
export default class RegularExpression { | ||
private readonly treeRegexp: TreeRegexp; | ||
private readonly treeRegexp: TreeRegexp | ||
@@ -13,3 +13,3 @@ constructor( | ||
) { | ||
this.treeRegexp = new TreeRegexp(regexp); | ||
this.treeRegexp = new TreeRegexp(regexp) | ||
} | ||
@@ -20,3 +20,3 @@ | ||
groupBuilder => { | ||
const parameterTypeRegexp = groupBuilder.source; | ||
const parameterTypeRegexp = groupBuilder.source | ||
@@ -37,12 +37,12 @@ return ( | ||
) | ||
); | ||
) | ||
} | ||
); | ||
) | ||
return Argument.build(this.treeRegexp, text, parameterTypes); | ||
return Argument.build(this.treeRegexp, text, parameterTypes) | ||
} | ||
get source() { | ||
return this.regexp.source; | ||
return this.regexp.source | ||
} | ||
} |
@@ -1,60 +0,60 @@ | ||
import GroupBuilder from "./GroupBuilder"; | ||
import GroupBuilder from './GroupBuilder' | ||
// @ts-ignore | ||
import Regex from "becke-ch--regex--s0-0-v1--base--pl--lib"; | ||
import RegexExecArray from "./RegexExecArray"; | ||
import Regex from 'becke-ch--regex--s0-0-v1--base--pl--lib' | ||
import RegexExecArray from './RegexExecArray' | ||
export default class TreeRegexp { | ||
public regexp: RegExp; | ||
private regex: any; | ||
public groupBuilder: GroupBuilder; | ||
public regexp: RegExp | ||
private regex: any | ||
public groupBuilder: GroupBuilder | ||
constructor(regexp: RegExp | string) { | ||
this.regexp = "string" === typeof regexp ? new RegExp(regexp) : regexp; | ||
this.regex = new Regex(this.regexp.source, this.regexp.flags); | ||
this.regexp = 'string' === typeof regexp ? new RegExp(regexp) : regexp | ||
this.regex = new Regex(this.regexp.source, this.regexp.flags) | ||
const stack: GroupBuilder[] = [new GroupBuilder()]; | ||
const groupStartStack: number[] = []; | ||
let last: string = null; | ||
let escaping = false; | ||
let nonCapturingMaybe = false; | ||
let charClass = false; | ||
this.regexp.source.split("").forEach((c, n) => { | ||
if (c === "[" && !escaping) { | ||
charClass = true; | ||
} else if (c === "]" && !escaping) { | ||
charClass = false; | ||
} else if (c === "(" && !escaping && !charClass) { | ||
stack.push(new GroupBuilder()); | ||
groupStartStack.push(n + 1); | ||
nonCapturingMaybe = false; | ||
} else if (c === ")" && !escaping && !charClass) { | ||
const gb = stack.pop(); | ||
const groupStart = groupStartStack.pop(); | ||
const stack: GroupBuilder[] = [new GroupBuilder()] | ||
const groupStartStack: number[] = [] | ||
let last: string = null | ||
let escaping = false | ||
let nonCapturingMaybe = false | ||
let charClass = false | ||
this.regexp.source.split('').forEach((c, n) => { | ||
if (c === '[' && !escaping) { | ||
charClass = true | ||
} else if (c === ']' && !escaping) { | ||
charClass = false | ||
} else if (c === '(' && !escaping && !charClass) { | ||
stack.push(new GroupBuilder()) | ||
groupStartStack.push(n + 1) | ||
nonCapturingMaybe = false | ||
} else if (c === ')' && !escaping && !charClass) { | ||
const gb = stack.pop() | ||
const groupStart = groupStartStack.pop() | ||
if (gb.capturing) { | ||
gb.source = this.regexp.source.substring(groupStart, n); | ||
stack[stack.length - 1].add(gb); | ||
gb.source = this.regexp.source.substring(groupStart, n) | ||
stack[stack.length - 1].add(gb) | ||
} else { | ||
gb.moveChildrenTo(stack[stack.length - 1]); | ||
gb.moveChildrenTo(stack[stack.length - 1]) | ||
} | ||
nonCapturingMaybe = false; | ||
} else if (c === "?" && last === "(") { | ||
nonCapturingMaybe = true; | ||
} else if (c === ":" && nonCapturingMaybe) { | ||
stack[stack.length - 1].setNonCapturing(); | ||
nonCapturingMaybe = false; | ||
nonCapturingMaybe = false | ||
} else if (c === '?' && last === '(') { | ||
nonCapturingMaybe = true | ||
} else if (c === ':' && nonCapturingMaybe) { | ||
stack[stack.length - 1].setNonCapturing() | ||
nonCapturingMaybe = false | ||
} | ||
escaping = c === "\\" && !escaping; | ||
last = c; | ||
}); | ||
this.groupBuilder = stack.pop(); | ||
escaping = c === '\\' && !escaping | ||
last = c | ||
}) | ||
this.groupBuilder = stack.pop() | ||
} | ||
public match(s: string) { | ||
const match: RegexExecArray = this.regex.exec(s); | ||
const match: RegexExecArray = this.regex.exec(s) | ||
if (!match) { | ||
return null; | ||
return null | ||
} | ||
let groupIndex = 0; | ||
const nextGroupIndex = () => groupIndex++; | ||
return this.groupBuilder.build(match, nextGroupIndex); | ||
let groupIndex = 0 | ||
const nextGroupIndex = () => groupIndex++ | ||
return this.groupBuilder.build(match, nextGroupIndex) | ||
} | ||
} |
@@ -1,7 +0,7 @@ | ||
import assert from "assert"; | ||
import assert from 'assert' | ||
// A better assert.error that allows an exact error message | ||
export default (fn: () => any, message: string) => { | ||
const regexp = new RegExp(message.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&")); | ||
assert.throws(fn, regexp); | ||
}; | ||
const regexp = new RegExp(message.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')) | ||
assert.throws(fn, regexp) | ||
} |
@@ -1,11 +0,11 @@ | ||
import assert from "assert"; | ||
import ParameterType from "../src/ParameterType"; | ||
import CombinatorialGeneratedExpressionFactory from "../src/CombinatorialGeneratedExpressionFactory"; | ||
import assert from 'assert' | ||
import ParameterType from '../src/ParameterType' | ||
import CombinatorialGeneratedExpressionFactory from '../src/CombinatorialGeneratedExpressionFactory' | ||
describe("CucumberExpressionGenerator", () => { | ||
it("generates multiple expressions", () => { | ||
describe('CucumberExpressionGenerator', () => { | ||
it('generates multiple expressions', () => { | ||
const parameterTypeCombinations = [ | ||
[ | ||
new ParameterType( | ||
"color", | ||
'color', | ||
/red|blue|yellow/, | ||
@@ -18,3 +18,3 @@ null, | ||
new ParameterType( | ||
"csscolor", | ||
'csscolor', | ||
/red|blue|yellow/, | ||
@@ -25,7 +25,7 @@ null, | ||
true | ||
) | ||
), | ||
], | ||
[ | ||
new ParameterType( | ||
"date", | ||
'date', | ||
/\d{4}-\d{2}-\d{2}/, | ||
@@ -38,3 +38,3 @@ null, | ||
new ParameterType( | ||
"datetime", | ||
'datetime', | ||
/\d{4}-\d{2}-\d{2}/, | ||
@@ -47,3 +47,3 @@ null, | ||
new ParameterType( | ||
"timestamp", | ||
'timestamp', | ||
/\d{4}-\d{2}-\d{2}/, | ||
@@ -54,20 +54,20 @@ null, | ||
true | ||
) | ||
] | ||
]; | ||
), | ||
], | ||
] | ||
const factory = new CombinatorialGeneratedExpressionFactory( | ||
"I bought a {%s} ball on {%s}", | ||
'I bought a {%s} ball on {%s}', | ||
parameterTypeCombinations | ||
); | ||
const expressions = factory.generateExpressions().map(ge => ge.source); | ||
) | ||
const expressions = factory.generateExpressions().map(ge => ge.source) | ||
assert.deepStrictEqual(expressions, [ | ||
"I bought a {color} ball on {date}", | ||
"I bought a {color} ball on {datetime}", | ||
"I bought a {color} ball on {timestamp}", | ||
"I bought a {csscolor} ball on {date}", | ||
"I bought a {csscolor} ball on {datetime}", | ||
"I bought a {csscolor} ball on {timestamp}" | ||
]); | ||
}); | ||
}); | ||
'I bought a {color} ball on {date}', | ||
'I bought a {color} ball on {datetime}', | ||
'I bought a {color} ball on {timestamp}', | ||
'I bought a {csscolor} ball on {date}', | ||
'I bought a {csscolor} ball on {datetime}', | ||
'I bought a {csscolor} ball on {timestamp}', | ||
]) | ||
}) | ||
}) |
@@ -1,6 +0,6 @@ | ||
import assert from "assert"; | ||
import CucumberExpressionGenerator from "../src/CucumberExpressionGenerator"; | ||
import CucumberExpression from "../src/CucumberExpression"; | ||
import ParameterType from "../src/ParameterType"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import assert from 'assert' | ||
import CucumberExpressionGenerator from '../src/CucumberExpressionGenerator' | ||
import CucumberExpression from '../src/CucumberExpression' | ||
import ParameterType from '../src/ParameterType' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
@@ -11,5 +11,5 @@ class Currency { | ||
describe("CucumberExpressionGenerator", () => { | ||
let parameterTypeRegistry: ParameterTypeRegistry; | ||
let generator: CucumberExpressionGenerator; | ||
describe('CucumberExpressionGenerator', () => { | ||
let parameterTypeRegistry: ParameterTypeRegistry | ||
let generator: CucumberExpressionGenerator | ||
@@ -21,8 +21,8 @@ function assertExpression( | ||
) { | ||
const generatedExpression = generator.generateExpressions(text)[0]; | ||
const generatedExpression = generator.generateExpressions(text)[0] | ||
assert.deepStrictEqual( | ||
generatedExpression.parameterNames, | ||
expectedArgumentNames | ||
); | ||
assert.strictEqual(generatedExpression.source, expectedExpression); | ||
) | ||
assert.strictEqual(generatedExpression.source, expectedExpression) | ||
@@ -32,90 +32,88 @@ const cucumberExpression = new CucumberExpression( | ||
parameterTypeRegistry | ||
); | ||
const match = cucumberExpression.match(text); | ||
) | ||
const match = cucumberExpression.match(text) | ||
if (match === null) { | ||
assert.fail( | ||
`Expected text '${text}' to match generated expression '${ | ||
generatedExpression.source | ||
}'` | ||
); | ||
`Expected text '${text}' to match generated expression '${generatedExpression.source}'` | ||
) | ||
} | ||
assert.strictEqual(match.length, expectedArgumentNames.length); | ||
assert.strictEqual(match.length, expectedArgumentNames.length) | ||
} | ||
beforeEach(() => { | ||
parameterTypeRegistry = new ParameterTypeRegistry(); | ||
generator = new CucumberExpressionGenerator(parameterTypeRegistry); | ||
}); | ||
parameterTypeRegistry = new ParameterTypeRegistry() | ||
generator = new CucumberExpressionGenerator(parameterTypeRegistry) | ||
}) | ||
it("documents expression generation", () => { | ||
parameterTypeRegistry = new ParameterTypeRegistry(); | ||
generator = new CucumberExpressionGenerator(parameterTypeRegistry); | ||
const undefinedStepText = "I have 2 cucumbers and 1.5 tomato"; | ||
it('documents expression generation', () => { | ||
parameterTypeRegistry = new ParameterTypeRegistry() | ||
generator = new CucumberExpressionGenerator(parameterTypeRegistry) | ||
const undefinedStepText = 'I have 2 cucumbers and 1.5 tomato' | ||
const generatedExpression = generator.generateExpressions( | ||
undefinedStepText | ||
)[0]; | ||
)[0] | ||
assert.strictEqual( | ||
generatedExpression.source, | ||
"I have {int} cucumbers and {float} tomato" | ||
); | ||
assert.strictEqual(generatedExpression.parameterNames[0], "int"); | ||
assert.strictEqual(generatedExpression.parameterTypes[1].name, "float"); | ||
}); | ||
'I have {int} cucumbers and {float} tomato' | ||
) | ||
assert.strictEqual(generatedExpression.parameterNames[0], 'int') | ||
assert.strictEqual(generatedExpression.parameterTypes[1].name, 'float') | ||
}) | ||
it("generates expression for no args", () => { | ||
assertExpression("hello", [], "hello"); | ||
}); | ||
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 parenthesis', () => { | ||
assertExpression('\\(iii)', [], '(iii)') | ||
}) | ||
it("generates expression with escaped left curly brace", () => { | ||
assertExpression("\\{iii}", [], "{iii}"); | ||
}); | ||
it('generates expression with escaped left curly brace', () => { | ||
assertExpression('\\{iii}', [], '{iii}') | ||
}) | ||
it("generates expression with escaped slashes", () => { | ||
it('generates expression with escaped slashes', () => { | ||
assertExpression( | ||
"The {int}\\/{int}\\/{int} hey", | ||
["int", "int2", "int3"], | ||
"The 1814/05/17 hey" | ||
); | ||
}); | ||
'The {int}\\/{int}\\/{int} hey', | ||
['int', 'int2', 'int3'], | ||
'The 1814/05/17 hey' | ||
) | ||
}) | ||
it("generates expression for int float arg", () => { | ||
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" | ||
); | ||
}); | ||
'I have {int} cukes and {float} euro', | ||
['int', 'float'], | ||
'I have 2 cukes and 1.5 euro' | ||
) | ||
}) | ||
it("generates expression for strings", () => { | ||
it('generates expression for strings', () => { | ||
assertExpression( | ||
"I like {string} and {string}", | ||
["string", "string2"], | ||
"I like \"bangers\" and 'mash'" | ||
); | ||
}); | ||
'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 with % sign', () => { | ||
assertExpression('I am {int}%% foobar', ['int'], 'I am 20%% foobar') | ||
}) | ||
it("generates expression for just int", () => { | ||
assertExpression("{int}", ["int"], "99999"); | ||
}); | ||
it('generates expression for just int', () => { | ||
assertExpression('{int}', ['int'], '99999') | ||
}) | ||
it("numbers only second argument when builtin type is not reserved keyword", () => { | ||
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" | ||
); | ||
}); | ||
'I have {float} cukes and {float} euro', | ||
['float', 'float2'], | ||
'I have 2.5 cukes and 1.5 euro' | ||
) | ||
}) | ||
it("generates expression for custom type", () => { | ||
it('generates expression for custom type', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"currency", | ||
'currency', | ||
/[A-Z]{3}/, | ||
@@ -127,15 +125,15 @@ Currency, | ||
) | ||
); | ||
) | ||
assertExpression( | ||
"I have a {currency} account", | ||
["currency"], | ||
"I have a EUR account" | ||
); | ||
}); | ||
'I have a {currency} account', | ||
['currency'], | ||
'I have a EUR account' | ||
) | ||
}) | ||
it("prefers leftmost match when there is overlap", () => { | ||
it('prefers leftmost match when there is overlap', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType<Currency>( | ||
"currency", | ||
'currency', | ||
/cd/, | ||
@@ -147,16 +145,16 @@ Currency, | ||
) | ||
); | ||
) | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType("date", /bc/, Date, s => new Date(s), true, false) | ||
); | ||
new ParameterType('date', /bc/, Date, s => new Date(s), true, false) | ||
) | ||
assertExpression("a{date}defg", ["date"], "abcdefg"); | ||
}); | ||
assertExpression('a{date}defg', ['date'], 'abcdefg') | ||
}) | ||
// TODO: prefers widest match | ||
it("generates all combinations of expressions when several parameter types match", () => { | ||
it('generates all combinations of expressions when several parameter types match', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"currency", | ||
'currency', | ||
/x/, | ||
@@ -168,37 +166,35 @@ null, | ||
) | ||
); | ||
) | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType("date", /x/, null, s => new Date(s), true, false) | ||
); | ||
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); | ||
'I have x and x and another x' | ||
) | ||
const expressions = generatedExpressions.map(e => e.source) | ||
assert.deepStrictEqual(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}" | ||
]); | ||
}); | ||
'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", () => { | ||
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.deepStrictEqual(typeNames, ["int", "float"]); | ||
}); | ||
'I have 2 cukes and 1.5 euro' | ||
)[0] | ||
const typeNames = expression.parameterTypes.map(parameter => parameter.name) | ||
assert.deepStrictEqual(typeNames, ['int', 'float']) | ||
}) | ||
it("matches parameter types with optional capture groups", () => { | ||
it('matches parameter types with optional capture groups', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"optional-flight", | ||
'optional-flight', | ||
/(1st flight)?/, | ||
@@ -210,6 +206,6 @@ null, | ||
) | ||
); | ||
) | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"optional-hotel", | ||
'optional-hotel', | ||
/(1st hotel)?/, | ||
@@ -221,7 +217,7 @@ null, | ||
) | ||
); | ||
) | ||
const expression = generator.generateExpressions( | ||
"I reach Stage4: 1st flight-1st hotel" | ||
)[0]; | ||
'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 | ||
@@ -231,36 +227,36 @@ // {int} to match just before {optional-hotel}. | ||
expression.source, | ||
"I reach Stage{int}: {optional-flight}{int}st hotel" | ||
); | ||
}); | ||
'I reach Stage{int}: {optional-flight}{int}st hotel' | ||
) | ||
}) | ||
it("generates at most 256 expressions", () => { | ||
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) | ||
); | ||
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.strictEqual(expressions.length, 256); | ||
}); | ||
const expressions = generator.generateExpressions('a simple step') | ||
assert.strictEqual(expressions.length, 256) | ||
}) | ||
it("prefers expression with longest non empty match", () => { | ||
it('prefers expression with longest non empty match', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType("zero-or-more", /[a-z]*/, null, s => s, true, false) | ||
); | ||
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) | ||
); | ||
new ParameterType('exactly-one', /[a-z]/, null, s => s, true, false) | ||
) | ||
const expressions = generator.generateExpressions("a simple step"); | ||
assert.strictEqual(expressions.length, 2); | ||
const expressions = generator.generateExpressions('a simple step') | ||
assert.strictEqual(expressions.length, 2) | ||
assert.strictEqual( | ||
expressions[0].source, | ||
"{exactly-one} {zero-or-more} {zero-or-more}" | ||
); | ||
'{exactly-one} {zero-or-more} {zero-or-more}' | ||
) | ||
assert.strictEqual( | ||
expressions[1].source, | ||
"{zero-or-more} {zero-or-more} {zero-or-more}" | ||
); | ||
}); | ||
}); | ||
'{zero-or-more} {zero-or-more} {zero-or-more}' | ||
) | ||
}) | ||
}) |
@@ -1,44 +0,44 @@ | ||
import assert from "assert"; | ||
import CucumberExpression from "../src/CucumberExpression"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import assert from 'assert' | ||
import CucumberExpression from '../src/CucumberExpression' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
describe("CucumberExpression", () => { | ||
describe("RegExp translation", () => { | ||
it("translates no arguments", () => { | ||
describe('CucumberExpression', () => { | ||
describe('RegExp translation', () => { | ||
it('translates no arguments', () => { | ||
assertRegexp( | ||
"I have 10 cukes in my belly now", | ||
'I have 10 cukes in my belly now', | ||
/^I have 10 cukes in my belly now$/ | ||
); | ||
}); | ||
) | ||
}) | ||
it("translates alternation", () => { | ||
it('translates alternation', () => { | ||
assertRegexp( | ||
"I had/have a great/nice/charming friend", | ||
'I had/have a great/nice/charming friend', | ||
/^I (?:had|have) a (?:great|nice|charming) friend$/ | ||
); | ||
}); | ||
) | ||
}) | ||
it("translates alternation with non-alpha", () => { | ||
assertRegexp("I said Alpha1/Beta1", /^I said (?:Alpha1|Beta1)$/); | ||
}); | ||
it('translates alternation with non-alpha', () => { | ||
assertRegexp('I said Alpha1/Beta1', /^I said (?:Alpha1|Beta1)$/) | ||
}) | ||
it("translates parameters", () => { | ||
it('translates parameters', () => { | ||
assertRegexp( | ||
"I have {float} cukes at {int} o'clock", | ||
/^I have (-?\d*\.?\d+) cukes at ((?:-?\d+)|(?:\d+)) o'clock$/ | ||
); | ||
}); | ||
) | ||
}) | ||
it("translates parenthesis to non-capturing optional capture group", () => { | ||
it('translates parenthesis to non-capturing optional capture group', () => { | ||
assertRegexp( | ||
"I have many big(ish) cukes", | ||
'I have many big(ish) cukes', | ||
/^I have many big(?:ish)? cukes$/ | ||
); | ||
}); | ||
) | ||
}) | ||
it("translates parenthesis with alpha unicode", () => { | ||
assertRegexp("Привет, Мир(ы)!", /^Привет, Мир(?:ы)?!$/); | ||
}); | ||
}); | ||
}); | ||
it('translates parenthesis with alpha unicode', () => { | ||
assertRegexp('Привет, Мир(ы)!', /^Привет, Мир(?:ы)?!$/) | ||
}) | ||
}) | ||
}) | ||
@@ -49,4 +49,4 @@ const assertRegexp = (expression: string, expectedRegexp: RegExp) => { | ||
new ParameterTypeRegistry() | ||
); | ||
assert.deepStrictEqual(cucumberExpression.regexp, expectedRegexp); | ||
}; | ||
) | ||
assert.deepStrictEqual(cucumberExpression.regexp, expectedRegexp) | ||
} |
@@ -1,186 +0,183 @@ | ||
import assert from "assert"; | ||
import CucumberExpression from "../src/CucumberExpression"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import ParameterType from "../src/ParameterType"; | ||
import assert from 'assert' | ||
import CucumberExpression from '../src/CucumberExpression' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
import ParameterType from '../src/ParameterType' | ||
describe("CucumberExpression", () => { | ||
it("documents match arguments", () => { | ||
const parameterTypeRegistry = new ParameterTypeRegistry(); | ||
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.strictEqual(7, args[0].getValue(null)); | ||
const expr = 'I have {int} cuke(s)' | ||
const expression = new CucumberExpression(expr, parameterTypeRegistry) | ||
const args = expression.match('I have 7 cukes') | ||
assert.strictEqual(7, args[0].getValue(null)) | ||
/// [capture-match-arguments] | ||
}); | ||
}) | ||
it("matches word", () => { | ||
assert.deepStrictEqual(match("three {word} mice", "three blind mice"), [ | ||
"blind" | ||
]); | ||
}); | ||
it('matches word', () => { | ||
assert.deepStrictEqual(match('three {word} mice', 'three blind mice'), [ | ||
'blind', | ||
]) | ||
}) | ||
it("matches double quoted string", () => { | ||
assert.deepStrictEqual(match("three {string} mice", 'three "blind" mice'), [ | ||
"blind" | ||
]); | ||
}); | ||
it('matches double quoted string', () => { | ||
assert.deepStrictEqual(match('three {string} mice', 'three "blind" mice'), [ | ||
'blind', | ||
]) | ||
}) | ||
it("matches multiple double quoted strings", () => { | ||
it('matches multiple double quoted strings', () => { | ||
assert.deepStrictEqual( | ||
match( | ||
"three {string} and {string} mice", | ||
'three {string} and {string} mice', | ||
'three "blind" and "crippled" mice' | ||
), | ||
["blind", "crippled"] | ||
); | ||
}); | ||
['blind', 'crippled'] | ||
) | ||
}) | ||
it("matches single quoted string", () => { | ||
assert.deepStrictEqual(match("three {string} mice", "three 'blind' mice"), [ | ||
"blind" | ||
]); | ||
}); | ||
it('matches single quoted string', () => { | ||
assert.deepStrictEqual(match('three {string} mice', "three 'blind' mice"), [ | ||
'blind', | ||
]) | ||
}) | ||
it("matches multiple single quoted strings", () => { | ||
it('matches multiple single quoted strings', () => { | ||
assert.deepStrictEqual( | ||
match( | ||
"three {string} and {string} mice", | ||
'three {string} and {string} mice', | ||
"three 'blind' and 'crippled' mice" | ||
), | ||
["blind", "crippled"] | ||
); | ||
}); | ||
['blind', 'crippled'] | ||
) | ||
}) | ||
it("does not match misquoted string", () => { | ||
it('does not match misquoted string', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", "three \"blind' mice"), | ||
match('three {string} mice', 'three "blind\' mice'), | ||
null | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches single quoted string with double quotes", () => { | ||
it('matches single quoted string with double quotes', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", "three '\"blind\"' mice"), | ||
match('three {string} mice', 'three \'"blind"\' mice'), | ||
['"blind"'] | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches double quoted string with single quotes", () => { | ||
it('matches double quoted string with single quotes', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", "three \"'blind'\" mice"), | ||
match('three {string} mice', 'three "\'blind\'" mice'), | ||
["'blind'"] | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches double quoted string with escaped double quote", () => { | ||
it('matches double quoted string with escaped double quote', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", 'three "bl\\"nd" mice'), | ||
match('three {string} mice', 'three "bl\\"nd" mice'), | ||
['bl"nd'] | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches single quoted string with escaped single quote", () => { | ||
it('matches single quoted string with escaped single quote', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", "three 'bl\\'nd' mice"), | ||
match('three {string} mice', "three 'bl\\'nd' mice"), | ||
["bl'nd"] | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches single quoted string with escaped single quote", () => { | ||
it('matches single quoted string with escaped single quote', () => { | ||
assert.deepStrictEqual( | ||
match("three {string} mice", "three 'bl\\'nd' mice"), | ||
match('three {string} mice', "three 'bl\\'nd' mice"), | ||
["bl'nd"] | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches escaped parenthesis", () => { | ||
it('matches escaped parenthesis', () => { | ||
assert.deepStrictEqual( | ||
match( | ||
"three \\(exceptionally) {string} mice", | ||
'three \\(exceptionally) {string} mice', | ||
'three (exceptionally) "blind" mice' | ||
), | ||
["blind"] | ||
); | ||
}); | ||
['blind'] | ||
) | ||
}) | ||
it("matches escaped slash", () => { | ||
assert.deepStrictEqual(match("12\\/2020", "12/2020"), []); | ||
}); | ||
it('matches escaped slash', () => { | ||
assert.deepStrictEqual(match('12\\/2020', '12/2020'), []) | ||
}) | ||
it("matches int", () => { | ||
assert.deepStrictEqual(match("{int}", "22"), [22]); | ||
}); | ||
it('matches int', () => { | ||
assert.deepStrictEqual(match('{int}', '22'), [22]) | ||
}) | ||
it("doesn't match float as int", () => { | ||
assert.deepStrictEqual(match("{int}", "1.22"), null); | ||
}); | ||
assert.deepStrictEqual(match('{int}', '1.22'), null) | ||
}) | ||
it("matches float", () => { | ||
assert.deepStrictEqual(match("{float}", "0.22"), [0.22]); | ||
assert.deepStrictEqual(match("{float}", ".22"), [0.22]); | ||
}); | ||
it('matches float', () => { | ||
assert.deepStrictEqual(match('{float}', '0.22'), [0.22]) | ||
assert.deepStrictEqual(match('{float}', '.22'), [0.22]) | ||
}) | ||
it("matches anonymous", () => { | ||
assert.deepStrictEqual(match("{}", "0.22"), ["0.22"]); | ||
}); | ||
it('matches anonymous', () => { | ||
assert.deepStrictEqual(match('{}', '0.22'), ['0.22']) | ||
}) | ||
it("throws unknown parameter type", () => { | ||
it('throws unknown parameter type', () => { | ||
try { | ||
match("{unknown}", "something"); | ||
assert.fail(); | ||
match('{unknown}', 'something') | ||
assert.fail() | ||
} catch (expected) { | ||
assert.strictEqual( | ||
expected.message, | ||
"Undefined parameter type {unknown}" | ||
); | ||
assert.strictEqual(expected.message, 'Undefined parameter type {unknown}') | ||
} | ||
}); | ||
}) | ||
it("does not allow optional parameter types", () => { | ||
it('does not allow optional parameter types', () => { | ||
try { | ||
match("({int})", "3"); | ||
assert.fail(); | ||
match('({int})', '3') | ||
assert.fail() | ||
} catch (expected) { | ||
assert.strictEqual( | ||
expected.message, | ||
"Parameter types cannot be optional: ({int})" | ||
); | ||
'Parameter types cannot be optional: ({int})' | ||
) | ||
} | ||
}); | ||
}) | ||
it("allows escaped optional parameter types", () => { | ||
assert.deepStrictEqual(match("\\({int})", "(3)"), [3]); | ||
}); | ||
it('allows escaped optional parameter types', () => { | ||
assert.deepStrictEqual(match('\\({int})', '(3)'), [3]) | ||
}) | ||
it("does not allow text/parameter type alternation", () => { | ||
it('does not allow text/parameter type alternation', () => { | ||
try { | ||
match("x/{int}", "3"); | ||
assert.fail(); | ||
match('x/{int}', '3') | ||
assert.fail() | ||
} catch (expected) { | ||
assert.strictEqual( | ||
expected.message, | ||
"Parameter types cannot be alternative: x/{int}" | ||
); | ||
'Parameter types cannot be alternative: x/{int}' | ||
) | ||
} | ||
}); | ||
}) | ||
it("does not allow parameter type/text alternation", () => { | ||
it('does not allow parameter type/text alternation', () => { | ||
try { | ||
match("{int}/x", "3"); | ||
assert.fail(); | ||
match('{int}/x', '3') | ||
assert.fail() | ||
} catch (expected) { | ||
assert.strictEqual( | ||
expected.message, | ||
"Parameter types cannot be alternative: {int}/x" | ||
); | ||
'Parameter types cannot be alternative: {int}/x' | ||
) | ||
} | ||
}); | ||
}) | ||
for (const c of "[]()$.|?*+".split("")) { | ||
for (const c of '[]()$.|?*+'.split('')) { | ||
it(`does not allow parameter type with ${c}`, () => { | ||
try { | ||
match(`{${c}string}`, "something"); | ||
assert.fail(); | ||
match(`{${c}string}`, 'something') | ||
assert.fail() | ||
} catch (expected) { | ||
@@ -190,26 +187,26 @@ assert.strictEqual( | ||
`Illegal character '${c}' in parameter name {${c}string}` | ||
); | ||
) | ||
} | ||
}); | ||
}) | ||
} | ||
it("exposes source", () => { | ||
const expr = "I have {int} cuke(s)"; | ||
it('exposes source', () => { | ||
const expr = 'I have {int} cuke(s)' | ||
assert.strictEqual( | ||
new CucumberExpression(expr, new ParameterTypeRegistry()).source, | ||
expr | ||
); | ||
}); | ||
) | ||
}) | ||
// JavaScript-specific | ||
it("delegates transform to custom object", () => { | ||
const parameterTypeRegistry = new ParameterTypeRegistry(); | ||
it('delegates transform to custom object', () => { | ||
const parameterTypeRegistry = new ParameterTypeRegistry() | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"widget", | ||
'widget', | ||
/\w+/, | ||
null, | ||
function(s: string) { | ||
return this.createWidget(s); | ||
return this.createWidget(s) | ||
}, | ||
@@ -219,55 +216,55 @@ false, | ||
) | ||
); | ||
) | ||
const expression = new CucumberExpression( | ||
"I have a {widget}", | ||
'I have a {widget}', | ||
parameterTypeRegistry | ||
); | ||
) | ||
const world = { | ||
createWidget(s: string) { | ||
return `widget:${s}`; | ||
} | ||
}; | ||
return `widget:${s}` | ||
}, | ||
} | ||
const args = expression.match(`I have a bolt`); | ||
assert.strictEqual(args[0].getValue(world), "widget:bolt"); | ||
}); | ||
const args = expression.match(`I have a bolt`) | ||
assert.strictEqual(args[0].getValue(world), 'widget:bolt') | ||
}) | ||
describe("escapes special characters", () => { | ||
["\\", "[", "]", "^", "$", ".", "|", "?", "*", "+"].forEach(character => { | ||
describe('escapes special characters', () => { | ||
;['\\', '[', ']', '^', '$', '.', '|', '?', '*', '+'].forEach(character => { | ||
it(`escapes ${character}`, () => { | ||
const expr = `I have {int} cuke(s) and ${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.strictEqual(arg1.getValue(null), 800); | ||
}); | ||
}); | ||
) | ||
const arg1 = expression.match(`I have 800 cukes and ${character}`)[0] | ||
assert.strictEqual(arg1.getValue(null), 800) | ||
}) | ||
}) | ||
it(`escapes .`, () => { | ||
const expr = `I have {int} cuke(s) and .`; | ||
const expr = `I have {int} cuke(s) and .` | ||
const expression = new CucumberExpression( | ||
expr, | ||
new ParameterTypeRegistry() | ||
); | ||
assert.strictEqual(expression.match(`I have 800 cukes and 3`), null); | ||
const arg1 = expression.match(`I have 800 cukes and .`)[0]; | ||
assert.strictEqual(arg1.getValue(null), 800); | ||
}); | ||
) | ||
assert.strictEqual(expression.match(`I have 800 cukes and 3`), null) | ||
const arg1 = expression.match(`I have 800 cukes and .`)[0] | ||
assert.strictEqual(arg1.getValue(null), 800) | ||
}) | ||
it(`escapes |`, () => { | ||
const expr = `I have {int} cuke(s) and a|b`; | ||
const expr = `I have {int} cuke(s) and a|b` | ||
const expression = new CucumberExpression( | ||
expr, | ||
new ParameterTypeRegistry() | ||
); | ||
assert.strictEqual(expression.match(`I have 800 cukes and a`), null); | ||
assert.strictEqual(expression.match(`I have 800 cukes and b`), null); | ||
const arg1 = expression.match(`I have 800 cukes and a|b`)[0]; | ||
assert.strictEqual(arg1.getValue(null), 800); | ||
}); | ||
}); | ||
}); | ||
) | ||
assert.strictEqual(expression.match(`I have 800 cukes and a`), null) | ||
assert.strictEqual(expression.match(`I have 800 cukes and b`), null) | ||
const arg1 = expression.match(`I have 800 cukes and a|b`)[0] | ||
assert.strictEqual(arg1.getValue(null), 800) | ||
}) | ||
}) | ||
}) | ||
@@ -278,8 +275,8 @@ const match = (expression: string, text: string) => { | ||
new ParameterTypeRegistry() | ||
); | ||
const args = cucumberExpression.match(text); | ||
) | ||
const args = cucumberExpression.match(text) | ||
if (!args) { | ||
return null; | ||
return null | ||
} | ||
return args.map(arg => arg.getValue(null)); | ||
}; | ||
return args.map(arg => arg.getValue(null)) | ||
} |
@@ -1,9 +0,9 @@ | ||
"use strict"; | ||
'use strict' | ||
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"; | ||
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' | ||
@@ -20,7 +20,7 @@ class Color { | ||
describe("Custom parameter type", () => { | ||
let parameterTypeRegistry: ParameterTypeRegistry; | ||
describe('Custom parameter type', () => { | ||
let parameterTypeRegistry: ParameterTypeRegistry | ||
beforeEach(() => { | ||
parameterTypeRegistry = new ParameterTypeRegistry(); | ||
parameterTypeRegistry = new ParameterTypeRegistry() | ||
/* eslint-disable prettier/prettier */ | ||
@@ -30,3 +30,3 @@ /// [add-color-parameter-type] | ||
new ParameterType( | ||
"color", // name | ||
'color', // name | ||
/red|blue|yellow/, // regexp | ||
@@ -38,25 +38,25 @@ Color, // type | ||
) | ||
); | ||
) | ||
/// [add-color-parameter-type] | ||
/* eslint-enable prettier/prettier */ | ||
}); | ||
}) | ||
describe("CucumberExpression", () => { | ||
it("throws exception for illegal character in parameter name", () => { | ||
describe('CucumberExpression', () => { | ||
it('throws exception for illegal character in parameter name', () => { | ||
assertThrows( | ||
() => new ParameterType("[string]", /.*/, String, s => s, false, true), | ||
() => new ParameterType('[string]', /.*/, String, s => s, false, true), | ||
"Illegal character '[' in parameter name {[string]}" | ||
); | ||
}); | ||
) | ||
}) | ||
it("matches parameters with custom parameter type", () => { | ||
it('matches parameters with custom parameter type', () => { | ||
const expression = new CucumberExpression( | ||
"I have a {color} ball", | ||
'I have a {color} ball', | ||
parameterTypeRegistry | ||
); | ||
const value = expression.match("I have a red ball")[0].getValue(null); | ||
assert.strictEqual(value.name, "red"); | ||
}); | ||
) | ||
const value = expression.match('I have a red ball')[0].getValue(null) | ||
assert.strictEqual(value.name, 'red') | ||
}) | ||
it("matches parameters with multiple capture groups", () => { | ||
it('matches parameters with multiple capture groups', () => { | ||
class Coordinate { | ||
@@ -72,3 +72,3 @@ constructor( | ||
new ParameterType( | ||
"coordinate", | ||
'coordinate', | ||
/(\d+),\s*(\d+),\s*(\d+)/, | ||
@@ -81,28 +81,28 @@ Coordinate, | ||
) | ||
); | ||
) | ||
const expression = new CucumberExpression( | ||
"A {int} thick line from {coordinate} to {coordinate}", | ||
'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 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 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 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); | ||
}); | ||
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(); | ||
it('matches parameters with custom parameter type using optional capture group', () => { | ||
parameterTypeRegistry = new ParameterTypeRegistry() | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"color", | ||
'color', | ||
[/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/], | ||
@@ -114,21 +114,19 @@ Color, | ||
) | ||
); | ||
) | ||
const expression = new CucumberExpression( | ||
"I have a {color} ball", | ||
'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"); | ||
}); | ||
) | ||
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", () => { | ||
it('defers transformation until queried from argument', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"throwing", | ||
'throwing', | ||
/bad/, | ||
null, | ||
s => { | ||
throw new Error(`Can't transform [${s}]`); | ||
throw new Error(`Can't transform [${s}]`) | ||
}, | ||
@@ -138,14 +136,14 @@ false, | ||
) | ||
); | ||
) | ||
const expression = new CucumberExpression( | ||
"I have a {throwing} parameter", | ||
'I have a {throwing} parameter', | ||
parameterTypeRegistry | ||
); | ||
const args = expression.match("I have a bad parameter"); | ||
assertThrows(() => args[0].getValue(null), "Can't transform [bad]"); | ||
}); | ||
) | ||
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", () => { | ||
describe('conflicting parameter type', () => { | ||
it('is detected for type name', () => { | ||
assertThrows( | ||
@@ -155,3 +153,3 @@ () => | ||
new ParameterType( | ||
"color", | ||
'color', | ||
/.*/, | ||
@@ -164,10 +162,10 @@ CssColor, | ||
), | ||
"There is already a parameter type with name color" | ||
); | ||
}); | ||
'There is already a parameter type with name color' | ||
) | ||
}) | ||
it("is not detected for type", () => { | ||
it('is not detected for type', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"whatever", | ||
'whatever', | ||
/.*/, | ||
@@ -179,9 +177,9 @@ Color, | ||
) | ||
); | ||
}); | ||
) | ||
}) | ||
it("is not detected for regexp", () => { | ||
it('is not detected for regexp', () => { | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"css-color", | ||
'css-color', | ||
/red|blue|yellow/, | ||
@@ -193,44 +191,44 @@ CssColor, | ||
) | ||
); | ||
) | ||
assert.strictEqual( | ||
new CucumberExpression( | ||
"I have a {css-color} ball", | ||
'I have a {css-color} ball', | ||
parameterTypeRegistry | ||
) | ||
.match("I have a blue ball")[0] | ||
.match('I have a blue ball')[0] | ||
.getValue(null).constructor, | ||
CssColor | ||
); | ||
) | ||
assert.strictEqual( | ||
new CucumberExpression( | ||
"I have a {css-color} ball", | ||
'I have a {css-color} ball', | ||
parameterTypeRegistry | ||
) | ||
.match("I have a blue ball")[0] | ||
.match('I have a blue ball')[0] | ||
.getValue(null).name, | ||
"blue" | ||
); | ||
'blue' | ||
) | ||
assert.strictEqual( | ||
new CucumberExpression("I have a {color} ball", parameterTypeRegistry) | ||
.match("I have a blue ball")[0] | ||
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] | ||
new CucumberExpression('I have a {color} ball', parameterTypeRegistry) | ||
.match('I have a blue ball')[0] | ||
.getValue(null).name, | ||
"blue" | ||
); | ||
}); | ||
}); | ||
'blue' | ||
) | ||
}) | ||
}) | ||
// JavaScript-specific | ||
it("creates arguments using async transform", async () => { | ||
parameterTypeRegistry = new ParameterTypeRegistry(); | ||
it('creates arguments using async transform', async () => { | ||
parameterTypeRegistry = new ParameterTypeRegistry() | ||
/// [add-async-parameter-type] | ||
parameterTypeRegistry.defineParameterType( | ||
new ParameterType( | ||
"asyncColor", | ||
'asyncColor', | ||
/red|blue|yellow/, | ||
@@ -242,26 +240,26 @@ Color, | ||
) | ||
); | ||
) | ||
/// [add-async-parameter-type] | ||
const expression = new CucumberExpression( | ||
"I have a {asyncColor} ball", | ||
'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"); | ||
}); | ||
}); | ||
) | ||
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", () => { | ||
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"); | ||
}); | ||
}); | ||
}); | ||
) | ||
const value = expression.match('I have a red ball')[0].getValue(null) | ||
assert.strictEqual(value.constructor, Color) | ||
assert.strictEqual(value.name, 'red') | ||
}) | ||
}) | ||
}) |
@@ -1,24 +0,24 @@ | ||
import fs from "fs"; | ||
import assert from "assert"; | ||
import CucumberExpression from "../src/CucumberExpression"; | ||
import RegularExpression from "../src/RegularExpression"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import fs from 'fs' | ||
import assert from 'assert' | ||
import CucumberExpression from '../src/CucumberExpression' | ||
import RegularExpression from '../src/RegularExpression' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
describe("examples.txt", () => { | ||
describe('examples.txt', () => { | ||
const match = (expressionText: string, text: string) => { | ||
const m = /\/(.*)\//.exec(expressionText); | ||
const m = /\/(.*)\//.exec(expressionText) | ||
const expression = m | ||
? new RegularExpression(new RegExp(m[1]), new ParameterTypeRegistry()) | ||
: new CucumberExpression(expressionText, new ParameterTypeRegistry()); | ||
const args = expression.match(text); | ||
: new CucumberExpression(expressionText, new ParameterTypeRegistry()) | ||
const args = expression.match(text) | ||
if (!args) { | ||
return null; | ||
return null | ||
} | ||
return args.map(arg => arg.getValue(null)); | ||
}; | ||
return args.map(arg => arg.getValue(null)) | ||
} | ||
const examples = fs.readFileSync("examples.txt", "utf-8"); | ||
const chunks = examples.split(/^---/m); | ||
const examples = fs.readFileSync('examples.txt', 'utf-8') | ||
const chunks = examples.split(/^---/m) | ||
for (const chunk of chunks) { | ||
const [expressionText, text, expectedArgs] = chunk.trim().split(/\n/m); | ||
const [expressionText, text, expectedArgs] = chunk.trim().split(/\n/m) | ||
it(`Works with: ${expressionText}`, () => { | ||
@@ -28,5 +28,5 @@ assert.deepStrictEqual( | ||
expectedArgs | ||
); | ||
}); | ||
) | ||
}) | ||
} | ||
}); | ||
}) |
@@ -1,4 +0,4 @@ | ||
import assert from "assert"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import ParameterType from "../src/ParameterType"; | ||
import assert from 'assert' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
import ParameterType from '../src/ParameterType' | ||
@@ -15,14 +15,14 @@ class Name { | ||
const CAPITALISED_WORD = /[A-Z]+\w+/; | ||
const CAPITALISED_WORD = /[A-Z]+\w+/ | ||
describe("ParameterTypeRegistry", () => { | ||
let registry: ParameterTypeRegistry; | ||
describe('ParameterTypeRegistry', () => { | ||
let registry: ParameterTypeRegistry | ||
beforeEach(() => { | ||
registry = new ParameterTypeRegistry(); | ||
}); | ||
registry = new ParameterTypeRegistry() | ||
}) | ||
it("does not allow more than one preferential parameter type for each regexp", () => { | ||
it('does not allow more than one preferential parameter type for each regexp', () => { | ||
registry.defineParameterType( | ||
new ParameterType( | ||
"name", | ||
'name', | ||
CAPITALISED_WORD, | ||
@@ -34,6 +34,6 @@ Name, | ||
) | ||
); | ||
) | ||
registry.defineParameterType( | ||
new ParameterType( | ||
"person", | ||
'person', | ||
CAPITALISED_WORD, | ||
@@ -45,7 +45,7 @@ Person, | ||
) | ||
); | ||
) | ||
try { | ||
registry.defineParameterType( | ||
new ParameterType( | ||
"place", | ||
'place', | ||
CAPITALISED_WORD, | ||
@@ -57,4 +57,4 @@ Place, | ||
) | ||
); | ||
throw new Error("Should have failed"); | ||
) | ||
throw new Error('Should have failed') | ||
} catch (err) { | ||
@@ -64,9 +64,9 @@ assert.strictEqual( | ||
`There can only be one preferential parameter type per regexp. The regexp ${CAPITALISED_WORD} is used for two preferential parameter types, {name} and {place}` | ||
); | ||
) | ||
} | ||
}); | ||
}) | ||
it("looks up preferential parameter type by regexp", () => { | ||
it('looks up preferential parameter type by regexp', () => { | ||
const name = new ParameterType( | ||
"name", | ||
'name', | ||
/[A-Z]+\w+/, | ||
@@ -77,5 +77,5 @@ null, | ||
false | ||
); | ||
) | ||
const person = new ParameterType( | ||
"person", | ||
'person', | ||
/[A-Z]+\w+/, | ||
@@ -86,5 +86,5 @@ null, | ||
true | ||
); | ||
) | ||
const place = new ParameterType( | ||
"place", | ||
'place', | ||
/[A-Z]+\w+/, | ||
@@ -95,17 +95,17 @@ null, | ||
false | ||
); | ||
) | ||
registry.defineParameterType(name); | ||
registry.defineParameterType(person); | ||
registry.defineParameterType(place); | ||
registry.defineParameterType(name) | ||
registry.defineParameterType(person) | ||
registry.defineParameterType(place) | ||
assert.strictEqual( | ||
registry.lookupByRegexp( | ||
"[A-Z]+\\w+", | ||
'[A-Z]+\\w+', | ||
/([A-Z]+\w+) and ([A-Z]+\w+)/, | ||
"Lisa and Bob" | ||
'Lisa and Bob' | ||
), | ||
person | ||
); | ||
}); | ||
}); | ||
) | ||
}) | ||
}) |
@@ -1,10 +0,10 @@ | ||
import assertThrows from "./assert_throws"; | ||
import ParameterType from "../src/ParameterType"; | ||
import assertThrows from './assert_throws' | ||
import ParameterType from '../src/ParameterType' | ||
describe("ParameterType", () => { | ||
it("does not allow ignore flag on regexp", () => { | ||
describe('ParameterType', () => { | ||
it('does not allow ignore flag on regexp', () => { | ||
assertThrows( | ||
() => | ||
new ParameterType( | ||
"case-insensitive", | ||
'case-insensitive', | ||
/[a-z]+/i, | ||
@@ -17,4 +17,4 @@ String, | ||
"ParameterType Regexps can't use flag 'i'" | ||
); | ||
}); | ||
}); | ||
) | ||
}) | ||
}) |
@@ -1,115 +0,115 @@ | ||
import assert from "assert"; | ||
import RegularExpression from "../src/RegularExpression"; | ||
import ParameterTypeRegistry from "../src/ParameterTypeRegistry"; | ||
import assert from 'assert' | ||
import RegularExpression from '../src/RegularExpression' | ||
import ParameterTypeRegistry from '../src/ParameterTypeRegistry' | ||
describe("RegularExpression", () => { | ||
it("documents match arguments", () => { | ||
const parameterRegistry = new ParameterTypeRegistry(); | ||
describe('RegularExpression', () => { | ||
it('documents match arguments', () => { | ||
const parameterRegistry = new ParameterTypeRegistry() | ||
/// [capture-match-arguments] | ||
const expr = /I have (\d+) cukes? in my (\w+) now/; | ||
const expression = new RegularExpression(expr, parameterRegistry); | ||
const args = expression.match("I have 7 cukes in my belly now"); | ||
assert.strictEqual(7, args[0].getValue(null)); | ||
assert.strictEqual("belly", args[1].getValue(null)); | ||
const expr = /I have (\d+) cukes? in my (\w+) now/ | ||
const expression = new RegularExpression(expr, parameterRegistry) | ||
const args = expression.match('I have 7 cukes in my belly now') | ||
assert.strictEqual(7, args[0].getValue(null)) | ||
assert.strictEqual('belly', args[1].getValue(null)) | ||
/// [capture-match-arguments] | ||
}); | ||
}) | ||
it("does no transform by default", () => { | ||
assert.deepStrictEqual(match(/(\d\d)/, "22")[0], "22"); | ||
}); | ||
it('does no transform by default', () => { | ||
assert.deepStrictEqual(match(/(\d\d)/, '22')[0], '22') | ||
}) | ||
it("does not transform anonymous", () => { | ||
assert.deepStrictEqual(match(/(.*)/, "22")[0], "22"); | ||
}); | ||
it('does not transform anonymous', () => { | ||
assert.deepStrictEqual(match(/(.*)/, '22')[0], '22') | ||
}) | ||
it("transforms negative int", () => { | ||
assert.deepStrictEqual(match(/(-?\d+)/, "-22")[0], -22); | ||
}); | ||
it('transforms negative int', () => { | ||
assert.deepStrictEqual(match(/(-?\d+)/, '-22')[0], -22) | ||
}) | ||
it("transforms positive int", () => { | ||
assert.deepStrictEqual(match(/(\d+)/, "22")[0], 22); | ||
}); | ||
it('transforms positive int', () => { | ||
assert.deepStrictEqual(match(/(\d+)/, '22')[0], 22) | ||
}) | ||
it("transforms float without integer part", () => { | ||
assert.deepStrictEqual(match(/(-?\d*\.?\d+)/, ".22")[0], 0.22); | ||
}); | ||
it('transforms float without integer part', () => { | ||
assert.deepStrictEqual(match(/(-?\d*\.?\d+)/, '.22')[0], 0.22) | ||
}) | ||
it("transforms float with sign", () => { | ||
assert.deepStrictEqual(match(/(-?\d*\.?\d+)/, "-1.22")[0], -1.22); | ||
}); | ||
it('transforms float with sign', () => { | ||
assert.deepStrictEqual(match(/(-?\d*\.?\d+)/, '-1.22')[0], -1.22) | ||
}) | ||
it("returns null when there is no match", () => { | ||
assert.strictEqual(match(/hello/, "world"), null); | ||
}); | ||
it('returns null when there is no match', () => { | ||
assert.strictEqual(match(/hello/, 'world'), null) | ||
}) | ||
it("matches nested capture group without match", () => { | ||
assert.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, "a user"), [ | ||
null | ||
]); | ||
}); | ||
it('matches nested capture group without match', () => { | ||
assert.deepStrictEqual(match(/^a user( named "([^"]*)")?$/, 'a user'), [ | ||
null, | ||
]) | ||
}) | ||
it("matches nested capture group with match", () => { | ||
it('matches nested capture group with match', () => { | ||
assert.deepStrictEqual( | ||
match(/^a user( named "([^"]*)")?$/, 'a user named "Charlie"'), | ||
["Charlie"] | ||
); | ||
}); | ||
['Charlie'] | ||
) | ||
}) | ||
it("matches capture group nested in optional one", () => { | ||
const regexp = /^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/; | ||
assert.deepStrictEqual(match(regexp, "a purchase"), [null, null]); | ||
assert.deepStrictEqual(match(regexp, "a purchase for $33"), [null, 33]); | ||
assert.deepStrictEqual(match(regexp, "a pre buyer fee model purchase"), [ | ||
"pre buyer fee model ", | ||
null | ||
]); | ||
}); | ||
it('matches capture group nested in optional one', () => { | ||
const regexp = /^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/ | ||
assert.deepStrictEqual(match(regexp, 'a purchase'), [null, null]) | ||
assert.deepStrictEqual(match(regexp, 'a purchase for $33'), [null, 33]) | ||
assert.deepStrictEqual(match(regexp, 'a pre buyer fee model purchase'), [ | ||
'pre buyer fee model ', | ||
null, | ||
]) | ||
}) | ||
it("ignores non capturing groups", () => { | ||
it('ignores non capturing groups', () => { | ||
assert.deepStrictEqual( | ||
match( | ||
/(\S+) ?(can|cannot)? (?:delete|cancel) the (\d+)(?:st|nd|rd|th) (attachment|slide) ?(?:upload)?/, | ||
"I can cancel the 1st slide upload" | ||
'I can cancel the 1st slide upload' | ||
), | ||
["I", "can", 1, "slide"] | ||
); | ||
}); | ||
['I', 'can', 1, 'slide'] | ||
) | ||
}) | ||
it("works with escaped parenthesis", () => { | ||
it('works with escaped parenthesis', () => { | ||
assert.deepStrictEqual( | ||
match(/Across the line\(s\)/, "Across the line(s)"), | ||
match(/Across the line\(s\)/, 'Across the line(s)'), | ||
[] | ||
); | ||
}); | ||
) | ||
}) | ||
it("exposes regexp and source", () => { | ||
const regexp = /I have (\d+) cukes? in my (.+) now/; | ||
it('exposes regexp and source', () => { | ||
const regexp = /I have (\d+) cukes? in my (.+) now/ | ||
const expression = new RegularExpression( | ||
regexp, | ||
new ParameterTypeRegistry() | ||
); | ||
assert.deepStrictEqual(expression.regexp, regexp); | ||
assert.deepStrictEqual(expression.source, regexp.source); | ||
}); | ||
) | ||
assert.deepStrictEqual(expression.regexp, regexp) | ||
assert.deepStrictEqual(expression.source, regexp.source) | ||
}) | ||
it("does not take consider parenthesis in character class as group", function() { | ||
it('does not take consider parenthesis in character class as group', function() { | ||
const expression = new RegularExpression( | ||
/^drawings: ([A-Z_, ()]+)$/, | ||
new ParameterTypeRegistry() | ||
); | ||
const args = expression.match("drawings: ONE, TWO(ABC)"); | ||
) | ||
const args = expression.match('drawings: ONE, TWO(ABC)') | ||
assert.strictEqual(args[0].getValue(this), "ONE, TWO(ABC)"); | ||
}); | ||
}); | ||
assert.strictEqual(args[0].getValue(this), 'ONE, TWO(ABC)') | ||
}) | ||
}) | ||
const match = (regexp: RegExp, text: string) => { | ||
const parameterRegistry = new ParameterTypeRegistry(); | ||
const regularExpression = new RegularExpression(regexp, parameterRegistry); | ||
const args = regularExpression.match(text); | ||
const parameterRegistry = new ParameterTypeRegistry() | ||
const regularExpression = new RegularExpression(regexp, parameterRegistry) | ||
const args = regularExpression.match(text) | ||
if (!args) { | ||
return null; | ||
return null | ||
} | ||
return args.map(arg => arg.getValue(null)); | ||
}; | ||
return args.map(arg => arg.getValue(null)) | ||
} |
@@ -1,99 +0,99 @@ | ||
import assert from "assert"; | ||
import TreeRegexp from "../src/TreeRegexp"; | ||
import assert from 'assert' | ||
import TreeRegexp from '../src/TreeRegexp' | ||
describe("TreeRegexp", () => { | ||
it("exposes group source", () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/); | ||
describe('TreeRegexp', () => { | ||
it('exposes group source', () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/) | ||
assert.deepStrictEqual(tr.groupBuilder.children.map(gb => gb.source), [ | ||
"a(?:b)?", | ||
"c" | ||
]); | ||
}); | ||
'a(?:b)?', | ||
'c', | ||
]) | ||
}) | ||
it("builds tree", () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/); | ||
const group = tr.match("ac"); | ||
assert.strictEqual(group.value, "ac"); | ||
assert.strictEqual(group.children[0].value, "a"); | ||
assert.deepStrictEqual(group.children[0].children, []); | ||
assert.strictEqual(group.children[1].value, "c"); | ||
}); | ||
it('builds tree', () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/) | ||
const group = tr.match('ac') | ||
assert.strictEqual(group.value, 'ac') | ||
assert.strictEqual(group.children[0].value, 'a') | ||
assert.deepStrictEqual(group.children[0].children, []) | ||
assert.strictEqual(group.children[1].value, 'c') | ||
}) | ||
it("ignores non-capturing groups", () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/); | ||
const group = tr.match("ac"); | ||
assert.strictEqual(group.value, "ac"); | ||
assert.strictEqual(group.children[0].value, "a"); | ||
assert.deepStrictEqual(group.children[0].children, []); | ||
assert.strictEqual(group.children[1].value, "c"); | ||
}); | ||
it('ignores non-capturing groups', () => { | ||
const tr = new TreeRegexp(/(a(?:b)?)(c)/) | ||
const group = tr.match('ac') | ||
assert.strictEqual(group.value, 'ac') | ||
assert.strictEqual(group.children[0].value, 'a') | ||
assert.deepStrictEqual(group.children[0].children, []) | ||
assert.strictEqual(group.children[1].value, 'c') | ||
}) | ||
it("matches optional group", () => { | ||
const tr = new TreeRegexp(/^Something( with an optional argument)?/); | ||
const group = tr.match("Something"); | ||
assert.strictEqual(group.children[0].value, null); | ||
}); | ||
it('matches optional group', () => { | ||
const tr = new TreeRegexp(/^Something( with an optional argument)?/) | ||
const group = tr.match('Something') | ||
assert.strictEqual(group.children[0].value, null) | ||
}) | ||
it("matches nested groups", () => { | ||
it('matches nested groups', () => { | ||
const tr = new TreeRegexp( | ||
/^A (\d+) thick line from ((\d+),\s*(\d+),\s*(\d+)) to ((\d+),\s*(\d+),\s*(\d+))/ | ||
); | ||
const group = tr.match("A 5 thick line from 10,20,30 to 40,50,60"); | ||
) | ||
const group = tr.match('A 5 thick line from 10,20,30 to 40,50,60') | ||
assert.strictEqual(group.children[0].value, "5"); | ||
assert.strictEqual(group.children[1].value, "10,20,30"); | ||
assert.strictEqual(group.children[1].children[0].value, "10"); | ||
assert.strictEqual(group.children[1].children[1].value, "20"); | ||
assert.strictEqual(group.children[1].children[2].value, "30"); | ||
assert.strictEqual(group.children[2].value, "40,50,60"); | ||
assert.strictEqual(group.children[2].children[0].value, "40"); | ||
assert.strictEqual(group.children[2].children[1].value, "50"); | ||
assert.strictEqual(group.children[2].children[2].value, "60"); | ||
}); | ||
assert.strictEqual(group.children[0].value, '5') | ||
assert.strictEqual(group.children[1].value, '10,20,30') | ||
assert.strictEqual(group.children[1].children[0].value, '10') | ||
assert.strictEqual(group.children[1].children[1].value, '20') | ||
assert.strictEqual(group.children[1].children[2].value, '30') | ||
assert.strictEqual(group.children[2].value, '40,50,60') | ||
assert.strictEqual(group.children[2].children[0].value, '40') | ||
assert.strictEqual(group.children[2].children[1].value, '50') | ||
assert.strictEqual(group.children[2].children[2].value, '60') | ||
}) | ||
it("detects multiple non capturing groups", () => { | ||
const tr = new TreeRegexp(/(?:a)(:b)(\?c)(d)/); | ||
const group = tr.match("a:b?cd"); | ||
assert.strictEqual(group.children.length, 3); | ||
}); | ||
it('detects multiple non capturing groups', () => { | ||
const tr = new TreeRegexp(/(?:a)(:b)(\?c)(d)/) | ||
const group = tr.match('a:b?cd') | ||
assert.strictEqual(group.children.length, 3) | ||
}) | ||
it("works with escaped backslash", () => { | ||
const tr = new TreeRegexp(/foo\\(bar|baz)/); | ||
const group = tr.match("foo\\bar"); | ||
assert.strictEqual(group.children.length, 1); | ||
}); | ||
it('works with escaped backslash', () => { | ||
const tr = new TreeRegexp(/foo\\(bar|baz)/) | ||
const group = tr.match('foo\\bar') | ||
assert.strictEqual(group.children.length, 1) | ||
}) | ||
it("works with escaped slash", () => { | ||
const tr = new TreeRegexp(/^I go to '\/(.+)'$/); | ||
const group = tr.match("I go to '/hello'"); | ||
assert.strictEqual(group.children.length, 1); | ||
}); | ||
it('works with escaped slash', () => { | ||
const tr = new TreeRegexp(/^I go to '\/(.+)'$/) | ||
const group = tr.match("I go to '/hello'") | ||
assert.strictEqual(group.children.length, 1) | ||
}) | ||
it("works with digit and word", () => { | ||
const tr = new TreeRegexp(/^(\d) (\w+)$/); | ||
const group = tr.match("2 you"); | ||
assert.strictEqual(group.children.length, 2); | ||
}); | ||
it('works with digit and word', () => { | ||
const tr = new TreeRegexp(/^(\d) (\w+)$/) | ||
const group = tr.match('2 you') | ||
assert.strictEqual(group.children.length, 2) | ||
}) | ||
it("captures non capturing groups with capturing groups inside", () => { | ||
const tr = new TreeRegexp('the stdout(?: from "(.*?)")?'); | ||
const group = tr.match("the stdout"); | ||
assert.strictEqual(group.value, "the stdout"); | ||
assert.strictEqual(group.children[0].value, null); | ||
assert.strictEqual(group.children.length, 1); | ||
}); | ||
it('captures non capturing groups with capturing groups inside', () => { | ||
const tr = new TreeRegexp('the stdout(?: from "(.*?)")?') | ||
const group = tr.match('the stdout') | ||
assert.strictEqual(group.value, 'the stdout') | ||
assert.strictEqual(group.children[0].value, null) | ||
assert.strictEqual(group.children.length, 1) | ||
}) | ||
it("works with flags", () => { | ||
const tr = new TreeRegexp(/HELLO/i); | ||
const group = tr.match("hello"); | ||
assert.strictEqual(group.value, "hello"); | ||
}); | ||
it('works with flags', () => { | ||
const tr = new TreeRegexp(/HELLO/i) | ||
const group = tr.match('hello') | ||
assert.strictEqual(group.value, 'hello') | ||
}) | ||
it("does not consider parenthesis in character class as group", () => { | ||
const tr = new TreeRegexp(/^drawings: ([A-Z, ()]+)$/); | ||
const group = tr.match("drawings: ONE(TWO)"); | ||
assert.strictEqual(group.value, "drawings: ONE(TWO)"); | ||
assert.strictEqual(group.children.length, 1); | ||
assert.strictEqual(group.children[0].value, "ONE(TWO)"); | ||
}); | ||
}); | ||
it('does not consider parenthesis in character class as group', () => { | ||
const tr = new TreeRegexp(/^drawings: ([A-Z, ()]+)$/) | ||
const group = tr.match('drawings: ONE(TWO)') | ||
assert.strictEqual(group.value, 'drawings: ONE(TWO)') | ||
assert.strictEqual(group.children.length, 1) | ||
assert.strictEqual(group.children[0].value, 'ONE(TWO)') | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
506011
155
3
6038