Skip to content

Instantly share code, notes, and snippets.

@jbpros
Last active May 25, 2021 10:17
Show Gist options
  • Save jbpros/8414fc60f4fd072c12f3 to your computer and use it in GitHub Desktop.
Save jbpros/8414fc60f4fd072c12f3 to your computer and use it in GitHub Desktop.
Cucumber.js step definition transforms
# features/my.feature
Feature:
Scenario: cukes
Given I have 10 cucumbers in my BaG
Given I don't have 20 cucumbers in my bAg
Given I have 98775655 cucumbers in my bag
// features/step_definitions/stepdefs.js
var transform = require('./support/transform.js');
module.exports = function () {
this.Transform(/^(\d+)$/, function (matches) { return parseInt(matches[0]); });
this.Transform(/^(have|don't have)$/, function (matches) { return matches[0] == 'have'; });
this.Transform(/^([bB][aA][gG])$/, function () { return 'bag'; });
this.Given(/^I (have|don't have) (\d+) cucumbers in my (.*)$/, function (has, count, where) {
console.log('Given...', has, typeof count, where)
});
}
// features/support/transform.js
var transforms = [];
function cast(value) {
for (var i = 0; i < transforms.length; i++) {
var transform = transforms[i];
var matches = transform.pattern.exec(value);
if (matches) {
return transform.fn(matches);
}
}
return value;
}
function t(fn) {
var args = [];
var body = 'var args = [];';
for (var i = 0; i < fn.length; i++) {
args.push('arg' + i);
body += 'args.push(this.cast(arg' + i + '));\n';
}
body += 'return this.fn.apply(this, args);';
var transformedFn = Function.apply(null, args.concat([body])).bind({fn: fn, cast: cast});
return transformedFn;
}
module.exports = function () {
var _defineStep = this.defineStep;
this.defineStep = function (pattern, fn) {
_defineStep(pattern, t(fn));
};
this.Given = this.When = this.Then = this.defineStep;
this.Transform = function (pattern, fn) {
transforms.push({ pattern: pattern, fn: fn });
};
}
@setthase
Copy link

setthase commented May 10, 2017

@robsquires - your solution was quite close, but you should do something like that:

Function.apply(null, args.concat([body])).bind(Object.assign({}, new this.World(), {fn: fn, cast: cast})

And just make sure that t function is called with the same scope from exported function. For example using ES6 you can do something like that:

  this.defineStep = (pattern, fn) => {
    _defineStep(pattern, t.call(this, fn));
  };

@pittgoose I also had same issue as you and to fix it I required transforms inside module.exports function, i.e.:

module.exports = function () {
  require('./support/transform').call(this);

  this.Transform(/^(\d+)$/, function (matches) {
    return parseInt(matches[0], 10);
  });
}

I know maybe it's late for you guys, but I got exactly same problem, so I would like to help others that will fall into same issues here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment