Skip to content
This repository was archived by the owner on May 28, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions lib/cucumber/sequential_test_case_executor.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
module.exports = function SequentialTestCaseExecutor(testCases) {
this.execute = function (eventEmitter) {
var all_passed = true;
for (var i=0 ; i<testCases.length ; i++) {
var testCase = testCases[i];
var passed = testCase.execute(eventEmitter);
all_passed = all_passed && passed;
}
return all_passed;

// This is essentially a for loop. If you think it looks weird it's
// because we're using JavaScript promises, which is a mechanism
// for running asynchronous code.
return testCases.reduce(function (promise, testCase) {
return promise.then(function () {
return testCase.execute(eventEmitter)
});
}, Promise.resolve());
//
// return testCases.reduce(function (promise, testCase) {
// return promise.then(function () {
// return testCase.execute(eventEmitter)
// });
// }, Promise.resolve());

};
};
38 changes: 23 additions & 15 deletions lib/cucumber/test_case.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,32 @@ module.exports = function TestCase(pickle, testSteps) {
pickleSteps: pickle.steps
});
var world = {};

return runTestStepsInSequence(testSteps, eventEmitter, world)
.then(function () {
eventEmitter.emit('scenario-finished', {
path: pickle.path,
location: location
});
});
};
runTestStepsInSequence(testSteps, eventEmitter, world);
eventEmitter.emit('scenario-finished', {
path: pickle.path,
location: location
}
);
}

function runTestStepsInSequence(testSteps, eventEmitter, world) {
var all_passed = true;
for (var i=0 ; i<testSteps.length; i++) {
var testStep = testSteps[i];
var run = all_passed;
var passed = testStep.execute(world, eventEmitter, run);
all_passed = all_passed && passed;
}
return all_passed

// This is essentially a for loop. If you think it looks weird it's
// because we're using JavaScript promises, which is a mechanism
// for running asynchronous code.
return testSteps.reduce(function (promise, testStep) {
return promise.then(function (run) {
return testStep.execute(world, eventEmitter, run)
})
}, Promise.resolve(true));
// return testSteps.reduce(function (promise, testStep) {
// return promise.then(function (run) {
// return testStep.execute(world, eventEmitter, run)
// })
// }, Promise.resolve(true));

}
};
};
89 changes: 46 additions & 43 deletions lib/cucumber/test_step.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
module.exports = function TestStep(gherkinLocations, matchedArguments, bodyFn, bodyLocation) {
this.execute = function (world, eventEmitter, run) {
eventEmitter.emit('step-started', {
status: 'unknown',
gherkinLocation: gherkinLocations[gherkinLocations.length - 1],
bodyLocation: bodyLocation,
matchedArguments: matchedArguments
});

// We're returning a promise of a boolean here, because JavaScript.
// Most languages should simply return a boolean and forget about
// the promise stuff - simpler!
return new Promise(function (resolve) {
if (!bodyFn) {
resolve({status: 'undefined'});
} else if (!run) {
resolve({status: 'skipped'});
} else {
var matchedArgumentValues = matchedArguments.map(function (arg) {
return arg.value
});
try {
// Execute the step definition body
var promise = bodyFn.apply(world, matchedArgumentValues);
// this object tracks the execution status as it goes
var data = {
status: 'unknown',
gherkinLocation: gherkinLocations[gherkinLocations.length - 1],
bodyLocation: bodyLocation,
matchedArguments: matchedArguments
}

// handles execution details
var _execute = function (world, data) {
var matchedArgumentValues = matchedArguments.map(
function (arg) {return arg.value}
);
try {
// Execute the step definition body
result = bodyFn.apply(world, matchedArgumentValues);
data.status = 'passed';
} catch (err) {
data.status = 'failed';
data.error = err;
} finally {
return data;
}
}

// main execution logic
//
// Overview:
// 1. startup
// 2. execution
// 3. completion
this.execute = function(world, eventEmitter, run) {
// 1. startup
eventEmitter.emit('step-started', data);

// 2. execution
if (!bodyFn) {
data.status = 'undefined';
} else if (!run) {
data.status = 'skipped';
} else {
data = _execute(world, data);
}

if (promise && typeof(promise.then) === 'function') {
// ok, it's a promise
promise.then(function () {
resolve({status: 'passed'});
}).catch(function (err) {
resolve({status: 'failed', error: err});
})
} else {
resolve({status: 'passed'});
}
} catch (err) {
resolve({status: 'failed', error: err});
}
}
}).then(function (event) {
event.gherkinLocation = gherkinLocations[gherkinLocations.length - 1];
event.bodyLocation = bodyLocation;
event.matchedArguments = matchedArguments;
eventEmitter.emit('step-finished', event);
return event.status === 'passed';
});
// 3. completion
eventEmitter.emit('step-finished', data);
return data.status === 'passed';
}
};
26 changes: 11 additions & 15 deletions test/cucumber/glue_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("Glue", function () {
return {
execute: function () {
executed = true;
return Promise.resolve();
return true;
}
};
}
Expand All @@ -31,9 +31,8 @@ describe("Glue", function () {
var testCase = glue.createTestCase(pickle);

assert(!executed);
return testCase.execute(new EventEmitter()).then(function () {
assert(executed);
});
testCase.execute(new EventEmitter());
assert(executed);
});

it("creates an undefined step when no stepdefs match", function () {
Expand All @@ -53,10 +52,8 @@ describe("Glue", function () {
assert.equal(step.status, 'undefined');
assert.deepEqual(step.gherkinLocation, {path: 'features/hello.feature', line: 3, column: 11});
});
return testCase.execute(eventEmitter)
.then(function () {
assert.ok(finished);
});
testCase.execute(eventEmitter);
assert(finished);
});

it("throws an exception when two stepdefs match", function () {
Expand Down Expand Up @@ -91,7 +88,7 @@ describe("Glue", function () {
return {
execute: function () {
result.push('step');
return Promise.resolve();
return true;
}
};
}
Expand All @@ -104,8 +101,8 @@ describe("Glue", function () {
createTestStep: function (pickle) {
return {
execute: function () {
result.push('before')
return Promise.resolve();
result.push('before');
return;
}
};
}
Expand All @@ -116,7 +113,7 @@ describe("Glue", function () {
return {
execute: function () {
result.push('after');
return Promise.resolve();
return;
}
};
}
Expand All @@ -127,9 +124,8 @@ describe("Glue", function () {
var testCase = glue.createTestCase(pickle);

assert.deepEqual(result, []);
return testCase.execute(new EventEmitter()).then(function () {
assert.deepEqual(result, ['before', 'step', 'after']);
});
testCase.execute(new EventEmitter());
assert.deepEqual(result, ['before', 'step', 'after']);
});
});
});
8 changes: 2 additions & 6 deletions test/cucumber/sequential_test_case_executor_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,17 @@ describe("Runtime", function () {
var tc1 = {
execute: function (eventEmitter) {
order.push(1);
return Promise.resolve();
}
};
var tc2 = {
execute: function (eventEmitter) {
order.push(2);
return Promise.resolve();
}
};

var runtime = new SequentialTestCaseExecutor([tc1, tc2]);
return runtime.execute(new EventEmitter())
.then(function () {
assert.deepEqual(order, [1, 2]);
});
runtime.execute(new EventEmitter())
assert.deepEqual(order, [1, 2]);
});
});
});
49 changes: 23 additions & 26 deletions test/cucumber/test_case_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,53 +10,51 @@ describe("TestCase", function () {
path: 'features/test.feature',
locations: []
};
var testCase = new TestCase(pickle, [
var testSteps = [
{
execute: function (world, eventEmitter, run) {
return Promise.resolve(true);
return true;
}
},
{
execute: function (world, eventEmitter, run) {
done = true;
assert(run);
return Promise.resolve(true);
assert(run === true);
return true;
}
}
]);
];
var testCase = new TestCase(pickle, testSteps);

return testCase.execute(new EventEmitter())
.then(function () {
assert(done);
});
testCase.execute(new EventEmitter());
assert(done === true);
});

it("uses the same this object across steps", function () {
it("uses the same 'this' object across steps", function () {
var done = false;
var pickle = {
path: 'features/test.feature',
locations: []
};
var testCase = new TestCase(pickle, [
var testSteps = [
{
execute: function (world, eventEmitter, run) {
world.bingo = 'yes';
return Promise.resolve(true);
return true;
}
},
{
execute: function (world, eventEmitter, run) {
done = true;
assert.equal(world.bingo, 'yes');
return Promise.resolve(true);
return true;
}
}
]);
];
var testCase = new TestCase(pickle, testSteps);

return testCase.execute(new EventEmitter())
.then(function () {
assert(done);
});
testCase.execute(new EventEmitter());
assert(done === true);
});

it("tells next step to not run when previous one failed", function () {
Expand All @@ -65,25 +63,24 @@ describe("TestCase", function () {
path: 'features/test.feature',
locations: []
};
var testCase = new TestCase(pickle, [
var testSteps = [
{
execute: function (world, eventEmitter, run) {
return Promise.resolve(false);
return false;
}
},
{
execute: function (world, eventEmitter, run) {
done = true;
assert(!run);
return Promise.resolve(false);
return false;
}
}
]);
];
var testCase = new TestCase(pickle, testSteps);

return testCase.execute(new EventEmitter())
.then(function () {
assert(done);
});
testCase.execute(new EventEmitter());
assert(done === true);
});
});
});
Loading