Skip to content
Merged
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
16 changes: 11 additions & 5 deletions lib/cucumber/listener.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ var Listener = function () {
},

buildHandlerNameForEvent: function buildHandlerNameForEvent(event) {
var handlerName =
Listener.EVENT_HANDLER_NAME_PREFIX +
event.getName() +
Listener.EVENT_HANDLER_NAME_SUFFIX;
return handlerName;
return self.buildHandlerName(event.getName());
},

getHandlerForEvent: function getHandlerForEvent(event) {
var eventHandlerName = self.buildHandlerNameForEvent(event);
return self[eventHandlerName];
},

buildHandlerName: function buildHandler(shortName) {
return Listener.EVENT_HANDLER_NAME_PREFIX + shortName + Listener.EVENT_HANDLER_NAME_SUFFIX;
},

setHandlerForEvent: function setHandlerForEvent(shortname, handler) {
var eventName = self.buildHandlerName(shortname);
self[eventName] = handler;
}
};
return self;
Expand All @@ -33,6 +38,7 @@ var Listener = function () {
Listener.EVENT_HANDLER_NAME_PREFIX = 'handle';
Listener.EVENT_HANDLER_NAME_SUFFIX = 'Event';

Listener.Events = require('./listener/events');
Listener.Formatter = require('./listener/formatter');
Listener.PrettyFormatter = require('./listener/pretty_formatter');
Listener.ProgressFormatter = require('./listener/progress_formatter');
Expand Down
10 changes: 10 additions & 0 deletions lib/cucumber/listener/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
exports['BeforeFeatures'] = 'BeforeFeatures';
exports['BeforeFeature'] = 'BeforeFeature';
exports['Background'] = 'Background';
exports['BeforeScenario'] = 'BeforeScenario';
exports['BeforeStep'] = 'BeforeStep';
exports['StepResult'] = 'StepResult';
exports['AfterStep'] = 'AfterStep';
exports['AfterScenario'] = 'AfterScenario';
exports['AfterFeature'] = 'AfterFeature';
exports['AfterFeatures'] = 'AfterFeatures';
18 changes: 13 additions & 5 deletions lib/cucumber/runtime/ast_tree_walker.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var AstTreeWalker = function(features, supportCodeLibrary, listeners) {
var Cucumber = require('../../cucumber');

var listeners;
var world;
var allFeaturesSucceded = true;
var skippingSteps = false;
Expand Down Expand Up @@ -107,10 +106,19 @@ var AstTreeWalker = function(features, supportCodeLibrary, listeners) {
},

broadcastEvent: function broadcastEvent(event, callback) {
listeners.forEach(
function(listener, callback) { listener.hear(event, callback); },
callback
);
broadcastToListners(listeners, onRuntimeListenersComplete);

function onRuntimeListenersComplete() {
var listeners = supportCodeLibrary.getListeners();
broadcastToListners(listeners, callback);
}

function broadcastToListners(listeners, callback) {
listeners.forEach(
function(listener, callback) { listener.hear(event, callback); },
callback
);
}
},

lookupStepDefinitionByName: function lookupStepDefinitionByName(stepName) {
Expand Down
54 changes: 46 additions & 8 deletions lib/cucumber/support_code/library.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var Library = function(supportCodeDefinition) {
var Cucumber = require('../../cucumber');

var listeners = Cucumber.Type.Collection();
var stepDefinitions = Cucumber.Type.Collection();
var hooker = Cucumber.SupportCode.Library.Hooker();
var worldConstructor = Cucumber.SupportCode.WorldConstructor();
Expand Down Expand Up @@ -50,6 +51,20 @@ var Library = function(supportCodeDefinition) {
stepDefinitions.add(stepDefinition);
},

registerListener: function registerListener(listener) {
listeners.add(listener);
},

registerHandler: function registerHandler(eventName, handler) {
var listener = Cucumber.Listener();
listener.setHandlerForEvent(eventName, handler);
self.registerListener(listener);
},

getListeners: function getListeners() {
return listeners;
},

instantiateNewWorld: function instantiateNewWorld(callback) {
var world = new worldConstructor(function(explicitWorld) {
process.nextTick(function() { // release the constructor
Expand All @@ -60,19 +75,42 @@ var Library = function(supportCodeDefinition) {
};

var supportCodeHelper = {
Around : self.defineAroundHook,
Before : self.defineBeforeHook,
After : self.defineAfterHook,
Given : self.defineStep,
When : self.defineStep,
Then : self.defineStep,
defineStep : self.defineStep,
World : worldConstructor
Around : self.defineAroundHook,
Before : self.defineBeforeHook,
After : self.defineAfterHook,
Given : self.defineStep,
When : self.defineStep,
Then : self.defineStep,
defineStep : self.defineStep,
registerListener : self.registerListener,
registerHandler : self.registerHandler,
World : worldConstructor
};

appendEventHandlers(supportCodeHelper, self);
supportCodeDefinition.call(supportCodeHelper);
worldConstructor = supportCodeHelper.World;

return self;
};

function appendEventHandlers(supportCodeHelper, library) {
var Cucumber = require('../../cucumber');
var events = Cucumber.Listener.Events;
var eventName;

for (eventName in events) {
if (events.hasOwnProperty(eventName)) {
supportCodeHelper[eventName] = createEventListenerMethod(library, eventName);
}
}
}

function createEventListenerMethod(library, eventName) {
return function(handler) {
library.registerHandler(eventName, handler);
};
}

Library.Hooker = require('./library/hooker');
module.exports = Library;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"Kim, Jang-hwan <janghwan@gmail.com>",
"Michael Zedeler <michael@zedeler.dk>",
"Tom V <tom@toc.com>",
"David Godfrey <reactiveraven@reactiveraven.co.uk>"
"David Godfrey <reactiveraven@reactiveraven.co.uk>",
"Paul Shannon (http://devpaul.com)"
],
"repository": {
"type": "git",
Expand Down
20 changes: 20 additions & 0 deletions spec/cucumber/listener/events_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require('../../support/spec_helper');

describe('Cucumber.Listener.Events', function () {
var Cucumber = requireLib('cucumber');
var events = Cucumber.Listener.Events;

describe('construction', function () {
it("contains a list of event names", function () {
for(var name in events) {
if(events.hasOwnProperty(name)) {
expect(events[name]).toEqual(name);
}
}
});

it("is defined", function() {
expect(events).toBeDefined();
});
});
});
39 changes: 36 additions & 3 deletions spec/cucumber/listener_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ require('../support/spec_helper');

describe("Cucumber.Listener", function() {
var Cucumber = requireLib('cucumber');
var listener;

beforeEach(function() {
listener = Cucumber.Listener();
Expand Down Expand Up @@ -96,20 +97,23 @@ describe("Cucumber.Listener", function() {
});

describe("buildHandlerNameForEvent", function () {
var event, eventName;
var event, eventName, buildHandlerName;

beforeEach(function () {
eventName = "SomeEventName";
event = createSpyWithStubs("Event", {getName: eventName});
buildHandlerName = spyOn(listener, "buildHandlerName");

});

it("gets the name of the event", function () {
listener.buildHandlerNameForEvent(event);
expect(event.getName).toHaveBeenCalled();
});

it("returns the name of the event with prefix 'handle' and suffix 'Event'", function () {
expect(listener.buildHandlerNameForEvent(event)).toBe("handle" + eventName + "Event");
it("calls buildHandlerName", function() {
listener.buildHandlerNameForEvent(event);
expect(buildHandlerName).toHaveBeenCalled();
});
});

Expand Down Expand Up @@ -145,4 +149,33 @@ describe("Cucumber.Listener", function() {
});
});
});

describe("buildHandlerName", function() {
it("returns the name of the event with prefix 'handle' and suffix 'Event'", function () {
var eventName = "shortName";
var expected = "handle" + eventName + "Event";

expect(listener.buildHandlerName(eventName)).toBe(expected);
});
});

describe("setHandlerForEvent", function() {
var shortName = "anEventName";
var handler = function(){};
var buildHandlerName;

beforeEach(function() {
buildHandlerName = spyOn(listener, "buildHandlerName").andCallThrough();
listener.setHandlerForEvent(shortName, handler);
});

it("attaches the function as a property to itself", function() {
var expectedKey = Cucumber.Listener.EVENT_HANDLER_NAME_PREFIX + shortName + Cucumber.Listener.EVENT_HANDLER_NAME_SUFFIX;
expect(listener[expectedKey]).toBe(handler);
});

it("calls buildHandlerName", function() {
expect(buildHandlerName).toHaveBeenCalled();
});
});
});
30 changes: 23 additions & 7 deletions spec/cucumber/runtime/ast_tree_walker_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ require('../../support/spec_helper');

describe("Cucumber.Runtime.AstTreeWalker", function() {
var Cucumber = requireLib('cucumber');
var treeWalker, features, supportCodeLibrary, listeners;
var treeWalker, features, supportCodeLibrary, listeners, supportListeners;

beforeEach(function() {
features = createSpyWithStubs("Features AST element", {acceptVisitor: null});
supportCodeLibrary = createSpy("Support code library");
listeners = [createSpy("First listener"), createSpy("Second listener")];
supportListeners = [createSpy("First support listener"), createSpy("Second support listener")];
spyOnStub(listeners, 'syncForEach').andCallFake(function(cb) { listeners.forEach(cb); });
spyOnStub(supportListeners, 'syncForEach').andCallFake(function(cb) { supportListeners.forEach(cb); });
spyOnStub(supportCodeLibrary, 'getListeners').andCallFake(function() { return supportListeners; });
treeWalker = Cucumber.Runtime.AstTreeWalker(features, supportCodeLibrary, listeners);
});

Expand Down Expand Up @@ -447,7 +450,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() {

beforeEach(function() {
wrapper = treeWalker.wrapAfterEventBroadcast(event, callback);
spyOn(treeWalker, 'broadcastAfterEvent');;
spyOn(treeWalker, 'broadcastAfterEvent');
});

it("broadcasts an after event with the received callback as callback", function() {
Expand Down Expand Up @@ -501,21 +504,34 @@ describe("Cucumber.Runtime.AstTreeWalker", function() {


describe("broadcastEvent()", function() {
var event, eventName, callback;
var event, callback;

beforeEach(function() {
event = createSpy("Event");
callback = createSpy("Callback");
spyOn(listeners, 'forEach');
spyOnListeners(listeners);
spyOnListeners(supportListeners);
});

function spyOnListeners(listeners) {
spyOn(listeners, 'forEach').andCallFake(function() {
var callback = listeners.forEach.mostRecentCall.args[1];
callback();
});
}

it("iterates over the listeners", function() {
treeWalker.broadcastEvent(event, callback);
expect(listeners.forEach).toHaveBeenCalled();
expect(listeners.forEach).toHaveBeenCalledWithAFunctionAsNthParameter(1);
expect(listeners.forEach).toHaveBeenCalledWithValueAsNthParameter(callback, 2);
assertListenerCollectionCalled(listeners.forEach);
assertListenerCollectionCalled(supportListeners.forEach);
expect(supportListeners.forEach).toHaveBeenCalledWithValueAsNthParameter(callback, 2);
});

function assertListenerCollectionCalled(forEachSpy) {
expect(forEachSpy).toHaveBeenCalled();
expect(forEachSpy).toHaveBeenCalledWithAFunctionAsNthParameter(1);
}

describe("for each listener", function() {
var userFunction, listener, forEachCallback;

Expand Down
Loading