From 837c021241f494c9534c4d62a65bbd0e03a3e1df Mon Sep 17 00:00:00 2001 From: Julien Biezemans Date: Sun, 17 Jun 2012 21:57:48 +0200 Subject: [PATCH] Refactor listener infrastructure (#35, #59, #63) * Extract common listener behaviour from progress formatter * Extract stats journal from progress formatter Theses changes will ease the implementation of new listeners (e.g. the pretty, JSON and jUnit formatters). --- lib/cucumber/listener.js | 37 +- lib/cucumber/listener/progress_formatter.js | 525 ++--- lib/cucumber/listener/stats_journal.js | 213 ++ spec/cucumber/ast/feature_spec.js | 2 +- .../ast/filter/any_of_tags_rule_spec.js | 8 +- .../filter/element_matching_tag_spec_spec.js | 14 +- spec/cucumber/ast/filter_spec.js | 12 +- spec/cucumber/ast/step_spec.js | 36 +- .../cli/argument_parser/path_expander_spec.js | 2 +- spec/cucumber/cli/configuration_spec.js | 4 +- spec/cucumber/cli/support_code_loader_spec.js | 4 +- spec/cucumber/cli_spec.js | 4 +- .../listener/progress_formatter_spec.js | 1848 ++++++----------- spec/cucumber/listener/stats_journal_spec.js | 787 +++++++ spec/cucumber/listener_spec.js | 148 ++ spec/cucumber/runtime/ast_tree_walker_spec.js | 12 +- spec/cucumber/support_code/hook_spec.js | 4 +- .../step_definition_snippet_builder_spec.js | 8 +- .../support_code/step_definition_spec.js | 2 +- 19 files changed, 2029 insertions(+), 1641 deletions(-) create mode 100644 lib/cucumber/listener/stats_journal.js create mode 100644 spec/cucumber/listener/stats_journal_spec.js create mode 100644 spec/cucumber/listener_spec.js diff --git a/lib/cucumber/listener.js b/lib/cucumber/listener.js index 396281cbd..f96a6f18d 100644 --- a/lib/cucumber/listener.js +++ b/lib/cucumber/listener.js @@ -1,3 +1,38 @@ -var Listener = {}; +var Listener = function () { + var self = { + hear: function hear(event, callback) { + if (self.hasHandlerForEvent(event)) { + var handler = self.getHandlerForEvent(event); + handler(event, callback); + } else { + callback(); + } + }, + + hasHandlerForEvent: function hasHandlerForEvent(event) { + var handlerName = self.buildHandlerNameForEvent(event); + return self[handlerName] != undefined; + }, + + buildHandlerNameForEvent: function buildHandlerNameForEvent(event) { + var handlerName = + Listener.EVENT_HANDLER_NAME_PREFIX + + event.getName() + + Listener.EVENT_HANDLER_NAME_SUFFIX; + return handlerName; + }, + + getHandlerForEvent: function getHandlerForEvent(event) { + var eventHandlerName = self.buildHandlerNameForEvent(event); + return self[eventHandlerName]; + } + }; + return self; +}; + +Listener.EVENT_HANDLER_NAME_PREFIX = 'handle'; +Listener.EVENT_HANDLER_NAME_SUFFIX = 'Event'; + Listener.ProgressFormatter = require('./listener/progress_formatter'); +Listener.StatsJournal = require('./listener/stats_journal'); module.exports = Listener; diff --git a/lib/cucumber/listener/progress_formatter.js b/lib/cucumber/listener/progress_formatter.js index d02ff4f46..4e423dc24 100644 --- a/lib/cucumber/listener/progress_formatter.js +++ b/lib/cucumber/listener/progress_formatter.js @@ -1,389 +1,210 @@ var ProgressFormatter = function(options) { var Cucumber = require('../../cucumber'); - var logs = ""; - var failedScenarioLogBuffer = ""; - var undefinedStepLogBuffer = ""; - var passedScenarioCount = 0; - var undefinedScenarioCount = 0; - var pendingScenarioCount = 0; - var failedScenarioCount = 0; - var passedStepCount = 0; - var failedStepCount = 0; - var skippedStepCount = 0; - var undefinedStepCount = 0; - var pendingStepCount = 0; - var currentScenarioFailing = false; - var currentScenarioUndefined = false; - var currentScenarioPending = false; - var failedStepResults = Cucumber.Type.Collection(); + var logs = ""; + var failedScenarioLogBuffer = ""; + var undefinedStepLogBuffer = ""; + var failedStepResults = Cucumber.Type.Collection(); + var statsJournal = Cucumber.Listener.StatsJournal(); if (!options) options = {}; if (options['logToConsole'] == undefined) options['logToConsole'] = true; - var self = { - log: function log(string) { - logs += string; - if (options['logToConsole']) - process.stdout.write(string); - if (typeof(options['logToFunction']) == 'function') - options['logToFunction'](string); - }, - getLogs: function getLogs() { - return logs; - }, + var self = Cucumber.Listener(); - hear: function hear(event, callback) { - if (self.hasHandlerForEvent(event)) { - var handler = self.getHandlerForEvent(event); - handler(event, callback); - } else { - callback(); - } - }, + var parentHear = self.hear; - hasHandlerForEvent: function hasHandlerForEvent(event) { - var handlerName = self.buildHandlerNameForEvent(event); - return self[handlerName] != undefined; - }, - - buildHandlerNameForEvent: function buildHandlerNameForEvent(event) { - var handlerName = - ProgressFormatter.EVENT_HANDLER_NAME_PREFIX + - event.getName() + - ProgressFormatter.EVENT_HANDLER_NAME_SUFFIX; - return handlerName; - }, - - getHandlerForEvent: function getHandlerForEvent(event) { - var eventHandlerName = self.buildHandlerNameForEvent(event); - return self[eventHandlerName]; - }, - - handleBeforeScenarioEvent: function handleBeforeScenarioEvent(event, callback) { - self.prepareBeforeScenario(); - callback(); - }, - - handleStepResultEvent: function handleStepResult(event, callback) { - var stepResult = event.getPayloadItem('stepResult'); - if (stepResult.isSuccessful()) - self.handleSuccessfulStepResult(); - else if (stepResult.isPending()) - self.handlePendingStepResult(); - else if (stepResult.isSkipped()) - self.handleSkippedStepResult(); - else if (stepResult.isUndefined()) - self.handleUndefinedStepResult(stepResult); - else - self.handleFailedStepResult(stepResult); - callback(); - }, - - handleSuccessfulStepResult: function handleSuccessfulStepResult() { - self.witnessPassedStep(); - self.log(ProgressFormatter.PASSED_STEP_CHARACTER); - }, - - handlePendingStepResult: function handlePendingStepResult() { - self.witnessPendingStep(); - self.markCurrentScenarioAsPending(); - self.log(ProgressFormatter.PENDING_STEP_CHARACTER); - }, - - handleSkippedStepResult: function handleSkippedStepResult() { - self.witnessSkippedStep(); - self.log(ProgressFormatter.SKIPPED_STEP_CHARACTER); - }, - - handleUndefinedStepResult: function handleUndefinedStepResult(stepResult) { - var step = stepResult.getStep(); - self.storeUndefinedStep(step); - self.witnessUndefinedStep(); - self.markCurrentScenarioAsUndefined(); - self.log(ProgressFormatter.UNDEFINED_STEP_CHARACTER); - }, - - handleFailedStepResult: function handleFailedStepResult(stepResult) { - self.storeFailedStepResult(stepResult); - self.witnessFailedStep(); - self.markCurrentScenarioAsFailing(); - self.log(ProgressFormatter.FAILED_STEP_CHARACTER); - }, - - handleAfterFeaturesEvent: function handleAfterFeaturesEvent(event, callback) { - self.logSummary(); - callback(); - }, - - handleAfterScenarioEvent: function handleAfterScenarioEvent(event, callback) { - if (self.isCurrentScenarioFailing()) { - var scenario = event.getPayloadItem('scenario'); - self.storeFailedScenario(scenario); - self.witnessFailedScenario(); - } else if (self.isCurrentScenarioUndefined()) { - self.witnessUndefinedScenario(); - } else if (self.isCurrentScenarioPending()) { - self.witnessPendingScenario(); - } else { - self.witnessPassedScenario(); - } - callback(); - }, - - prepareBeforeScenario: function prepareBeforeScenario() { - currentScenarioFailing = false; - currentScenarioPending = false; - currentScenarioUndefined = false; - }, - - markCurrentScenarioAsFailing: function markCurrentScenarioAsFailing() { - currentScenarioFailing = true; - }, - - markCurrentScenarioAsUndefined: function markCurrentScenarioAsUndefined() { - currentScenarioUndefined = true; - }, - - markCurrentScenarioAsPending: function markCurrentScenarioAsPending() { - currentScenarioPending = true; - }, - - isCurrentScenarioFailing: function isCurrentScenarioFailing() { - return currentScenarioFailing; - }, - - isCurrentScenarioUndefined: function isCurrentScenarioUndefined() { - return currentScenarioUndefined; - }, - - isCurrentScenarioPending: function isCurrentScenarioPending() { - return currentScenarioPending; - }, - - storeFailedStepResult: function storeFailedStepResult(failedStepResult) { - failedStepResults.add(failedStepResult); - }, - - storeFailedScenario: function storeFailedScenario(failedScenario) { - var name = failedScenario.getName(); - var line = failedScenario.getLine(); - self.appendStringToFailedScenarioLogBuffer(":" + line + " # Scenario: " + name); - }, - - storeUndefinedStep: function storeUndefinedStep(step) { - var snippetBuilder = Cucumber.SupportCode.StepDefinitionSnippetBuilder(step); - var snippet = snippetBuilder.buildSnippet(); - self.appendStringToUndefinedStepLogBuffer(snippet); - }, - - appendStringToFailedScenarioLogBuffer: function appendStringToFailedScenarioLogBuffer(string) { - failedScenarioLogBuffer += string + "\n"; - }, - - appendStringToUndefinedStepLogBuffer: function appendStringToUndefinedStepLogBuffer(string) { - if (undefinedStepLogBuffer.indexOf(string) == -1) - undefinedStepLogBuffer += string + "\n"; - }, - - getFailedScenarioLogBuffer: function getFailedScenarioLogBuffer() { - return failedScenarioLogBuffer; - }, - - getUndefinedStepLogBuffer: function getUndefinedStepLogBuffer() { - return undefinedStepLogBuffer; - }, - - logSummary: function logSummary() { - self.log("\n\n"); - if (self.witnessedAnyFailedStep()) - self.logFailedStepResults(); - self.logScenariosSummary(); - self.logStepsSummary(); - if (self.witnessedAnyUndefinedStep()) - self.logUndefinedStepSnippets(); - }, - - logFailedStepResults: function logFailedStepResults() { - self.log("(::) failed steps (::)\n\n"); - failedStepResults.syncForEach(function(stepResult) { - self.logFailedStepResult(stepResult); - }); - self.log("Failing scenarios:\n"); - var failedScenarios = self.getFailedScenarioLogBuffer(); - self.log(failedScenarios); - self.log("\n"); - }, - - logFailedStepResult: function logFailedStepResult(stepResult) { - var failureMessage = stepResult.getFailureException(); - self.log(failureMessage.stack || failureMessage); - self.log("\n\n"); - }, - - logScenariosSummary: function logScenariosSummary() { - var scenarioCount = self.getScenarioCount(); - var passedScenarioCount = self.getPassedScenarioCount(); - var undefinedScenarioCount = self.getUndefinedScenarioCount(); - var pendingScenarioCount = self.getPendingScenarioCount(); - var failedScenarioCount = self.getFailedScenarioCount(); - var details = []; - - self.log(scenarioCount + " scenario" + (scenarioCount != 1 ? "s" : "")); - if (scenarioCount > 0 ) { - if (failedScenarioCount > 0) - details.push(failedScenarioCount + " failed"); - if (undefinedScenarioCount > 0) - details.push(undefinedScenarioCount + " undefined"); - if (pendingScenarioCount > 0) - details.push(pendingScenarioCount + " pending"); - if (passedScenarioCount > 0) - details.push(passedScenarioCount + " passed"); - self.log(" (" + details.join(', ') + ")"); - } - self.log("\n"); - }, - - logStepsSummary: function logStepsSummary() { - var stepCount = self.getStepCount(); - var passedStepCount = self.getPassedStepCount(); - var undefinedStepCount = self.getUndefinedStepCount(); - var skippedStepCount = self.getSkippedStepCount(); - var pendingStepCount = self.getPendingStepCount(); - var failedStepCount = self.getFailedStepCount(); - var details = []; - - self.log(stepCount + " step" + (stepCount != 1 ? "s" : "")); - if (stepCount > 0) { - if (failedStepCount > 0) - details.push(failedStepCount + " failed"); - if (undefinedStepCount > 0) - details.push(undefinedStepCount + " undefined"); - if (pendingStepCount > 0) - details.push(pendingStepCount + " pending"); - if (skippedStepCount > 0) - details.push(skippedStepCount + " skipped"); - if (passedStepCount > 0) - details.push(passedStepCount + " passed"); - self.log(" (" + details.join(', ') + ")"); - } - self.log("\n"); - }, - - logUndefinedStepSnippets: function logUndefinedStepSnippets() { - var undefinedStepLogBuffer = self.getUndefinedStepLogBuffer(); - self.log("\nYou can implement step definitions for undefined steps with these snippets:\n\n"); - self.log(undefinedStepLogBuffer); - }, + self.hear = function hear(event, callback) { + statsJournal.hear(event, function () { + parentHear(event, callback); + }); + }; - witnessPassedScenario: function witnessPassedScenario() { - passedScenarioCount++; - }, + self.log = function log(string) { + logs += string; + if (options['logToConsole']) + process.stdout.write(string); + if (typeof(options['logToFunction']) == 'function') + options['logToFunction'](string); + }; - witnessUndefinedScenario: function witnessUndefinedScenario() { - undefinedScenarioCount++; - }, + self.getLogs = function getLogs() { + return logs; + }; - witnessPendingScenario: function witnessPendingScenario() { - pendingScenarioCount++; - }, + self.handleStepResultEvent = function handleStepResult(event, callback) { + var stepResult = event.getPayloadItem('stepResult'); + if (stepResult.isSuccessful()) + self.handleSuccessfulStepResult(); + else if (stepResult.isPending()) + self.handlePendingStepResult(); + else if (stepResult.isSkipped()) + self.handleSkippedStepResult(); + else if (stepResult.isUndefined()) + self.handleUndefinedStepResult(stepResult); + else + self.handleFailedStepResult(stepResult); + callback(); + }; - witnessFailedScenario: function witnessFailedScenario() { - failedScenarioCount++; - }, + self.handleSuccessfulStepResult = function handleSuccessfulStepResult() { + self.log(ProgressFormatter.PASSED_STEP_CHARACTER); + }; - witnessPassedStep: function witnessPassedStep() { - passedStepCount++; - }, + self.handlePendingStepResult = function handlePendingStepResult() { + self.log(ProgressFormatter.PENDING_STEP_CHARACTER); + }; - witnessUndefinedStep: function witnessUndefinedStep() { - undefinedStepCount++; - }, + self.handleSkippedStepResult = function handleSkippedStepResult() { + self.log(ProgressFormatter.SKIPPED_STEP_CHARACTER); + }; - witnessPendingStep: function witnessPendingStep() { - pendingStepCount++; - }, + self.handleUndefinedStepResult = function handleUndefinedStepResult(stepResult) { + var step = stepResult.getStep(); + self.storeUndefinedStep(step); + self.log(ProgressFormatter.UNDEFINED_STEP_CHARACTER); + }; - witnessFailedStep: function witnessFailedStep() { - failedStepCount++; - }, + self.handleFailedStepResult = function handleFailedStepResult(stepResult) { + self.storeFailedStepResult(stepResult); + self.log(ProgressFormatter.FAILED_STEP_CHARACTER); + }; - witnessSkippedStep: function witnessSkippedStep() { - skippedStepCount++; - }, + self.handleAfterFeaturesEvent = function handleAfterFeaturesEvent(event, callback) { + self.logSummary(); + callback(); + }; - getScenarioCount: function getScenarioCount() { - var scenarioCount = - self.getPassedScenarioCount() + - self.getUndefinedScenarioCount() + - self.getPendingScenarioCount() + - self.getFailedScenarioCount(); - return scenarioCount; - }, + self.handleAfterScenarioEvent = function handleAfterScenarioEvent(event, callback) { + if (statsJournal.isCurrentScenarioFailing()) { + var scenario = event.getPayloadItem('scenario'); + self.storeFailedScenario(scenario); + } + callback(); + }; - getPassedScenarioCount: function getPassedScenarioCount() { - return passedScenarioCount; - }, + self.storeFailedStepResult = function storeFailedStepResult(failedStepResult) { + failedStepResults.add(failedStepResult); + }; - getUndefinedScenarioCount: function getUndefinedScenarioCount() { - return undefinedScenarioCount; - }, + self.storeFailedScenario = function storeFailedScenario(failedScenario) { + var name = failedScenario.getName(); + var line = failedScenario.getLine(); + self.appendStringToFailedScenarioLogBuffer(":" + line + " # Scenario: " + name); + }; - getPendingScenarioCount: function getPendingScenarioCount() { - return pendingScenarioCount; - }, + self.storeUndefinedStep = function storeUndefinedStep(step) { + var snippetBuilder = Cucumber.SupportCode.StepDefinitionSnippetBuilder(step); + var snippet = snippetBuilder.buildSnippet(); + self.appendStringToUndefinedStepLogBuffer(snippet); + }; - getFailedScenarioCount: function getFailedScenarioCount() { - return failedScenarioCount; - }, + self.appendStringToFailedScenarioLogBuffer = function appendStringToFailedScenarioLogBuffer(string) { + failedScenarioLogBuffer += string + "\n"; + }; - getStepCount: function getStepCount() { - var stepCount = - self.getPassedStepCount() + - self.getUndefinedStepCount() + - self.getSkippedStepCount() + - self.getPendingStepCount() + - self.getFailedStepCount(); - return stepCount; - }, + self.appendStringToUndefinedStepLogBuffer = function appendStringToUndefinedStepLogBuffer(string) { + if (undefinedStepLogBuffer.indexOf(string) == -1) + undefinedStepLogBuffer += string + "\n"; + }; - getPassedStepCount: function getPassedStepCount() { - return passedStepCount; - }, + self.getFailedScenarioLogBuffer = function getFailedScenarioLogBuffer() { + return failedScenarioLogBuffer; + }; - getPendingStepCount: function getPendingStepCount() { - return pendingStepCount; - }, + self.getUndefinedStepLogBuffer = function getUndefinedStepLogBuffer() { + return undefinedStepLogBuffer; + }; - getFailedStepCount: function getFailedStepCount() { - return failedStepCount; - }, + self.logSummary = function logSummary() { + self.log("\n\n"); + if (statsJournal.witnessedAnyFailedStep()) + self.logFailedStepResults(); + self.logScenariosSummary(); + self.logStepsSummary(); + if (statsJournal.witnessedAnyUndefinedStep()) + self.logUndefinedStepSnippets(); + }; - getSkippedStepCount: function getSkippedStepCount() { - return skippedStepCount; - }, + self.logFailedStepResults = function logFailedStepResults() { + self.log("(::) failed steps (::)\n\n"); + failedStepResults.syncForEach(function(stepResult) { + self.logFailedStepResult(stepResult); + }); + self.log("Failing scenarios:\n"); + var failedScenarios = self.getFailedScenarioLogBuffer(); + self.log(failedScenarios); + self.log("\n"); + }; - getUndefinedStepCount: function getUndefinedStepCount() { - return undefinedStepCount; - }, + self.logFailedStepResult = function logFailedStepResult(stepResult) { + var failureMessage = stepResult.getFailureException(); + self.log(failureMessage.stack || failureMessage); + self.log("\n\n"); + }; - witnessedAnyFailedStep: function witnessedAnyFailedStep() { - return failedStepCount > 0; - }, + self.logScenariosSummary = function logScenariosSummary() { + var scenarioCount = statsJournal.getScenarioCount(); + var passedScenarioCount = statsJournal.getPassedScenarioCount(); + var undefinedScenarioCount = statsJournal.getUndefinedScenarioCount(); + var pendingScenarioCount = statsJournal.getPendingScenarioCount(); + var failedScenarioCount = statsJournal.getFailedScenarioCount(); + var details = []; + + self.log(scenarioCount + " scenario" + (scenarioCount != 1 ? "s" : "")); + if (scenarioCount > 0 ) { + if (failedScenarioCount > 0) + details.push(failedScenarioCount + " failed"); + if (undefinedScenarioCount > 0) + details.push(undefinedScenarioCount + " undefined"); + if (pendingScenarioCount > 0) + details.push(pendingScenarioCount + " pending"); + if (passedScenarioCount > 0) + details.push(passedScenarioCount + " passed"); + self.log(" (" + details.join(', ') + ")"); + } + self.log("\n"); + }; - witnessedAnyUndefinedStep: function witnessedAnyUndefinedStep() { - return undefinedStepCount > 0; + self.logStepsSummary = function logStepsSummary() { + var stepCount = statsJournal.getStepCount(); + var passedStepCount = statsJournal.getPassedStepCount(); + var undefinedStepCount = statsJournal.getUndefinedStepCount(); + var skippedStepCount = statsJournal.getSkippedStepCount(); + var pendingStepCount = statsJournal.getPendingStepCount(); + var failedStepCount = statsJournal.getFailedStepCount(); + var details = []; + + self.log(stepCount + " step" + (stepCount != 1 ? "s" : "")); + if (stepCount > 0) { + if (failedStepCount > 0) + details.push(failedStepCount + " failed"); + if (undefinedStepCount > 0) + details.push(undefinedStepCount + " undefined"); + if (pendingStepCount > 0) + details.push(pendingStepCount + " pending"); + if (skippedStepCount > 0) + details.push(skippedStepCount + " skipped"); + if (passedStepCount > 0) + details.push(passedStepCount + " passed"); + self.log(" (" + details.join(', ') + ")"); } + self.log("\n"); }; + + self.logUndefinedStepSnippets = function logUndefinedStepSnippets() { + var undefinedStepLogBuffer = self.getUndefinedStepLogBuffer(); + self.log("\nYou can implement step definitions for undefined steps with these snippets:\n\n"); + self.log(undefinedStepLogBuffer); + }; + return self; }; -ProgressFormatter.PASSED_STEP_CHARACTER = '.'; -ProgressFormatter.SKIPPED_STEP_CHARACTER = '-'; -ProgressFormatter.UNDEFINED_STEP_CHARACTER = 'U'; -ProgressFormatter.PENDING_STEP_CHARACTER = 'P'; -ProgressFormatter.FAILED_STEP_CHARACTER = 'F'; -ProgressFormatter.EVENT_HANDLER_NAME_PREFIX = 'handle'; -ProgressFormatter.EVENT_HANDLER_NAME_SUFFIX = 'Event'; -module.exports = ProgressFormatter; +ProgressFormatter.PASSED_STEP_CHARACTER = '.'; +ProgressFormatter.SKIPPED_STEP_CHARACTER = '-'; +ProgressFormatter.UNDEFINED_STEP_CHARACTER = 'U'; +ProgressFormatter.PENDING_STEP_CHARACTER = 'P'; +ProgressFormatter.FAILED_STEP_CHARACTER = 'F'; +module.exports = ProgressFormatter; diff --git a/lib/cucumber/listener/stats_journal.js b/lib/cucumber/listener/stats_journal.js new file mode 100644 index 000000000..b382c70e3 --- /dev/null +++ b/lib/cucumber/listener/stats_journal.js @@ -0,0 +1,213 @@ +var StatsJournal = function(options) { + var Cucumber = require('../../cucumber'); + + var passedScenarioCount = 0; + var undefinedScenarioCount = 0; + var pendingScenarioCount = 0; + var failedScenarioCount = 0; + var passedStepCount = 0; + var failedStepCount = 0; + var skippedStepCount = 0; + var undefinedStepCount = 0; + var pendingStepCount = 0; + var currentScenarioFailing = false; + var currentScenarioUndefined = false; + var currentScenarioPending = false; + + if (!options) + options = {}; + + var self = Cucumber.Listener(); + + self.handleBeforeScenarioEvent = function handleBeforeScenarioEvent(event, callback) { + self.prepareBeforeScenario(); + callback(); + }; + + self.handleStepResultEvent = function handleStepResult(event, callback) { + var stepResult = event.getPayloadItem('stepResult'); + if (stepResult.isSuccessful()) + self.handleSuccessfulStepResult(); + else if (stepResult.isPending()) + self.handlePendingStepResult(); + else if (stepResult.isSkipped()) + self.handleSkippedStepResult(); + else if (stepResult.isUndefined()) + self.handleUndefinedStepResult(stepResult); + else + self.handleFailedStepResult(stepResult); + callback(); + }; + + self.handleSuccessfulStepResult = function handleSuccessfulStepResult() { + self.witnessPassedStep(); + }; + + self.handlePendingStepResult = function handlePendingStepResult() { + self.witnessPendingStep(); + self.markCurrentScenarioAsPending(); + }; + + self.handleSkippedStepResult = function handleSkippedStepResult() { + self.witnessSkippedStep(); + }; + + self.handleUndefinedStepResult = function handleUndefinedStepResult(stepResult) { + var step = stepResult.getStep(); + self.witnessUndefinedStep(); + self.markCurrentScenarioAsUndefined(); + }; + + self.handleFailedStepResult = function handleFailedStepResult(stepResult) { + self.witnessFailedStep(); + self.markCurrentScenarioAsFailing(); + }; + + self.handleAfterScenarioEvent = function handleAfterScenarioEvent(event, callback) { + if (self.isCurrentScenarioFailing()) { + var scenario = event.getPayloadItem('scenario'); + self.witnessFailedScenario(); + } else if (self.isCurrentScenarioUndefined()) { + self.witnessUndefinedScenario(); + } else if (self.isCurrentScenarioPending()) { + self.witnessPendingScenario(); + } else { + self.witnessPassedScenario(); + } + callback(); + }; + + self.prepareBeforeScenario = function prepareBeforeScenario() { + currentScenarioFailing = false; + currentScenarioPending = false; + currentScenarioUndefined = false; + }; + + self.markCurrentScenarioAsFailing = function markCurrentScenarioAsFailing() { + currentScenarioFailing = true; + }; + + self.markCurrentScenarioAsUndefined = function markCurrentScenarioAsUndefined() { + currentScenarioUndefined = true; + }; + + self.markCurrentScenarioAsPending = function markCurrentScenarioAsPending() { + currentScenarioPending = true; + }; + + self.isCurrentScenarioFailing = function isCurrentScenarioFailing() { + return currentScenarioFailing; + }; + + self.isCurrentScenarioUndefined = function isCurrentScenarioUndefined() { + return currentScenarioUndefined; + }; + + self.isCurrentScenarioPending = function isCurrentScenarioPending() { + return currentScenarioPending; + }; + + self.witnessPassedScenario = function witnessPassedScenario() { + passedScenarioCount++; + }; + + self.witnessUndefinedScenario = function witnessUndefinedScenario() { + undefinedScenarioCount++; + }; + + self.witnessPendingScenario = function witnessPendingScenario() { + pendingScenarioCount++; + }; + + self.witnessFailedScenario = function witnessFailedScenario() { + failedScenarioCount++; + }; + + self.witnessPassedStep = function witnessPassedStep() { + passedStepCount++; + }; + + self.witnessUndefinedStep = function witnessUndefinedStep() { + undefinedStepCount++; + }; + + self.witnessPendingStep = function witnessPendingStep() { + pendingStepCount++; + }; + + self.witnessFailedStep = function witnessFailedStep() { + failedStepCount++; + }; + + self.witnessSkippedStep = function witnessSkippedStep() { + skippedStepCount++; + }; + + self.getScenarioCount = function getScenarioCount() { + var scenarioCount = + self.getPassedScenarioCount() + + self.getUndefinedScenarioCount() + + self.getPendingScenarioCount() + + self.getFailedScenarioCount(); + return scenarioCount; + }; + + self.getPassedScenarioCount = function getPassedScenarioCount() { + return passedScenarioCount; + }; + + self.getUndefinedScenarioCount = function getUndefinedScenarioCount() { + return undefinedScenarioCount; + }; + + self.getPendingScenarioCount = function getPendingScenarioCount() { + return pendingScenarioCount; + }; + + self.getFailedScenarioCount = function getFailedScenarioCount() { + return failedScenarioCount; + }; + + self.getStepCount = function getStepCount() { + var stepCount = + self.getPassedStepCount() + + self.getUndefinedStepCount() + + self.getSkippedStepCount() + + self.getPendingStepCount() + + self.getFailedStepCount(); + return stepCount; + }; + + self.getPassedStepCount = function getPassedStepCount() { + return passedStepCount; + }; + + self.getPendingStepCount = function getPendingStepCount() { + return pendingStepCount; + }; + + self.getFailedStepCount = function getFailedStepCount() { + return failedStepCount; + }; + + self.getSkippedStepCount = function getSkippedStepCount() { + return skippedStepCount; + }; + + self.getUndefinedStepCount = function getUndefinedStepCount() { + return undefinedStepCount; + }; + + self.witnessedAnyFailedStep = function witnessedAnyFailedStep() { + return failedStepCount > 0; + }; + + self.witnessedAnyUndefinedStep = function witnessedAnyUndefinedStep() { + return undefinedStepCount > 0; + }; + + return self; +}; +StatsJournal.EVENT_HANDLER_NAME_PREFIX = 'handle'; +StatsJournal.EVENT_HANDLER_NAME_SUFFIX = 'Event'; +module.exports = StatsJournal; diff --git a/spec/cucumber/ast/feature_spec.js b/spec/cucumber/ast/feature_spec.js index 7e755c2cc..0e2babcd9 100644 --- a/spec/cucumber/ast/feature_spec.js +++ b/spec/cucumber/ast/feature_spec.js @@ -173,7 +173,7 @@ describe("Cucumber.Ast.Feature", function() { spyOn(feature, 'hasBackground'); }); - it("checks wether the feature has a background", function() { + it("checks whether the feature has a background", function() { feature.instructVisitorToVisitBackground(visitor, callback); expect(feature.hasBackground).toHaveBeenCalled(); }); diff --git a/spec/cucumber/ast/filter/any_of_tags_rule_spec.js b/spec/cucumber/ast/filter/any_of_tags_rule_spec.js index c9bd45b3c..dfe2e35a1 100644 --- a/spec/cucumber/ast/filter/any_of_tags_rule_spec.js +++ b/spec/cucumber/ast/filter/any_of_tags_rule_spec.js @@ -17,7 +17,7 @@ describe("Cucumber.Ast.Filter.AnyOfTagsRule", function() { beforeEach(function() { element = createSpy("element"); - satisfyingElement = createSpy("wether the element is satisfying"); + satisfyingElement = createSpy("whether the element is satisfying"); spyOn(_, 'any').andReturn(satisfyingElement); }); @@ -32,7 +32,7 @@ describe("Cucumber.Ast.Filter.AnyOfTagsRule", function() { var spec, everyTagConditionFunc, tag, matchingSpec; beforeEach(function() { - matchingSpec = createSpy("wether the spec is satisfied or not"); + matchingSpec = createSpy("whether the spec is satisfied or not"); tag = createSpy("tag"); spec = createSpyWithStubs("element matching tag spec", {isMatching: matchingSpec}); rule.isSatisfiedByElement(element); @@ -45,7 +45,7 @@ describe("Cucumber.Ast.Filter.AnyOfTagsRule", function() { expect(Cucumber.Ast.Filter.ElementMatchingTagSpec).toHaveBeenCalledWith(tag); }); - it("checks wether the element is matching the spec", function() { + it("checks whether the element is matching the spec", function() { everyTagConditionFunc(tag); expect(spec.isMatching).toHaveBeenCalledWith(element); }); @@ -55,7 +55,7 @@ describe("Cucumber.Ast.Filter.AnyOfTagsRule", function() { }); }); - it("returns wether it found a matching tag or not", function() { + it("returns whether it found a matching tag or not", function() { expect(rule.isSatisfiedByElement(element)).toBe(satisfyingElement); }); }); diff --git a/spec/cucumber/ast/filter/element_matching_tag_spec_spec.js b/spec/cucumber/ast/filter/element_matching_tag_spec_spec.js index da250970d..154711e53 100644 --- a/spec/cucumber/ast/filter/element_matching_tag_spec_spec.js +++ b/spec/cucumber/ast/filter/element_matching_tag_spec_spec.js @@ -18,7 +18,7 @@ describe("Cucumber.Ast.Filter.ElementMatchingTagSpec", function() { beforeEach(function() { elementTags = createSpy("element tags"); element = createSpyWithStubs("element", {getTags: elementTags}); - matchingElement = createSpy("wether the element is matching or not"); + matchingElement = createSpy("whether the element is matching or not"); spyOn(spec, 'isExpectingTag'); }); @@ -27,7 +27,7 @@ describe("Cucumber.Ast.Filter.ElementMatchingTagSpec", function() { expect(element.getTags).toHaveBeenCalled(); }); - it("checks wether the spec tag is expected or not", function() { + it("checks whether the spec tag is expected or not", function() { spec.isMatching(element); expect(spec.isExpectingTag).toHaveBeenCalled(); }); @@ -38,12 +38,12 @@ describe("Cucumber.Ast.Filter.ElementMatchingTagSpec", function() { spyOn(_, 'any').andReturn(matchingElement); }); - it("checks wether any of the element tags match the spec tag", function() { + it("checks whether any of the element tags match the spec tag", function() { spec.isMatching(element); expect(_.any).toHaveBeenCalledWith(elementTags, spec.isTagSatisfying); }); - it("returns wether the element matched or not", function() { + it("returns whether the element matched or not", function() { expect(spec.isMatching(element)).toBe(matchingElement); }); }); @@ -54,12 +54,12 @@ describe("Cucumber.Ast.Filter.ElementMatchingTagSpec", function() { spyOn(_, 'all').andReturn(matchingElement); }); - it("checks wether any of the element tags match the spec tag", function() { + it("checks whether any of the element tags match the spec tag", function() { spec.isMatching(element); expect(_.all).toHaveBeenCalledWith(elementTags, spec.isTagSatisfying); }); - it("returns wether the element matched or not", function() { + it("returns whether the element matched or not", function() { expect(spec.isMatching(element)).toBe(matchingElement); }); }); @@ -78,7 +78,7 @@ describe("Cucumber.Ast.Filter.ElementMatchingTagSpec", function() { expect(checkedTag.getName).toHaveBeenCalled(); }); - it("checks wether the spec tag is expected or not on the element", function() { + it("checks whether the spec tag is expected or not on the element", function() { spec.isTagSatisfying(checkedTag); expect(spec.isExpectingTag).toHaveBeenCalled(); }); diff --git a/spec/cucumber/ast/filter_spec.js b/spec/cucumber/ast/filter_spec.js index 9c1c121ad..9600534e9 100644 --- a/spec/cucumber/ast/filter_spec.js +++ b/spec/cucumber/ast/filter_spec.js @@ -17,7 +17,7 @@ describe("Cucumber.Ast.Filter", function() { beforeEach(function() { scenario = createSpy("scenario"); - scenarioEnrolled = createSpy("wether the scenario is enrolled or not"); + scenarioEnrolled = createSpy("whether the scenario is enrolled or not"); spyOn(_, 'all').andReturn(scenarioEnrolled); }); @@ -32,24 +32,24 @@ describe("Cucumber.Ast.Filter", function() { var ruleConditionFunc, rule, ruleSatisfied; beforeEach(function() { - ruleSatisfied = createSpy("wether the rule was satisfied or not"); + ruleSatisfied = createSpy("whether the rule was satisfied or not"); rule = createSpyWithStubs("rule", {isSatisfiedByElement: ruleSatisfied}); filter.isScenarioEnrolled(scenario); ruleConditionFunc = _.all.mostRecentCall.args[1]; }); - it("checks wether the rule is satisfied by the scenario", function() { + it("checks whether the rule is satisfied by the scenario", function() { ruleConditionFunc(rule); expect(rule.isSatisfiedByElement).toHaveBeenCalledWith(scenario); }); - it("returns wether the rule wa satisfied or not", function() { + it("returns whether the rule wa satisfied or not", function() { expect(ruleConditionFunc(rule)).toBe(ruleSatisfied); }); }); - it("returns wether the scenario was enrolled or not", function() { + it("returns whether the scenario was enrolled or not", function() { expect(filter.isScenarioEnrolled(scenario)).toBe(scenarioEnrolled); }) }); -}); \ No newline at end of file +}); diff --git a/spec/cucumber/ast/step_spec.js b/spec/cucumber/ast/step_spec.js index ed9f41d38..714c0fb58 100644 --- a/spec/cucumber/ast/step_spec.js +++ b/spec/cucumber/ast/step_spec.js @@ -85,7 +85,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'hasDataTable'); }); - it("checks wether a doc string is attached", function() { + it("checks whether a doc string is attached", function() { step.getAttachment(); expect(step.hasDocString).toHaveBeenCalled(); }); @@ -114,7 +114,7 @@ describe("Cucumber.Ast.Step", function() { step.hasDocString.andReturn(false); }); - it("checks wether a data table is attached", function() { + it("checks whether a data table is attached", function() { step.getAttachment(); expect(step.hasDataTable).toHaveBeenCalled(); }); @@ -188,7 +188,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'hasDataTable'); }); - it("checks wether the step has a doc string attached or not", function() { + it("checks whether the step has a doc string attached or not", function() { step.hasAttachment(); expect(step.hasDocString).toHaveBeenCalled(); }); @@ -208,7 +208,7 @@ describe("Cucumber.Ast.Step", function() { step.hasDocString.andReturn(false); }); - it("checks wether the step has a data table attached or not", function() { + it("checks whether the step has a data table attached or not", function() { step.hasAttachment(); expect(step.hasDataTable).toHaveBeenCalled(); }); @@ -346,7 +346,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'isRepeatingOutcomeStep'); }); - it("checks wether the keyword is an outcome step keyword", function() { + it("checks whether the keyword is an outcome step keyword", function() { step.isOutcomeStep(); expect(step.hasOutcomeStepKeyword).toHaveBeenCalled(); }); @@ -361,7 +361,7 @@ describe("Cucumber.Ast.Step", function() { step.hasOutcomeStepKeyword.andReturn(false); }); - it("checks wether the keyword is repeating an outcome step", function() { + it("checks whether the keyword is repeating an outcome step", function() { step.isOutcomeStep(); expect(step.isRepeatingOutcomeStep).toHaveBeenCalled(); }); @@ -379,7 +379,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'isRepeatingEventStep'); }); - it("checks wether the keyword is an event step keyword", function() { + it("checks whether the keyword is an event step keyword", function() { step.isEventStep(); expect(step.hasEventStepKeyword).toHaveBeenCalled(); }); @@ -394,7 +394,7 @@ describe("Cucumber.Ast.Step", function() { step.hasEventStepKeyword.andReturn(false); }); - it("checks wether the keyword is repeating an event step", function() { + it("checks whether the keyword is repeating an event step", function() { step.isEventStep(); expect(step.isRepeatingEventStep).toHaveBeenCalled(); }); @@ -434,7 +434,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'isPrecededByOutcomeStep'); }); - it("checks wether the keyword is a repeating keyword", function() { + it("checks whether the keyword is a repeating keyword", function() { step.isRepeatingOutcomeStep(); expect(step.hasRepeatStepKeyword).toHaveBeenCalled(); }); @@ -444,7 +444,7 @@ describe("Cucumber.Ast.Step", function() { step.hasRepeatStepKeyword.andReturn(true); }); - it("checks wether the preceding step is an outcome step", function() { + it("checks whether the preceding step is an outcome step", function() { step.isRepeatingOutcomeStep(); expect(step.isPrecededByOutcomeStep).toHaveBeenCalled(); }); @@ -475,7 +475,7 @@ describe("Cucumber.Ast.Step", function() { step.hasRepeatStepKeyword.andReturn(false); }); - it("does not check wether the preceding step is an outcome step", function() { + it("does not check whether the preceding step is an outcome step", function() { step.isRepeatingOutcomeStep(); expect(step.isPrecededByOutcomeStep).not.toHaveBeenCalled(); }); @@ -492,7 +492,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'isPrecededByEventStep'); }); - it("checks wether the keyword is a repeating keyword", function() { + it("checks whether the keyword is a repeating keyword", function() { step.isRepeatingEventStep(); expect(step.hasRepeatStepKeyword).toHaveBeenCalled(); }); @@ -502,7 +502,7 @@ describe("Cucumber.Ast.Step", function() { step.hasRepeatStepKeyword.andReturn(true); }); - it("checks wether the preceding step is an event step", function() { + it("checks whether the preceding step is an event step", function() { step.isRepeatingEventStep(); expect(step.isPrecededByEventStep).toHaveBeenCalled(); }); @@ -533,7 +533,7 @@ describe("Cucumber.Ast.Step", function() { step.hasRepeatStepKeyword.andReturn(false); }); - it("does not check wether the preceding step is an event step", function() { + it("does not check whether the preceding step is an event step", function() { step.isRepeatingEventStep(); expect(step.isPrecededByEventStep).not.toHaveBeenCalled(); }); @@ -570,7 +570,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'hasPreviousStep'); }); - it("checks wether there is a previous step or not", function() { + it("checks whether there is a previous step or not", function() { step.isPrecededByOutcomeStep(); expect(step.hasPreviousStep).toHaveBeenCalled(); }); @@ -599,7 +599,7 @@ describe("Cucumber.Ast.Step", function() { expect(step.getPreviousStep).toHaveBeenCalled(); }); - it("checks wether the previous step is an outcome step or not", function() { + it("checks whether the previous step is an outcome step or not", function() { step.isPrecededByOutcomeStep(); expect(previousStep.isOutcomeStep).toHaveBeenCalled(); }); @@ -631,7 +631,7 @@ describe("Cucumber.Ast.Step", function() { spyOn(step, 'hasPreviousStep'); }); - it("checks wether there is a previous step or not", function() { + it("checks whether there is a previous step or not", function() { step.isPrecededByEventStep(); expect(step.hasPreviousStep).toHaveBeenCalled(); }); @@ -660,7 +660,7 @@ describe("Cucumber.Ast.Step", function() { expect(step.getPreviousStep).toHaveBeenCalled(); }); - it("checks wether the previous step is an event step or not", function() { + it("checks whether the previous step is an event step or not", function() { step.isPrecededByEventStep(); expect(previousStep.isEventStep).toHaveBeenCalled(); }); diff --git a/spec/cucumber/cli/argument_parser/path_expander_spec.js b/spec/cucumber/cli/argument_parser/path_expander_spec.js index 3fe620d2b..9a1cdcd40 100644 --- a/spec/cucumber/cli/argument_parser/path_expander_spec.js +++ b/spec/cucumber/cli/argument_parser/path_expander_spec.js @@ -60,7 +60,7 @@ describe("Cucumber.Cli.ArgumentParser.PathExpander", function() { expect(fs.statSync).toHaveBeenCalledWith(realPath); }); - it("checks wether the path points to a directory or not", function() { + it("checks whether the path points to a directory or not", function() { PathExpander.expandPathWithRegexp(path); expect(stats.isDirectory).toHaveBeenCalled(); }); diff --git a/spec/cucumber/cli/configuration_spec.js b/spec/cucumber/cli/configuration_spec.js index 21d0e2a1a..d588e15ea 100644 --- a/spec/cucumber/cli/configuration_spec.js +++ b/spec/cucumber/cli/configuration_spec.js @@ -149,7 +149,7 @@ describe("Cucumber.Cli.Configuration", function() { spyOnStub(argumentParser, 'isHelpRequested'); }); - it("asks the argument parser wether the help was requested or not", function() { + it("asks the argument parser whether the help was requested or not", function() { configuration.isHelpRequested(); expect(argumentParser.isHelpRequested).toHaveBeenCalled(); }); @@ -166,7 +166,7 @@ describe("Cucumber.Cli.Configuration", function() { spyOnStub(argumentParser, 'isVersionRequested'); }); - it("asks the argument parser wether the version was requested or not", function() { + it("asks the argument parser whether the version was requested or not", function() { configuration.isVersionRequested(); expect(argumentParser.isVersionRequested).toHaveBeenCalled(); }); diff --git a/spec/cucumber/cli/support_code_loader_spec.js b/spec/cucumber/cli/support_code_loader_spec.js index b27e50cb1..ac08b158e 100644 --- a/spec/cucumber/cli/support_code_loader_spec.js +++ b/spec/cucumber/cli/support_code_loader_spec.js @@ -119,7 +119,7 @@ describe("Cucumber.Cli.SupportCodeLoader", function() { }); describe("getPrimeSupportCodeFilePaths()", function() { - it("for each support code file path, checks wether they match the prime support code directory name convention", function() { + it("for each support code file path, checks whether they match the prime support code directory name convention", function() { supportCodeLoader.getPrimeSupportCodeFilePaths(); supportCodeFilePaths.forEach(function(path) { expect(path.match).toHaveBeenCalledWith(Cucumber.Cli.SupportCodeLoader.PRIME_SUPPORT_CODE_PATH_REGEXP); @@ -156,7 +156,7 @@ describe("Cucumber.Cli.SupportCodeLoader", function() { }); describe("getSecondarySupportCodeFilePaths()", function() { - it("for each support code file path, checks wether they match the prime support code directory name convention", function() { + it("for each support code file path, checks whether they match the prime support code directory name convention", function() { supportCodeLoader.getSecondarySupportCodeFilePaths(); supportCodeFilePaths.forEach(function(path) { expect(path.match).toHaveBeenCalledWith(Cucumber.Cli.SupportCodeLoader.PRIME_SUPPORT_CODE_PATH_REGEXP); diff --git a/spec/cucumber/cli_spec.js b/spec/cucumber/cli_spec.js index 5dd87e769..6e0ddfc90 100644 --- a/spec/cucumber/cli_spec.js +++ b/spec/cucumber/cli_spec.js @@ -27,7 +27,7 @@ describe("Cucumber.Cli", function() { expect(Cucumber.Cli.Configuration).toHaveBeenCalledWith(argv); }); - it("checks wether the help is requested or not", function() { + it("checks whether the help is requested or not", function() { cli.run(callback); expect(configuration.isHelpRequested).toHaveBeenCalled(); }); @@ -58,7 +58,7 @@ describe("Cucumber.Cli", function() { configuration.isHelpRequested.andReturn(false); }); - it("checks wether the version is requested or not", function() { + it("checks whether the version is requested or not", function() { cli.run(callback); expect(configuration.isVersionRequested).toHaveBeenCalled(); }); diff --git a/spec/cucumber/listener/progress_formatter_spec.js b/spec/cucumber/listener/progress_formatter_spec.js index 1a6c225ae..1fe3c2fe9 100644 --- a/spec/cucumber/listener/progress_formatter_spec.js +++ b/spec/cucumber/listener/progress_formatter_spec.js @@ -1,238 +1,149 @@ require('../../support/spec_helper'); -describe("Cucumber.Listener.ProgressFormatter", function() { +describe("Cucumber.Listener.ProgressFormatter", function () { var Cucumber = requireLib('cucumber'); - var listener, failedStepResults; - - beforeEach(function() { - failedStepResults = createSpy("Failed steps"); + var listener, listenerHearMethod, progressFormatter, statsJournal, failedStepResults; + + beforeEach(function () { + var ProgressFormatter = Cucumber.Listener.ProgressFormatter; + listener = createSpyWithStubs("listener"); + listenerHearMethod = spyOnStub(listener, 'hear'); + statsJournal = createSpy("stats journal"); + failedStepResults = createSpy("failed steps"); spyOn(Cucumber.Type, 'Collection').andReturn(failedStepResults); - listener = Cucumber.Listener.ProgressFormatter(); + spyOn(Cucumber, 'Listener').andReturn(listener); + spyOnStub(Cucumber.Listener, 'StatsJournal').andReturn(statsJournal); + Cucumber.Listener.ProgressFormatter = ProgressFormatter; + progressFormatter = Cucumber.Listener.ProgressFormatter(); + }); + + it("is based on the listener", function () { + expect(progressFormatter).toBe(listener); }); - describe("constructor", function() { - it("creates a collection to store the failed steps", function() { + describe("constructor", function () { + it("creates a listener", function() { + expect(Cucumber.Listener).toHaveBeenCalled(); + }); + + it("creates a collection to store the failed steps", function () { expect(Cucumber.Type.Collection).toHaveBeenCalled(); }); + + it("creates a stats journal", function () { + expect(Cucumber.Listener.StatsJournal).toHaveBeenCalled(); + }) }); - describe("log()", function() { + describe("log()", function () { var logged, alsoLogged, loggedBuffer; - beforeEach(function() { + beforeEach(function () { logged = "this was logged"; alsoLogged = "this was also logged"; loggedBuffer = logged + alsoLogged; spyOn(process.stdout, 'write'); }); - it("records logged strings", function() { - listener.log(logged); - listener.log(alsoLogged); - expect(listener.getLogs()).toBe(loggedBuffer); + it("records logged strings", function () { + progressFormatter.log(logged); + progressFormatter.log(alsoLogged); + expect(progressFormatter.getLogs()).toBe(loggedBuffer); }); - it("outputs the logged string to STDOUT by default", function() { - listener.log(logged); + it("outputs the logged string to STDOUT by default", function () { + progressFormatter.log(logged); expect(process.stdout.write).toHaveBeenCalledWith(logged); }); - describe("when asked to output to STDOUT", function() { - beforeEach(function() { - listener = Cucumber.Listener.ProgressFormatter({logToConsole: true}); + describe("when asked to output to STDOUT", function () { + beforeEach(function () { + progressFormatter = Cucumber.Listener.ProgressFormatter({logToConsole: true}); }); - it("outputs the logged string to STDOUT", function() { - listener.log(logged); + it("outputs the logged string to STDOUT", function () { + progressFormatter.log(logged); expect(process.stdout.write).toHaveBeenCalledWith(logged); }); }); - describe("when asked to not output to STDOUT", function() { - beforeEach(function() { - listener = Cucumber.Listener.ProgressFormatter({logToConsole: false}); + describe("when asked to not output to STDOUT", function () { + beforeEach(function () { + progressFormatter = Cucumber.Listener.ProgressFormatter({logToConsole: false}); }); - it("does not output anything to STDOUT", function() { - listener.log(logged); + it("does not output anything to STDOUT", function () { + progressFormatter.log(logged); expect(process.stdout.write).not.toHaveBeenCalledWith(logged); }); }); - describe("when asked to output to a function", function() { + describe("when asked to output to a function", function () { var userFunction; - beforeEach(function() { - userFunction = createSpy("output user function"); - listener = Cucumber.Listener.ProgressFormatter({logToFunction: userFunction}); + beforeEach(function () { + userFunction = createSpy("output user function"); + progressFormatter = Cucumber.Listener.ProgressFormatter({logToFunction: userFunction}); }); - it("calls the function with the logged string", function() { - listener.log(logged); + it("calls the function with the logged string", function () { + progressFormatter.log(logged); expect(userFunction).toHaveBeenCalledWith(logged); }); }); }); - describe("getLogs()", function() { - it("returns the logged buffer", function() { + describe("getLogs()", function () { + it("returns the logged buffer", function () { var logged = "this was logged"; var alsoLogged = "this was also logged"; var loggedBuffer = logged + alsoLogged; spyOn(process.stdout, 'write'); // prevent actual output during spec execution - listener.log(logged); - listener.log(alsoLogged); - expect(listener.getLogs()).toBe(loggedBuffer); + progressFormatter.log(logged); + progressFormatter.log(alsoLogged); + expect(progressFormatter.getLogs()).toBe(loggedBuffer); }); - it("returns an empty string when the listener did not log anything yet", function() { - expect(listener.getLogs()).toBe(""); + it("returns an empty string when the progress formatter did not log anything yet", function () { + expect(progressFormatter.getLogs()).toBe(""); }); }); - describe("hear()", function() { + describe("hear()", function () { var event, callback; - var eventHandler; - - beforeEach(function() { - event = createSpy("Event"); - callback = createSpy("Callback"); - spyOn(listener, 'hasHandlerForEvent'); - spyOn(listener, 'getHandlerForEvent'); - }); - - it("checks wether there is a handler for the event", function() { - listener.hear(event, callback); - expect(listener.hasHandlerForEvent).toHaveBeenCalledWith(event); - }); - - describe("when there is a handler for that event", function() { - beforeEach(function() { - eventHandler = createSpy("Event handler (function)"); - listener.hasHandlerForEvent.andReturn(true); - listener.getHandlerForEvent.andReturn(eventHandler); - }); - - it("gets the handler for that event", function() { - listener.hear(event, callback); - expect(listener.getHandlerForEvent).toHaveBeenCalledWith(event); - }); - - it("calls the handler with the event and the callback", function() { - listener.hear(event, callback); - expect(eventHandler).toHaveBeenCalledWith(event, callback); - }); - - it("does not callback", function() { - listener.hear(event, callback); - expect(callback).not.toHaveBeenCalled(); - }); - }); - - describe("when there are no handlers for that event", function() { - beforeEach(function() { - listener.hasHandlerForEvent.andReturn(false); - }); - - it("calls back", function() { - listener.hear(event, callback); - expect(callback).toHaveBeenCalled(); - }); - - it("does not get the handler for the event", function() { - listener.hear(event, callback); - expect(listener.getHandlerForEvent).not.toHaveBeenCalled(); - }); - }); - }); - - describe("hasHandlerForEvent", function() { - var event, eventHandlerName, eventHandler; - - beforeEach(function() { - event = createSpy("Event"); - eventHandlerName = createSpy("event handler name"); - spyOn(listener, 'buildHandlerNameForEvent').andReturn(eventHandlerName); - }); - - it("builds the name of the handler for that event", function() { - listener.hasHandlerForEvent(event); - expect(listener.buildHandlerNameForEvent).toHaveBeenCalledWith(event); - }); - - describe("when the handler exists", function() { - beforeEach(function() { - eventHandler = createSpy("event handler"); - listener[eventHandlerName] = eventHandler; - }); - it("returns true", function() { - expect(listener.hasHandlerForEvent(event)).toBeTruthy(); - }); - }); - - describe("when the handler does not exist", function() { - it("returns false", function() { - expect(listener.hasHandlerForEvent(event)).toBeFalsy(); - }); - }); - }); - - describe("buildHandlerNameForEvent", function() { - var event, eventName; - - beforeEach(function() { - eventName = "SomeEventName"; - event = createSpyWithStubs("Event", {getName: eventName}); - }); - - 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"); - }); - }); - - describe("getHandlerForEvent()", function() { - var event; - var eventHandlerName, eventHandler; - - beforeEach(function() { - event = createSpy("event"); - eventHandlerName = 'handleSomeEvent'; - eventHandler = createSpy("event handler"); - spyOn(listener, 'buildHandlerNameForEvent').andReturn(eventHandlerName); + beforeEach(function () { + event = createSpy("event"); + callback = createSpy("callback"); + spyOnStub(statsJournal, 'hear'); }); - it("gets the name of the handler for the event", function() { - listener.getHandlerForEvent(event); - expect(listener.buildHandlerNameForEvent).toHaveBeenCalledWith(event); + it("tells the stats journal to listen to the event", function () { + progressFormatter.hear(event, callback); + expect(statsJournal.hear).toHaveBeenCalled(); + expect(statsJournal.hear).toHaveBeenCalledWithValueAsNthParameter(event, 1); + expect(statsJournal.hear).toHaveBeenCalledWithAFunctionAsNthParameter(2); }); - describe("when an event handler exists for the event", function() { - beforeEach(function() { - listener[eventHandlerName] = eventHandler; - }); + describe("stats journal callback", function () { + var statsJournalCallback; - it("returns the event handler", function() { - expect(listener.getHandlerForEvent(event)).toBe(eventHandler); + beforeEach(function () { + progressFormatter.hear(event, callback); + statsJournalCallback = statsJournal.hear.mostRecentCall.args[1]; }); - }); - describe("when no event handlers exist for the event", function() { - it("returns nothing", function() { - expect(listener.getHandlerForEvent(event)).toBeUndefined(); + it("tells the listener to listen to the event", function () { + statsJournalCallback(); + expect(listenerHearMethod).toHaveBeenCalledWith(event, callback); }); }); }); - describe("handleStepResultEvent()", function() { + describe("handleStepResultEvent()", function () { var event, callback, stepResult; - beforeEach(function() { + beforeEach(function () { stepResult = createSpyWithStubs("step result", { isSuccessful: undefined, isPending: undefined, @@ -242,1578 +153,1051 @@ describe("Cucumber.Listener.ProgressFormatter", function() { }); event = createSpyWithStubs("event", {getPayloadItem: stepResult}); callback = createSpy("Callback"); - spyOn(listener, 'handleFailedStepResult'); + spyOn(progressFormatter, 'handleFailedStepResult'); }); - it("gets the step result from the event payload", function() { - listener.handleStepResultEvent(event, callback); + it("gets the step result from the event payload", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(event.getPayloadItem).toHaveBeenCalledWith('stepResult'); }); - it("checks wether the step was successful or not", function() { - listener.handleStepResultEvent(event, callback); + it("checks whether the step was successful or not", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(stepResult.isSuccessful).toHaveBeenCalled(); }); - describe("when the step passed", function() { - beforeEach(function() { + describe("when the step passed", function () { + beforeEach(function () { stepResult.isSuccessful.andReturn(true); - spyOn(listener, 'handleSuccessfulStepResult'); + spyOn(progressFormatter, 'handleSuccessfulStepResult'); }); - it("handles the successful step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleSuccessfulStepResult).toHaveBeenCalled(); + it("handles the successful step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleSuccessfulStepResult).toHaveBeenCalled(); }); }); - describe("when the step did not pass", function() { - beforeEach(function() { + describe("when the step did not pass", function () { + beforeEach(function () { stepResult.isSuccessful.andReturn(false); - spyOn(listener, 'handleSuccessfulStepResult'); + spyOn(progressFormatter, 'handleSuccessfulStepResult'); }); - it("does not handle a successful step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleSuccessfulStepResult).not.toHaveBeenCalled(); + it("does not handle a successful step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleSuccessfulStepResult).not.toHaveBeenCalled(); }); - it("checks wether the step is pending", function() { - listener.handleStepResultEvent(event, callback); + it("checks whether the step is pending", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(stepResult.isPending).toHaveBeenCalled(); }); - describe("when the step was pending", function() { - beforeEach(function() { + describe("when the step was pending", function () { + beforeEach(function () { stepResult.isPending.andReturn(true); - spyOn(listener, 'handlePendingStepResult'); + spyOn(progressFormatter, 'handlePendingStepResult'); }); - it("handles the pending step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handlePendingStepResult).toHaveBeenCalled(); + it("handles the pending step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handlePendingStepResult).toHaveBeenCalled(); }); }); - describe("when the step was not pending", function() { - beforeEach(function() { + describe("when the step was not pending", function () { + beforeEach(function () { stepResult.isPending.andReturn(false); - spyOn(listener, 'handlePendingStepResult'); + spyOn(progressFormatter, 'handlePendingStepResult'); }); - it("does not handle a pending step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handlePendingStepResult).not.toHaveBeenCalled(); + it("does not handle a pending step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handlePendingStepResult).not.toHaveBeenCalled(); }); - it("checks wether the step was skipped", function() { - listener.handleStepResultEvent(event, callback); + it("checks whether the step was skipped", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(stepResult.isSkipped).toHaveBeenCalled(); }); - describe("when the step was skipped", function() { - beforeEach(function() { + describe("when the step was skipped", function () { + beforeEach(function () { stepResult.isSkipped.andReturn(true); - spyOn(listener, 'handleSkippedStepResult'); + spyOn(progressFormatter, 'handleSkippedStepResult'); }); - it("handles the skipped step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleSkippedStepResult).toHaveBeenCalled(); + it("handles the skipped step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleSkippedStepResult).toHaveBeenCalled(); }); }); - describe("when the step was not skipped", function() { - beforeEach(function() { + describe("when the step was not skipped", function () { + beforeEach(function () { stepResult.isSkipped.andReturn(false); - spyOn(listener, 'handleSkippedStepResult'); + spyOn(progressFormatter, 'handleSkippedStepResult'); }); - it("does not handle a skipped step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleSkippedStepResult).not.toHaveBeenCalled(); + it("does not handle a skipped step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleSkippedStepResult).not.toHaveBeenCalled(); }); - it("checks wether the step was undefined", function() { - listener.handleStepResultEvent(event, callback); + it("checks whether the step was undefined", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(stepResult.isUndefined).toHaveBeenCalled(); }); - describe("when the step was undefined", function() { - beforeEach(function() { + describe("when the step was undefined", function () { + beforeEach(function () { stepResult.isUndefined.andReturn(true); - spyOn(listener, 'handleUndefinedStepResult'); + spyOn(progressFormatter, 'handleUndefinedStepResult'); }); - it("handles the undefined step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleUndefinedStepResult).toHaveBeenCalledWith(stepResult); + it("handles the undefined step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleUndefinedStepResult).toHaveBeenCalledWith(stepResult); }); }); - describe("when the step was not undefined", function() { - beforeEach(function() { + describe("when the step was not undefined", function () { + beforeEach(function () { stepResult.isUndefined.andReturn(false); - spyOn(listener, 'handleUndefinedStepResult'); + spyOn(progressFormatter, 'handleUndefinedStepResult'); }); - it("does not handle a skipped step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleSkippedStepResult).not.toHaveBeenCalled(); + it("does not handle a skipped step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleSkippedStepResult).not.toHaveBeenCalled(); }); - it("handles a failed step result", function() { - listener.handleStepResultEvent(event, callback); - expect(listener.handleFailedStepResult).toHaveBeenCalledWith(stepResult); + it("handles a failed step result", function () { + progressFormatter.handleStepResultEvent(event, callback); + expect(progressFormatter.handleFailedStepResult).toHaveBeenCalledWith(stepResult); }); }); }); }); }); - it("calls back", function() { - listener.handleStepResultEvent(event, callback); + it("calls back", function () { + progressFormatter.handleStepResultEvent(event, callback); expect(callback).toHaveBeenCalled(); }); }); - describe("handleSuccessfulStepResult()", function() { - beforeEach(function() { - spyOn(listener, 'witnessPassedStep'); - spyOn(listener, 'log'); - }); - - it("witnesses a passed step", function() { - listener.handleSuccessfulStepResult(); - expect(listener.witnessPassedStep).toHaveBeenCalled(); + describe("handleSuccessfulStepResult()", function () { + beforeEach(function () { + spyOn(progressFormatter, 'log'); }); - it("logs the passing step character", function() { - listener.handleSuccessfulStepResult(); - expect(listener.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.PASSED_STEP_CHARACTER); + it("logs the passing step character", function () { + progressFormatter.handleSuccessfulStepResult(); + expect(progressFormatter.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.PASSED_STEP_CHARACTER); }); }); - describe("handlePendingStepResult()", function() { - beforeEach(function() { - spyOn(listener, 'witnessPendingStep'); - spyOn(listener, 'markCurrentScenarioAsPending'); - spyOn(listener, 'log') + describe("handlePendingStepResult()", function () { + beforeEach(function () { + spyOn(progressFormatter, 'log') }); - it("witnesses a pending step", function() { - listener.handlePendingStepResult(); - expect(listener.witnessPendingStep).toHaveBeenCalled(); - }); - - it("marks the current scenario as pending", function() { - listener.handlePendingStepResult(); - expect(listener.markCurrentScenarioAsPending).toHaveBeenCalled(); - }); - - it("logs the pending step character", function() { - listener.handlePendingStepResult(); - expect(listener.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.PENDING_STEP_CHARACTER); + it("logs the pending step character", function () { + progressFormatter.handlePendingStepResult(); + expect(progressFormatter.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.PENDING_STEP_CHARACTER); }); }); - describe("handleSkippedStepResult()", function() { - beforeEach(function() { - spyOn(listener, 'witnessSkippedStep'); - spyOn(listener, 'log'); + describe("handleSkippedStepResult()", function () { + beforeEach(function () { + spyOn(progressFormatter, 'log'); }); - it("counts one more skipped step", function() { - listener.handleSkippedStepResult(); - expect(listener.witnessSkippedStep).toHaveBeenCalled(); - }); - - it("logs the skipped step character", function() { - listener.handleSkippedStepResult(); - expect(listener.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.SKIPPED_STEP_CHARACTER); + it("logs the skipped step character", function () { + progressFormatter.handleSkippedStepResult(); + expect(progressFormatter.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.SKIPPED_STEP_CHARACTER); }); }); - describe("handleUndefinedStepResult()", function() { + describe("handleUndefinedStepResult()", function () { var stepResult, step; - beforeEach(function() { + beforeEach(function () { step = createSpy("step"); stepResult = createSpyWithStubs("step result", {getStep: step}); - spyOn(listener, 'storeUndefinedStep'); - spyOn(listener, 'witnessUndefinedStep'); - spyOn(listener, 'markCurrentScenarioAsUndefined'); - spyOn(listener, 'log'); + spyOn(progressFormatter, 'storeUndefinedStep'); + spyOn(progressFormatter, 'log'); }); - it("gets the step from the step result", function() { - listener.handleUndefinedStepResult(stepResult); + it("gets the step from the step result", function () { + progressFormatter.handleUndefinedStepResult(stepResult); expect(stepResult.getStep).toHaveBeenCalled(); }); - it("stores the undefined step", function() { - listener.handleUndefinedStepResult(stepResult); - expect(listener.storeUndefinedStep).toHaveBeenCalledWith(step); - }); - - it("witnesses an undefined step", function() { - listener.handleUndefinedStepResult(stepResult); - expect(listener.witnessUndefinedStep).toHaveBeenCalled(); + it("stores the undefined step", function () { + progressFormatter.handleUndefinedStepResult(stepResult); + expect(progressFormatter.storeUndefinedStep).toHaveBeenCalledWith(step); }); - it("marks the current scenario as undefined", function() { - listener.handleUndefinedStepResult(stepResult); - expect(listener.markCurrentScenarioAsUndefined).toHaveBeenCalled(); - }); - - it("logs the undefined step character", function() { - listener.handleUndefinedStepResult(stepResult); - expect(listener.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.UNDEFINED_STEP_CHARACTER); + it("logs the undefined step character", function () { + progressFormatter.handleUndefinedStepResult(stepResult); + expect(progressFormatter.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.UNDEFINED_STEP_CHARACTER); }); }); - describe("handleFailedStepResult()", function() { + describe("handleFailedStepResult()", function () { var stepResult; - beforeEach(function() { + beforeEach(function () { stepResult = createSpy("failed step result"); - spyOn(listener, 'storeFailedStepResult'); - spyOn(listener, 'witnessFailedStep'); - spyOn(listener, 'markCurrentScenarioAsFailing'); - spyOn(listener, 'log'); + spyOn(progressFormatter, 'storeFailedStepResult'); + spyOn(progressFormatter, 'log'); }); - it("stores the failed step result", function() { - listener.handleFailedStepResult(stepResult); - expect(listener.storeFailedStepResult).toHaveBeenCalledWith(stepResult); + it("stores the failed step result", function () { + progressFormatter.handleFailedStepResult(stepResult); + expect(progressFormatter.storeFailedStepResult).toHaveBeenCalledWith(stepResult); }); - it("witnesses a failed step", function() { - listener.handleFailedStepResult(stepResult); - expect(listener.witnessFailedStep).toHaveBeenCalled(); - }); - - it("marks the current scenario as failing", function() { - listener.handleFailedStepResult(stepResult); - expect(listener.markCurrentScenarioAsFailing).toHaveBeenCalled(); - }); - - it("logs the failed step character", function() { - listener.handleFailedStepResult(stepResult); - expect(listener.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.FAILED_STEP_CHARACTER); + it("logs the failed step character", function () { + progressFormatter.handleFailedStepResult(stepResult); + expect(progressFormatter.log).toHaveBeenCalledWith(Cucumber.Listener.ProgressFormatter.FAILED_STEP_CHARACTER); }); }); - describe("handleBeforeScenarioEvent", function() { - var event, callback; - - beforeEach(function() { - event = createSpy("event"); - callback = createSpy("callback"); - spyOn(listener, 'prepareBeforeScenario'); - }); - - it("prepares for a new scenario", function() { - listener.handleBeforeScenarioEvent(event, callback); - expect(listener.prepareBeforeScenario).toHaveBeenCalled(); - }); - - it("calls back", function() { - listener.handleBeforeScenarioEvent(event, callback); - expect(callback).toHaveBeenCalled(); - }); - }); - - describe("handleAfterFeaturesEvent()", function() { + describe("handleAfterFeaturesEvent()", function () { var features, callback; - beforeEach(function() { + beforeEach(function () { event = createSpy("Event"); callback = createSpy("Callback"); - spyOn(listener, "logSummary"); + spyOn(progressFormatter, "logSummary"); }); - it("displays a summary", function() { - listener.handleAfterFeaturesEvent(event, callback); - expect(listener.logSummary).toHaveBeenCalled(); + it("displays a summary", function () { + progressFormatter.handleAfterFeaturesEvent(event, callback); + expect(progressFormatter.logSummary).toHaveBeenCalled(); }); - it("calls back", function() { - listener.handleAfterFeaturesEvent(event, callback); + it("calls back", function () { + progressFormatter.handleAfterFeaturesEvent(event, callback); expect(callback).toHaveBeenCalled(); }); }); - describe("handleAfterScenarioEvent()", function() { + describe("handleAfterScenarioEvent()", function () { var event, callback; - beforeEach(function() { + beforeEach(function () { event = createSpy("event"); callback = createSpy("callback"); - spyOn(listener, 'isCurrentScenarioFailing'); - spyOn(listener, 'witnessPassedScenario'); - spyOn(listener, 'witnessUndefinedScenario'); - spyOn(listener, 'witnessPendingScenario'); - spyOn(listener, 'witnessFailedScenario'); + spyOnStub(statsJournal, 'isCurrentScenarioFailing'); }); - it("checks wether the current scenario failed", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.isCurrentScenarioFailing).toHaveBeenCalled(); + it("checks whether the current scenario failed", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); + expect(statsJournal.isCurrentScenarioFailing).toHaveBeenCalled(); }); - describe("when the current scenario failed", function() { + describe("when the current scenario failed", function () { var scenario; - beforeEach(function() { + beforeEach(function () { scenario = createSpy("scenario"); - listener.isCurrentScenarioFailing.andReturn(true); - spyOn(listener, 'storeFailedScenario'); + statsJournal.isCurrentScenarioFailing.andReturn(true); + spyOn(progressFormatter, 'storeFailedScenario'); spyOnStub(event, 'getPayloadItem').andReturn(scenario); }); - it("witnesses a failed scenario", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.witnessFailedScenario).toHaveBeenCalled(); - }); - - it("gets the scenario from the payload", function() { - listener.handleAfterScenarioEvent(event, callback); + it("gets the scenario from the payload", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); expect(event.getPayloadItem).toHaveBeenCalledWith('scenario'); }); - it("stores the failed scenario", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.storeFailedScenario).toHaveBeenCalledWith(scenario); + it("stores the failed scenario", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); + expect(progressFormatter.storeFailedScenario).toHaveBeenCalledWith(scenario); }); }); - describe("when the current scenario did not fail", function() { - beforeEach(function() { - listener.isCurrentScenarioFailing.andReturn(false); - spyOn(listener, 'isCurrentScenarioUndefined'); - }); - - it("checks wether the current scenario is undefined", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.isCurrentScenarioUndefined).toHaveBeenCalled(); + describe("when the current scenario did not fail", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioFailing.andReturn(false); + spyOn(progressFormatter, 'storeFailedScenario'); + spyOnStub(event, 'getPayloadItem'); }); - describe("when the current scenario is undefined", function() { - beforeEach(function() { - listener.isCurrentScenarioUndefined.andReturn(true); - }); - - it("witnesses an undefined scenario", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.witnessUndefinedScenario).toHaveBeenCalled(); - }); + it("does not get the scenario from the payload", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); + expect(event.getPayloadItem).not.toHaveBeenCalled(); }); - describe("when the current scenario is not undefined", function() { - beforeEach(function() { - listener.isCurrentScenarioUndefined.andReturn(false); - spyOn(listener, 'isCurrentScenarioPending'); - }); - - it("checks wether the current scenario is pending", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.isCurrentScenarioPending).toHaveBeenCalled(); - }); - - describe("when the current scenario is pending", function() { - beforeEach(function() { - listener.isCurrentScenarioPending.andReturn(true); - }); - - it("witnesses a pending scenario", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.witnessPendingScenario).toHaveBeenCalled(); - }); - }); - - describe("when the current scenario is not pending (passed)", function() { - beforeEach(function() { - listener.isCurrentScenarioPending.andReturn(false); - }); - - it("witnesses a passed scenario", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(listener.witnessPassedScenario).toHaveBeenCalled(); - }); - }); + it("does not store the failed scenario", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); + expect(progressFormatter.storeFailedScenario).not.toHaveBeenCalled(); }); }); - it("calls back", function() { - listener.handleAfterScenarioEvent(event, callback); - expect(callback).toHaveBeenCalled(); - }); - }); - describe("isCurrentScenarioFailing()", function() { - it("returns false when the current scenario did not fail yet", function() { - expect(listener.isCurrentScenarioFailing()).toBeFalsy(); - }); - - it("returns true when a step in the current scenario failed", function() { - listener.markCurrentScenarioAsFailing(); - expect(listener.isCurrentScenarioFailing()).toBeTruthy(); - }); - }); - - describe("isCurrentScenarioPending()", function() { - it("returns false when the current scenario was not set pending yet", function() { - expect(listener.isCurrentScenarioPending()).toBeFalsy(); - }); - - it("returns true when the current scenario was set pending", function() { - listener.markCurrentScenarioAsPending(); - expect(listener.isCurrentScenarioPending()).toBeTruthy(); - }); - }); - - describe("isCurrentScenarioUndefined()", function() { - it("returns false when the current scenario was not set undefined yet", function() { - expect(listener.isCurrentScenarioUndefined()).toBeFalsy(); - }); - - it("returns true when the current scenario was set undefined", function() { - listener.markCurrentScenarioAsUndefined(); - expect(listener.isCurrentScenarioUndefined()).toBeTruthy(); - }); - }); - - describe("prepareBeforeScenario()", function() { - it("unmarks the current scenario as pending", function() { - listener.markCurrentScenarioAsPending(); - listener.prepareBeforeScenario(); - expect(listener.isCurrentScenarioPending()).toBeFalsy(); - }); - - it("unmarks the current scenario as failing", function() { - listener.markCurrentScenarioAsFailing(); - listener.prepareBeforeScenario(); - expect(listener.isCurrentScenarioFailing()).toBeFalsy(); - }); - - it("unmarks the current scenario as undefined", function() { - listener.markCurrentScenarioAsUndefined(); - listener.prepareBeforeScenario(); - expect(listener.isCurrentScenarioUndefined()).toBeFalsy(); + it("calls back", function () { + progressFormatter.handleAfterScenarioEvent(event, callback); + expect(callback).toHaveBeenCalled(); }); }); - describe("storeFailedStepResult()", function() { + describe("storeFailedStepResult()", function () { var failedStepResult; - beforeEach(function() { + beforeEach(function () { failedStepResult = createSpy("failed step result"); spyOnStub(failedStepResults, 'add'); }); - it("adds the result to the failed step result collection", function() { - listener.storeFailedStepResult(failedStepResult); + it("adds the result to the failed step result collection", function () { + progressFormatter.storeFailedStepResult(failedStepResult); expect(failedStepResults.add).toHaveBeenCalledWith(failedStepResult); }); }); - describe("storeFailedScenario()", function() { + describe("storeFailedScenario()", function () { var failedScenario, name, line; - beforeEach(function() { + beforeEach(function () { name = "some failed scenario"; line = "123"; string = ":" + line + " # Scenario: " + name; failedScenario = createSpyWithStubs("failedScenario", {getName: name, getLine: line}); - spyOn(listener, 'appendStringToFailedScenarioLogBuffer'); + spyOn(progressFormatter, 'appendStringToFailedScenarioLogBuffer'); }); - it("gets the name of the scenario", function() { - listener.storeFailedScenario(failedScenario); + it("gets the name of the scenario", function () { + progressFormatter.storeFailedScenario(failedScenario); expect(failedScenario.getName).toHaveBeenCalled(); }); - it("gets the line of the scenario", function() { - listener.storeFailedScenario(failedScenario); + it("gets the line of the scenario", function () { + progressFormatter.storeFailedScenario(failedScenario); expect(failedScenario.getLine).toHaveBeenCalled(); }); - it("appends the scenario details to the failed scenario log buffer", function() { - listener.storeFailedScenario(failedScenario); - expect(listener.appendStringToFailedScenarioLogBuffer).toHaveBeenCalledWith(string); + it("appends the scenario details to the failed scenario log buffer", function () { + progressFormatter.storeFailedScenario(failedScenario); + expect(progressFormatter.appendStringToFailedScenarioLogBuffer).toHaveBeenCalledWith(string); }); }); - describe("storeUndefinedStep()", function() { + describe("storeUndefinedStep()", function () { var snippetBuilder, snippet, step; - beforeEach(function() { + beforeEach(function () { stpe = createSpy("step"); snippet = createSpy("step definition snippet"); snippetBuilder = createSpyWithStubs("snippet builder", {buildSnippet: snippet}); spyOn(Cucumber.SupportCode, 'StepDefinitionSnippetBuilder').andReturn(snippetBuilder); - spyOn(listener, 'appendStringToUndefinedStepLogBuffer'); + spyOn(progressFormatter, 'appendStringToUndefinedStepLogBuffer'); }); - it("creates a new step definition snippet builder", function() { - listener.storeUndefinedStep(step); + it("creates a new step definition snippet builder", function () { + progressFormatter.storeUndefinedStep(step); expect(Cucumber.SupportCode.StepDefinitionSnippetBuilder).toHaveBeenCalledWith(step); }); - it("builds the step definition", function() { - listener.storeUndefinedStep(step); + it("builds the step definition", function () { + progressFormatter.storeUndefinedStep(step); expect(snippetBuilder.buildSnippet).toHaveBeenCalled(); }); - it("appends the snippet to the undefined step log buffer", function() { - listener.storeUndefinedStep(step); - expect(listener.appendStringToUndefinedStepLogBuffer).toHaveBeenCalledWith(snippet); + it("appends the snippet to the undefined step log buffer", function () { + progressFormatter.storeUndefinedStep(step); + expect(progressFormatter.appendStringToUndefinedStepLogBuffer).toHaveBeenCalledWith(snippet); }); }); - describe("getFailedScenarioLogBuffer() [appendStringToFailedScenarioLogBuffer()]", function() { - it("returns the logged failed scenario details", function() { - listener.appendStringToFailedScenarioLogBuffer("abc"); - expect(listener.getFailedScenarioLogBuffer()).toBe("abc\n"); + describe("getFailedScenarioLogBuffer() [appendStringToFailedScenarioLogBuffer()]", function () { + it("returns the logged failed scenario details", function () { + progressFormatter.appendStringToFailedScenarioLogBuffer("abc"); + expect(progressFormatter.getFailedScenarioLogBuffer()).toBe("abc\n"); }); - it("returns all logged failed scenario lines joined with a line break", function() { - listener.appendStringToFailedScenarioLogBuffer("abc"); - listener.appendStringToFailedScenarioLogBuffer("def"); - expect(listener.getFailedScenarioLogBuffer()).toBe("abc\ndef\n"); + it("returns all logged failed scenario lines joined with a line break", function () { + progressFormatter.appendStringToFailedScenarioLogBuffer("abc"); + progressFormatter.appendStringToFailedScenarioLogBuffer("def"); + expect(progressFormatter.getFailedScenarioLogBuffer()).toBe("abc\ndef\n"); }); }); - describe("getUndefinedStepLogBuffer() [appendStringToUndefinedStepLogBuffer()]", function() { - it("returns the logged undefined step details", function() { - listener.appendStringToUndefinedStepLogBuffer("abc"); - expect(listener.getUndefinedStepLogBuffer()).toBe("abc\n"); + describe("getUndefinedStepLogBuffer() [appendStringToUndefinedStepLogBuffer()]", function () { + it("returns the logged undefined step details", function () { + progressFormatter.appendStringToUndefinedStepLogBuffer("abc"); + expect(progressFormatter.getUndefinedStepLogBuffer()).toBe("abc\n"); }); - it("returns all logged failed scenario lines joined with a line break", function() { - listener.appendStringToUndefinedStepLogBuffer("abc"); - listener.appendStringToUndefinedStepLogBuffer("def"); - expect(listener.getUndefinedStepLogBuffer()).toBe("abc\ndef\n"); + it("returns all logged failed scenario lines joined with a line break", function () { + progressFormatter.appendStringToUndefinedStepLogBuffer("abc"); + progressFormatter.appendStringToUndefinedStepLogBuffer("def"); + expect(progressFormatter.getUndefinedStepLogBuffer()).toBe("abc\ndef\n"); }); }); - describe("appendStringToUndefinedStepLogBuffer() [getUndefinedStepLogBuffer()]", function() { - it("does not log the same string twice", function() { - listener.appendStringToUndefinedStepLogBuffer("abcdef"); - listener.appendStringToUndefinedStepLogBuffer("abcdef"); - expect(listener.getUndefinedStepLogBuffer()).toBe("abcdef\n"); + describe("appendStringToUndefinedStepLogBuffer() [getUndefinedStepLogBuffer()]", function () { + it("does not log the same string twice", function () { + progressFormatter.appendStringToUndefinedStepLogBuffer("abcdef"); + progressFormatter.appendStringToUndefinedStepLogBuffer("abcdef"); + expect(progressFormatter.getUndefinedStepLogBuffer()).toBe("abcdef\n"); }); }); - describe("logSummary()", function() { + describe("logSummary()", function () { var scenarioCount, passedScenarioCount, failedScenarioCount; var stepCount, passedStepCount; - beforeEach(function() { - spyOn(listener, 'log'); - spyOn(listener, 'witnessedAnyFailedStep'); - spyOn(listener, 'witnessedAnyUndefinedStep'); - spyOn(listener, 'logFailedStepResults'); - spyOn(listener, 'logScenariosSummary'); - spyOn(listener, 'logStepsSummary'); - spyOn(listener, 'logUndefinedStepSnippets'); + beforeEach(function () { + spyOn(progressFormatter, 'log'); + spyOn(progressFormatter, 'logScenariosSummary'); + spyOn(progressFormatter, 'logStepsSummary'); + spyOn(progressFormatter, 'logFailedStepResults'); + spyOn(progressFormatter, 'logUndefinedStepSnippets'); + spyOnStub(statsJournal, 'witnessedAnyFailedStep'); + spyOnStub(statsJournal, 'witnessedAnyUndefinedStep'); + spyOnStub(statsJournal, 'logFailedStepResults'); + spyOnStub(statsJournal, 'logScenariosSummary'); + spyOnStub(statsJournal, 'logStepsSummary'); + spyOnStub(statsJournal, 'logUndefinedStepSnippets'); }); - it("logs two line feeds", function() { - listener.logSummary(); - expect(listener.log).toHaveBeenCalledWith("\n\n"); + it("logs two line feeds", function () { + progressFormatter.logSummary(); + expect(progressFormatter.log).toHaveBeenCalledWith("\n\n"); }); - it("checks wether there are failed steps or not", function() { - listener.logSummary(); - expect(listener.witnessedAnyFailedStep).toHaveBeenCalled(); + it("checks whether there are failed steps or not", function () { + progressFormatter.logSummary(); + expect(statsJournal.witnessedAnyFailedStep).toHaveBeenCalled(); }); - describe("when there are failed steps", function() { - beforeEach(function() { - listener.witnessedAnyFailedStep.andReturn(true); + describe("when there are failed steps", function () { + beforeEach(function () { + statsJournal.witnessedAnyFailedStep.andReturn(true); }); - it("logs the failed steps", function() { - listener.logSummary(); - expect(listener.logFailedStepResults).toHaveBeenCalled(); + it("logs the failed steps", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logFailedStepResults).toHaveBeenCalled(); }); }); - describe("when there are no failed steps", function() { - beforeEach(function() { - listener.witnessedAnyFailedStep.andReturn(false); + describe("when there are no failed steps", function () { + beforeEach(function () { + statsJournal.witnessedAnyFailedStep.andReturn(false); }); - it("does not log failed steps", function() { - listener.logSummary(); - expect(listener.logFailedStepResults).not.toHaveBeenCalled(); + it("does not log failed steps", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logFailedStepResults).not.toHaveBeenCalled(); }); }); - it("logs the scenarios summary", function() { - listener.logSummary(); - expect(listener.logScenariosSummary).toHaveBeenCalled(); + it("logs the scenarios summary", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logScenariosSummary).toHaveBeenCalled(); }); - it("logs the steps summary", function() { - listener.logSummary(); - expect(listener.logStepsSummary).toHaveBeenCalled(); + it("logs the steps summary", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logStepsSummary).toHaveBeenCalled(); }); - it("checks wether there are undefined steps or not", function() { - listener.logSummary(); - expect(listener.witnessedAnyUndefinedStep).toHaveBeenCalled(); + it("checks whether there are undefined steps or not", function () { + progressFormatter.logSummary(); + expect(statsJournal.witnessedAnyUndefinedStep).toHaveBeenCalled(); }); - describe("when there are undefined steps", function() { - beforeEach(function() { - listener.witnessedAnyUndefinedStep.andReturn(true); + describe("when there are undefined steps", function () { + beforeEach(function () { + statsJournal.witnessedAnyUndefinedStep.andReturn(true); }); - it("logs the undefined step snippets", function() { - listener.logSummary(); - expect(listener.logUndefinedStepSnippets).toHaveBeenCalled(); + it("logs the undefined step snippets", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logUndefinedStepSnippets).toHaveBeenCalled(); }); }); - describe("when there are no undefined steps", function() { - beforeEach(function() { - listener.witnessedAnyUndefinedStep.andReturn(false); + describe("when there are no undefined steps", function () { + beforeEach(function () { + statsJournal.witnessedAnyUndefinedStep.andReturn(false); }); - it("does not log the undefined step snippets", function() { - listener.logSummary(); - expect(listener.logUndefinedStepSnippets).not.toHaveBeenCalled(); + it("does not log the undefined step snippets", function () { + progressFormatter.logSummary(); + expect(progressFormatter.logUndefinedStepSnippets).not.toHaveBeenCalled(); }); }); }); - describe("logFailedStepResults()", function() { + describe("logFailedStepResults()", function () { var failedScenarioLogBuffer; - beforeEach(function() { + beforeEach(function () { failedScenarioLogBuffer = createSpy("failed scenario log buffer"); spyOnStub(failedStepResults, 'syncForEach'); - spyOn(listener, 'log'); - spyOn(listener, 'getFailedScenarioLogBuffer').andReturn(failedScenarioLogBuffer); + spyOn(progressFormatter, 'log'); + spyOn(progressFormatter, 'getFailedScenarioLogBuffer').andReturn(failedScenarioLogBuffer); }); - it("logs a failed steps header", function() { - listener.logFailedStepResults(); - expect(listener.log).toHaveBeenCalledWith("(::) failed steps (::)\n\n"); + it("logs a failed steps header", function () { + progressFormatter.logFailedStepResults(); + expect(progressFormatter.log).toHaveBeenCalledWith("(::) failed steps (::)\n\n"); }); - it("iterates synchronously over the failed step results", function() { - listener.logFailedStepResults(); + it("iterates synchronously over the failed step results", function () { + progressFormatter.logFailedStepResults(); expect(failedStepResults.syncForEach).toHaveBeenCalled(); expect(failedStepResults.syncForEach).toHaveBeenCalledWithAFunctionAsNthParameter(1); }); - describe("for each failed step result", function() { + describe("for each failed step result", function () { var userFunction, failedStep, forEachCallback; - beforeEach(function() { - listener.logFailedStepResults(); + beforeEach(function () { + progressFormatter.logFailedStepResults(); userFunction = failedStepResults.syncForEach.mostRecentCall.args[0]; failedStepResult = createSpy("failed step result"); - spyOn(listener, 'logFailedStepResult'); + spyOn(progressFormatter, 'logFailedStepResult'); }); - it("tells the visitor to visit the feature and call back when finished", function() { + it("tells the visitor to visit the feature and call back when finished", function () { userFunction(failedStepResult); - expect(listener.logFailedStepResult).toHaveBeenCalledWith(failedStepResult); + expect(progressFormatter.logFailedStepResult).toHaveBeenCalledWith(failedStepResult); }); }); - it("logs a failed scenarios header", function() { - listener.logFailedStepResults(); - expect(listener.log).toHaveBeenCalledWith("Failing scenarios:\n"); + it("logs a failed scenarios header", function () { + progressFormatter.logFailedStepResults(); + expect(progressFormatter.log).toHaveBeenCalledWith("Failing scenarios:\n"); }); - it("gets the failed scenario details from its log buffer", function() { - listener.logFailedStepResults(); - expect(listener.getFailedScenarioLogBuffer).toHaveBeenCalled(); + it("gets the failed scenario details from its log buffer", function () { + progressFormatter.logFailedStepResults(); + expect(progressFormatter.getFailedScenarioLogBuffer).toHaveBeenCalled(); }); - it("logs the failed scenario details", function() { - listener.logFailedStepResults(); - expect(listener.log).toHaveBeenCalledWith(failedScenarioLogBuffer); + it("logs the failed scenario details", function () { + progressFormatter.logFailedStepResults(); + expect(progressFormatter.log).toHaveBeenCalledWith(failedScenarioLogBuffer); }); - it("logs a line break", function() { - listener.logFailedStepResults(); - expect(listener.log).toHaveBeenCalledWith("\n"); + it("logs a line break", function () { + progressFormatter.logFailedStepResults(); + expect(progressFormatter.log).toHaveBeenCalledWith("\n"); }); }); - describe("logFailedStepResult()", function() { + describe("logFailedStepResult()", function () { var stepResult, failureException; - beforeEach(function() { - spyOn(listener, 'log'); + beforeEach(function () { + spyOn(progressFormatter, 'log'); failureException = createSpy('caught exception'); stepResult = createSpyWithStubs("failed step result", { getFailureException: failureException }); }); - it("gets the failure exception from the step result", function() { - listener.logFailedStepResult(stepResult); + it("gets the failure exception from the step result", function () { + progressFormatter.logFailedStepResult(stepResult); expect(stepResult.getFailureException).toHaveBeenCalled(); }); - describe("when the failure exception has a stack", function() { - beforeEach(function() { + describe("when the failure exception has a stack", function () { + beforeEach(function () { failureException.stack = createSpy('failure exception stack'); }); - it("logs the stack", function() { - listener.logFailedStepResult(stepResult); - expect(listener.log).toHaveBeenCalledWith(failureException.stack); + it("logs the stack", function () { + progressFormatter.logFailedStepResult(stepResult); + expect(progressFormatter.log).toHaveBeenCalledWith(failureException.stack); }); }); - describe("when the failure exception has no stack", function() { - it("logs the exception itself", function() { - listener.logFailedStepResult(stepResult); - expect(listener.log).toHaveBeenCalledWith(failureException); + describe("when the failure exception has no stack", function () { + it("logs the exception itself", function () { + progressFormatter.logFailedStepResult(stepResult); + expect(progressFormatter.log).toHaveBeenCalledWith(failureException); }); }); - it("logs two line breaks", function() { - listener.logFailedStepResult(stepResult); - expect(listener.log).toHaveBeenCalledWith("\n\n"); + it("logs two line breaks", function () { + progressFormatter.logFailedStepResult(stepResult); + expect(progressFormatter.log).toHaveBeenCalledWith("\n\n"); }); }); - describe("logScenariosSummary()", function() { + describe("logScenariosSummary()", function () { var scenarioCount, passedScenarioCount, pendingScenarioCount, failedScenarioCount; - beforeEach(function() { + beforeEach(function () { scenarioCount = 12; passedScenarioCount = 9; undefinedScenarioCount = 17; pendingScenarioCount = 7; failedScenarioCount = 15; - spyOn(listener, 'log'); - spyOn(listener, 'getScenarioCount').andReturn(scenarioCount); - spyOn(listener, 'getPassedScenarioCount').andReturn(passedScenarioCount); - spyOn(listener, 'getUndefinedScenarioCount').andReturn(undefinedScenarioCount); - spyOn(listener, 'getPendingScenarioCount').andReturn(pendingScenarioCount); - spyOn(listener, 'getFailedScenarioCount').andReturn(failedScenarioCount); + spyOn(progressFormatter, 'log'); + spyOnStub(statsJournal, 'getScenarioCount').andReturn(scenarioCount); + spyOnStub(statsJournal, 'getPassedScenarioCount').andReturn(passedScenarioCount); + spyOnStub(statsJournal, 'getUndefinedScenarioCount').andReturn(undefinedScenarioCount); + spyOnStub(statsJournal, 'getPendingScenarioCount').andReturn(pendingScenarioCount); + spyOnStub(statsJournal, 'getFailedScenarioCount').andReturn(failedScenarioCount); }); - it("gets the number of scenarios", function() { - listener.logScenariosSummary(); - expect(listener.getScenarioCount).toHaveBeenCalled(); + it("gets the number of scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(statsJournal.getScenarioCount).toHaveBeenCalled(); }); - describe("when there are no scenarios", function() { - beforeEach(function() { listener.getScenarioCount.andReturn(0); }); + describe("when there are no scenarios", function () { + beforeEach(function () { statsJournal.getScenarioCount.andReturn(0); }); - it("logs 0 scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/0 scenarios/); + it("logs 0 scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/0 scenarios/); }); - it("does not log any details", function() { - listener.logScenariosSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/\(.*\)/); + it("does not log any details", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/\(.*\)/); }); }); - describe("when there are scenarios", function() { - beforeEach(function() { listener.getScenarioCount.andReturn(12); }); + describe("when there are scenarios", function () { + beforeEach(function () { statsJournal.getScenarioCount.andReturn(12); }); - describe("when there is one scenario", function() { - beforeEach(function() { listener.getScenarioCount.andReturn(1); }); + describe("when there is one scenario", function () { + beforeEach(function () { statsJournal.getScenarioCount.andReturn(1); }); - it("logs one scenario", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 scenario([^s]|$)/); + it("logs one scenario", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 scenario([^s]|$)/); }); }); - describe("when there are 2 or more scenarios", function() { - beforeEach(function() { listener.getScenarioCount.andReturn(2); }); + describe("when there are 2 or more scenarios", function () { + beforeEach(function () { statsJournal.getScenarioCount.andReturn(2); }); - it("logs two or more scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 scenarios/); + it("logs two or more scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 scenarios/); }); }); - it("gets the number of failed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.getFailedScenarioCount).toHaveBeenCalled(); + it("gets the number of failed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(statsJournal.getFailedScenarioCount).toHaveBeenCalled(); }); - describe("when there are no failed scenarios", function() { - beforeEach(function() { listener.getFailedScenarioCount.andReturn(0); }); + describe("when there are no failed scenarios", function () { + beforeEach(function () { statsJournal.getFailedScenarioCount.andReturn(0); }); - it("does not log failed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/failed/); + it("does not log failed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/failed/); }); }); - describe("when there is one failed scenario", function() { - beforeEach(function() { listener.getFailedScenarioCount.andReturn(1); }); + describe("when there is one failed scenario", function () { + beforeEach(function () { statsJournal.getFailedScenarioCount.andReturn(1); }); - it("logs a failed scenario", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 failed/); + it("logs a failed scenario", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 failed/); }); }); - describe("when there are two or more failed scenarios", function() { - beforeEach(function() { listener.getFailedScenarioCount.andReturn(2); }); + describe("when there are two or more failed scenarios", function () { + beforeEach(function () { statsJournal.getFailedScenarioCount.andReturn(2); }); - it("logs the number of failed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 failed/); + it("logs the number of failed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 failed/); }); }); - it("gets the number of undefined scenarios", function() { - listener.logScenariosSummary(); - expect(listener.getUndefinedScenarioCount).toHaveBeenCalled(); + it("gets the number of undefined scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(statsJournal.getUndefinedScenarioCount).toHaveBeenCalled(); }); - describe("when there are no undefined scenarios", function() { - beforeEach(function() { listener.getUndefinedScenarioCount.andReturn(0); }); + describe("when there are no undefined scenarios", function () { + beforeEach(function () { statsJournal.getUndefinedScenarioCount.andReturn(0); }); - it("does not log passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/undefined/); + it("does not log passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/undefined/); }); }); - describe("when there is one undefined scenario", function() { - beforeEach(function() { listener.getUndefinedScenarioCount.andReturn(1); }); + describe("when there is one undefined scenario", function () { + beforeEach(function () { statsJournal.getUndefinedScenarioCount.andReturn(1); }); - it("logs one undefined scenario", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 undefined/); + it("logs one undefined scenario", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 undefined/); }); }); - describe("when there are two or more undefined scenarios", function() { - beforeEach(function() { listener.getUndefinedScenarioCount.andReturn(2); }); + describe("when there are two or more undefined scenarios", function () { + beforeEach(function () { statsJournal.getUndefinedScenarioCount.andReturn(2); }); - it("logs the undefined scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 undefined/); + it("logs the undefined scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 undefined/); }); }); - it("gets the number of pending scenarios", function() { - listener.logScenariosSummary(); - expect(listener.getPendingScenarioCount).toHaveBeenCalled(); + it("gets the number of pending scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(statsJournal.getPendingScenarioCount).toHaveBeenCalled(); }); - describe("when there are no pending scenarios", function() { - beforeEach(function() { listener.getPendingScenarioCount.andReturn(0); }); + describe("when there are no pending scenarios", function () { + beforeEach(function () { statsJournal.getPendingScenarioCount.andReturn(0); }); - it("does not log passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/pending/); + it("does not log passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/pending/); }); }); - describe("when there is one pending scenario", function() { - beforeEach(function() { listener.getPendingScenarioCount.andReturn(1); }); + describe("when there is one pending scenario", function () { + beforeEach(function () { statsJournal.getPendingScenarioCount.andReturn(1); }); - it("logs one pending scenario", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 pending/); + it("logs one pending scenario", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 pending/); }); }); - describe("when there are two or more pending scenarios", function() { - beforeEach(function() { listener.getPendingScenarioCount.andReturn(2); }); + describe("when there are two or more pending scenarios", function () { + beforeEach(function () { statsJournal.getPendingScenarioCount.andReturn(2); }); - it("logs the pending scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 pending/); + it("logs the pending scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 pending/); }); }); - it("gets the number of passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.getPassedScenarioCount).toHaveBeenCalled(); + it("gets the number of passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(statsJournal.getPassedScenarioCount).toHaveBeenCalled(); }); - describe("when there are no passed scenarios", function() { - beforeEach(function() { listener.getPassedScenarioCount.andReturn(0); }); + describe("when there are no passed scenarios", function () { + beforeEach(function () { statsJournal.getPassedScenarioCount.andReturn(0); }); - it("does not log passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/passed/); + it("does not log passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/passed/); }); }); - describe("when there is one passed scenario", function() { - beforeEach(function() { listener.getPassedScenarioCount.andReturn(1); }); + describe("when there is one passed scenario", function () { + beforeEach(function () { statsJournal.getPassedScenarioCount.andReturn(1); }); - it("logs 1 passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 passed/); + it("logs 1 passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 passed/); }); }); - describe("when there are two or more passed scenarios", function() { - beforeEach(function() { listener.getPassedScenarioCount.andReturn(2); }); + describe("when there are two or more passed scenarios", function () { + beforeEach(function () { statsJournal.getPassedScenarioCount.andReturn(2); }); - it("logs the number of passed scenarios", function() { - listener.logScenariosSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 passed/); + it("logs the number of passed scenarios", function () { + progressFormatter.logScenariosSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 passed/); }); }); }); }); - describe("logStepsSummary()", function() { + describe("logStepsSummary()", function () { var stepCount, passedStepCount, failedStepCount, skippedStepCount, pendingStepCount; - beforeEach(function() { + beforeEach(function () { stepCount = 34; passedStepCount = 31; failedStepCount = 7; skippedStepCount = 5; undefinedStepCount = 4; pendingStepCount = 2; - spyOn(listener, 'log'); - spyOn(listener, 'getStepCount').andReturn(stepCount); - spyOn(listener, 'getPassedStepCount').andReturn(passedStepCount); - spyOn(listener, 'getFailedStepCount').andReturn(failedStepCount); - spyOn(listener, 'getSkippedStepCount').andReturn(skippedStepCount); - spyOn(listener, 'getUndefinedStepCount').andReturn(undefinedStepCount); - spyOn(listener, 'getPendingStepCount').andReturn(pendingStepCount); + spyOn(progressFormatter, 'log'); + spyOnStub(statsJournal, 'getStepCount').andReturn(stepCount); + spyOnStub(statsJournal, 'getPassedStepCount').andReturn(passedStepCount); + spyOnStub(statsJournal, 'getFailedStepCount').andReturn(failedStepCount); + spyOnStub(statsJournal, 'getSkippedStepCount').andReturn(skippedStepCount); + spyOnStub(statsJournal, 'getUndefinedStepCount').andReturn(undefinedStepCount); + spyOnStub(statsJournal, 'getPendingStepCount').andReturn(pendingStepCount); }); - it("gets the number of steps", function() { - listener.logStepsSummary(); - expect(listener.getStepCount).toHaveBeenCalled(); + it("gets the number of steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getStepCount).toHaveBeenCalled(); }); - describe("when there are no steps", function() { - beforeEach(function() { - listener.getStepCount.andReturn(0); + describe("when there are no steps", function () { + beforeEach(function () { + statsJournal.getStepCount.andReturn(0); }); - it("logs 0 steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/0 steps/); + it("logs 0 steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/0 steps/); }); - it("does not log any details", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/\(.*\)/); + it("does not log any details", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/\(.*\)/); }); }); - describe("when there are steps", function() { - beforeEach(function() { listener.getStepCount.andReturn(13); }); + describe("when there are steps", function () { + beforeEach(function () { statsJournal.getStepCount.andReturn(13); }); - describe("when there is one step", function() { - beforeEach(function() { - listener.getStepCount.andReturn(1); + describe("when there is one step", function () { + beforeEach(function () { + statsJournal.getStepCount.andReturn(1); }); - it("logs 1 step", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 step/); + it("logs 1 step", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 step/); }); }); - describe("when there are two or more steps", function() { - beforeEach(function() { - listener.getStepCount.andReturn(2); + describe("when there are two or more steps", function () { + beforeEach(function () { + statsJournal.getStepCount.andReturn(2); }); - it("logs the number of steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 steps/); + it("logs the number of steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 steps/); }); }); - it("gets the number of failed steps", function() { - listener.logStepsSummary(); - expect(listener.getFailedStepCount).toHaveBeenCalled(); + it("gets the number of failed steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getFailedStepCount).toHaveBeenCalled(); }); - describe("when there are no failed steps", function() { - beforeEach(function() { - listener.getFailedStepCount.andReturn(0); + describe("when there are no failed steps", function () { + beforeEach(function () { + statsJournal.getFailedStepCount.andReturn(0); }); - it("does not log failed steps", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/failed/); + it("does not log failed steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/failed/); }); }); - describe("when there is one failed step", function() { - beforeEach(function() { - listener.getFailedStepCount.andReturn(1); + describe("when there is one failed step", function () { + beforeEach(function () { + statsJournal.getFailedStepCount.andReturn(1); }); - it("logs one failed step", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 failed/); + it("logs one failed step", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 failed/); }); }); - describe("when there is two or more failed steps", function() { - beforeEach(function() { - listener.getFailedStepCount.andReturn(2); + describe("when there is two or more failed steps", function () { + beforeEach(function () { + statsJournal.getFailedStepCount.andReturn(2); }); - it("logs the number of failed steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 failed/); + it("logs the number of failed steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 failed/); }); }); - it("gets the number of undefined steps", function() { - listener.logStepsSummary(); - expect(listener.getUndefinedStepCount).toHaveBeenCalled(); + it("gets the number of undefined steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getUndefinedStepCount).toHaveBeenCalled(); }); - describe("when there are no undefined steps", function() { - beforeEach(function() { - listener.getUndefinedStepCount.andReturn(0); + describe("when there are no undefined steps", function () { + beforeEach(function () { + statsJournal.getUndefinedStepCount.andReturn(0); }); - it("does not log undefined steps", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/undefined/); + it("does not log undefined steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/undefined/); }); }); - describe("when there is one undefined step", function() { - beforeEach(function() { - listener.getUndefinedStepCount.andReturn(1); + describe("when there is one undefined step", function () { + beforeEach(function () { + statsJournal.getUndefinedStepCount.andReturn(1); }); - it("logs one undefined steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 undefined/); + it("logs one undefined steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 undefined/); }); }); - describe("when there are two or more undefined steps", function() { - beforeEach(function() { - listener.getUndefinedStepCount.andReturn(2); + describe("when there are two or more undefined steps", function () { + beforeEach(function () { + statsJournal.getUndefinedStepCount.andReturn(2); }); - it("logs the number of undefined steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 undefined/); + it("logs the number of undefined steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 undefined/); }); }); - it("gets the number of pending steps", function() { - listener.logStepsSummary(); - expect(listener.getPendingStepCount).toHaveBeenCalled(); + it("gets the number of pending steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getPendingStepCount).toHaveBeenCalled(); }); - describe("when there are no pending steps", function() { - beforeEach(function() { - listener.getPendingStepCount.andReturn(0); + describe("when there are no pending steps", function () { + beforeEach(function () { + statsJournal.getPendingStepCount.andReturn(0); }); - it("does not log pending steps", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/pending/); + it("does not log pending steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/pending/); }); }); - describe("when there is one pending step", function() { - beforeEach(function() { - listener.getPendingStepCount.andReturn(1); + describe("when there is one pending step", function () { + beforeEach(function () { + statsJournal.getPendingStepCount.andReturn(1); }); - it("logs one pending steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 pending/); + it("logs one pending steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 pending/); }); }); - describe("when there are two or more pending steps", function() { - beforeEach(function() { - listener.getPendingStepCount.andReturn(2); + describe("when there are two or more pending steps", function () { + beforeEach(function () { + statsJournal.getPendingStepCount.andReturn(2); }); - it("logs the number of pending steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 pending/); + it("logs the number of pending steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 pending/); }); }); - it("gets the number of skipped steps", function() { - listener.logStepsSummary(); - expect(listener.getSkippedStepCount).toHaveBeenCalled(); + it("gets the number of skipped steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getSkippedStepCount).toHaveBeenCalled(); }); - describe("when there are no skipped steps", function() { - beforeEach(function() { - listener.getSkippedStepCount.andReturn(0); + describe("when there are no skipped steps", function () { + beforeEach(function () { + statsJournal.getSkippedStepCount.andReturn(0); }); - it("does not log skipped steps", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/skipped/); + it("does not log skipped steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/skipped/); }); }); - describe("when there is one skipped step", function() { - beforeEach(function() { - listener.getSkippedStepCount.andReturn(1); + describe("when there is one skipped step", function () { + beforeEach(function () { + statsJournal.getSkippedStepCount.andReturn(1); }); - it("logs one skipped steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 skipped/); + it("logs one skipped steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 skipped/); }); }); - describe("when there are two or more skipped steps", function() { - beforeEach(function() { - listener.getSkippedStepCount.andReturn(2); + describe("when there are two or more skipped steps", function () { + beforeEach(function () { + statsJournal.getSkippedStepCount.andReturn(2); }); - it("logs the number of skipped steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 skipped/); + it("logs the number of skipped steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 skipped/); }); }); - it("gets the number of passed steps", function() { - listener.logStepsSummary(); - expect(listener.getPassedStepCount).toHaveBeenCalled(); + it("gets the number of passed steps", function () { + progressFormatter.logStepsSummary(); + expect(statsJournal.getPassedStepCount).toHaveBeenCalled(); }); - describe("when there are no passed steps", function() { - beforeEach(function() { - listener.getPassedStepCount.andReturn(0); + describe("when there are no passed steps", function () { + beforeEach(function () { + statsJournal.getPassedStepCount.andReturn(0); }); - it("does not log passed steps", function() { - listener.logStepsSummary(); - expect(listener.log).not.toHaveBeenCalledWithStringMatching(/passed/); + it("does not log passed steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).not.toHaveBeenCalledWithStringMatching(/passed/); }); }); - describe("when there is one passed step", function() { - beforeEach(function() { - listener.getPassedStepCount.andReturn(1); + describe("when there is one passed step", function () { + beforeEach(function () { + statsJournal.getPassedStepCount.andReturn(1); }); - it("logs one passed step", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/1 passed/); + it("logs one passed step", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/1 passed/); }); }); - describe("when there is two or more passed steps", function() { - beforeEach(function() { - listener.getPassedStepCount.andReturn(2); + describe("when there is two or more passed steps", function () { + beforeEach(function () { + statsJournal.getPassedStepCount.andReturn(2); }); - it("logs the number of passed steps", function() { - listener.logStepsSummary(); - expect(listener.log).toHaveBeenCalledWithStringMatching(/2 passed/); + it("logs the number of passed steps", function () { + progressFormatter.logStepsSummary(); + expect(progressFormatter.log).toHaveBeenCalledWithStringMatching(/2 passed/); }); }); }); }); - describe("logUndefinedStepSnippets()", function() { + describe("logUndefinedStepSnippets()", function () { var undefinedStepLogBuffer; - beforeEach(function() { + beforeEach(function () { undefinedStepLogBuffer = createSpy("undefined step log buffer"); - spyOn(listener, 'log'); - spyOn(listener, 'getUndefinedStepLogBuffer').andReturn(undefinedStepLogBuffer); - }); - - it("logs a little explanation about the snippets", function() { - listener.logUndefinedStepSnippets(); - expect(listener.log).toHaveBeenCalledWith("\nYou can implement step definitions for undefined steps with these snippets:\n\n"); - }); - - it("gets the undefined steps log buffer", function() { - listener.logUndefinedStepSnippets(); - expect(listener.getUndefinedStepLogBuffer).toHaveBeenCalled(); + spyOn(progressFormatter, 'log'); + spyOn(progressFormatter, 'getUndefinedStepLogBuffer').andReturn(undefinedStepLogBuffer); }); - it("logs the undefined steps", function() { - listener.logUndefinedStepSnippets(); - expect(listener.log).toHaveBeenCalledWith(undefinedStepLogBuffer); + it("logs a little explanation about the snippets", function () { + progressFormatter.logUndefinedStepSnippets(); + expect(progressFormatter.log).toHaveBeenCalledWith("\nYou can implement step definitions for undefined steps with these snippets:\n\n"); }); - }); - - describe("getScenarioCount()", function() { - var passedScenarioCount, undefinedScenarioCount, pendingScenarioCount, failedScenarioCount; - - beforeEach(function() { - passedScenarioCount = Math.floor(Math.random()*11) + 1; - undefinedScenarioCount = Math.floor(Math.random()*11) + 1; - pendingScenarioCount = Math.floor(Math.random()*11) + 1; - failedScenarioCount = Math.floor(Math.random()*11) + 1; - spyOn(listener, 'getPassedScenarioCount').andReturn(passedScenarioCount); - spyOn(listener, 'getUndefinedScenarioCount').andReturn(undefinedScenarioCount); - spyOn(listener, 'getPendingScenarioCount').andReturn(pendingScenarioCount); - spyOn(listener, 'getFailedScenarioCount').andReturn(failedScenarioCount); - }); - - it("gets the number of passed scenarios", function() { - listener.getScenarioCount(); - expect(listener.getPassedScenarioCount).toHaveBeenCalled(); - }); - - it("gets the number of undefined scenarios", function() { - listener.getScenarioCount(); - expect(listener.getUndefinedScenarioCount).toHaveBeenCalled(); - }); - - it("gets the number of pending scenarios", function() { - listener.getScenarioCount(); - expect(listener.getPendingScenarioCount).toHaveBeenCalled(); - }); - - it("gets the number of failed scenarios", function() { - listener.getScenarioCount(); - expect(listener.getFailedScenarioCount).toHaveBeenCalled(); - }); - - it("returns the sum of passed, undefined, pending aand failed scenarios", function() { - expect(listener.getScenarioCount()).toBe(passedScenarioCount + undefinedScenarioCount + pendingScenarioCount + failedScenarioCount); - }); - }); - - describe("getStepCount()", function() { - var passedStepCount, undefinedStepCount, skippedStepCount, pendingStepCount, failedStepCount, stepCount; - - beforeEach(function() { - passedStepCount = Math.floor(Math.random()*11) + 1; - undefinedStepCount = Math.floor(Math.random()*11) + 1; - skippedStepCount = Math.floor(Math.random()*11) + 1; - pendingStepCount = Math.floor(Math.random()*11) + 1; - failedStepCount = Math.floor(Math.random()*11) + 1; - stepCount = - undefinedStepCount + - passedStepCount + - skippedStepCount + - pendingStepCount + - failedStepCount; - spyOn(listener, 'getPassedStepCount').andReturn(passedStepCount); - spyOn(listener, 'getUndefinedStepCount').andReturn(undefinedStepCount); - spyOn(listener, 'getSkippedStepCount').andReturn(skippedStepCount); - spyOn(listener, 'getPendingStepCount').andReturn(pendingStepCount); - spyOn(listener, 'getFailedStepCount').andReturn(failedStepCount); - }); - - it("gets the number of passed steps", function() { - listener.getStepCount(); - expect(listener.getPassedStepCount).toHaveBeenCalled(); - }); - - it("gets the number of undefined steps", function() { - listener.getStepCount(); - expect(listener.getUndefinedStepCount).toHaveBeenCalled(); - }); - - it("gets the number of skipped steps", function() { - listener.getStepCount(); - expect(listener.getSkippedStepCount).toHaveBeenCalled(); - }); - - it("gets the number of pending steps", function() { - listener.getStepCount(); - expect(listener.getPendingStepCount).toHaveBeenCalled(); - }); - - it("gets the number of failed steps", function() { - listener.getStepCount(); - expect(listener.getFailedStepCount).toHaveBeenCalled(); - }); - - it("returns the sum of passed steps and failed steps", function() { - expect(listener.getStepCount()).toBe(stepCount); - }); - }); - - describe("passed scenario counting", function() { - describe("witnessPassedScenario()", function() { - it("counts one more passed scenario", function() { - var beforeCountOne = listener.getPassedScenarioCount(); - listener.witnessPassedScenario(); - expect(listener.getPassedScenarioCount()).toBe(beforeCountOne + 1); - }); - }); - - describe("getPassedScenarioCount()", function() { - it("returns 0 when no scenario passed", function() { - expect(listener.getPassedScenarioCount()).toBe(0); - }); - - it("returns 1 when one scenario passed", function() { - listener.witnessPassedScenario(); - expect(listener.getPassedScenarioCount()).toBe(1); - }); - - it("returns 2 when two scenarios passed", function() { - listener.witnessPassedScenario(); - listener.witnessPassedScenario(); - expect(listener.getPassedScenarioCount()).toBe(2); - }); - - it("returns 3 when three scenarios passed", function() { - listener.witnessPassedScenario(); - listener.witnessPassedScenario(); - listener.witnessPassedScenario(); - expect(listener.getPassedScenarioCount()).toBe(3); - }); - }); - }); - - describe("undefined scenario counting", function() { - describe("getUndefinedScenarioCount()", function() { - it("returns 0 when no scenarios undefined", function() { - expect(listener.getUndefinedScenarioCount()).toBe(0); - }); - - it("returns 1 when one scenario passed", function() { - listener.witnessUndefinedScenario(); - expect(listener.getUndefinedScenarioCount()).toBe(1); - }); - - it("returns 2 when two scenarios passed", function() { - listener.witnessUndefinedScenario(); - listener.witnessUndefinedScenario(); - expect(listener.getUndefinedScenarioCount()).toBe(2); - }); - - it("returns 3 when two scenarios passed", function() { - listener.witnessUndefinedScenario(); - listener.witnessUndefinedScenario(); - listener.witnessUndefinedScenario(); - expect(listener.getUndefinedScenarioCount()).toBe(3); - }); - }); - }); - - describe("pending scenario counting", function() { - describe("getPendingScenarioCount()", function() { - it("returns 0 when no scenarios pending", function() { - expect(listener.getPendingScenarioCount()).toBe(0); - }); - - it("returns 1 when one scenario passed", function() { - listener.witnessPendingScenario(); - expect(listener.getPendingScenarioCount()).toBe(1); - }); - - it("returns 2 when two scenarios passed", function() { - listener.witnessPendingScenario(); - listener.witnessPendingScenario(); - expect(listener.getPendingScenarioCount()).toBe(2); - }); - - it("returns 3 when two scenarios passed", function() { - listener.witnessPendingScenario(); - listener.witnessPendingScenario(); - listener.witnessPendingScenario(); - expect(listener.getPendingScenarioCount()).toBe(3); - }); - }); - }); - - describe("failed scenario counting", function() { - describe("getFailedScenarioCount()", function() { - it("returns 0 when no scenarios failed", function() { - expect(listener.getFailedScenarioCount()).toBe(0); - }); - - it("returns 1 when one scenario passed", function() { - listener.witnessFailedScenario(); - expect(listener.getFailedScenarioCount()).toBe(1); - }); - - it("returns 2 when two scenarios passed", function() { - listener.witnessFailedScenario(); - listener.witnessFailedScenario(); - expect(listener.getFailedScenarioCount()).toBe(2); - }); - - it("returns 3 when two scenarios passed", function() { - listener.witnessFailedScenario(); - listener.witnessFailedScenario(); - listener.witnessFailedScenario(); - expect(listener.getFailedScenarioCount()).toBe(3); - }); - }); - }); - - describe("passed step counting", function() { - describe("witnessPassedStep()", function() { - it("counts one more passed step", function() { - var beforeCountOne = listener.getPassedStepCount(); - listener.witnessPassedStep(); - expect(listener.getPassedStepCount()).toBe(beforeCountOne + 1); - }); - }); - - describe("getPassedStepCount()", function() { - it("returns 0 when no step passed", function() { - expect(listener.getPassedStepCount()).toBe(0); - }); - - it("returns 1 when one step passed", function() { - listener.witnessPassedStep(); - expect(listener.getPassedStepCount()).toBe(1); - }); - - it("returns 2 when two steps passed", function() { - listener.witnessPassedStep(); - listener.witnessPassedStep(); - expect(listener.getPassedStepCount()).toBe(2); - }); - - it("returns 3 when three steps passed", function() { - listener.witnessPassedStep(); - listener.witnessPassedStep(); - listener.witnessPassedStep(); - expect(listener.getPassedStepCount()).toBe(3); - }); - }); - }); - - describe("failed step counting", function() { - describe("getFailedStepCount()", function() { - it("returns 0 when no steps failed", function() { - expect(listener.getFailedStepCount()).toBe(0); - }); - - it("returns 1 when one step passed", function() { - listener.witnessFailedStep(); - expect(listener.getFailedStepCount()).toBe(1); - }); - - it("returns 2 when two steps passed", function() { - listener.witnessFailedStep(); - listener.witnessFailedStep(); - expect(listener.getFailedStepCount()).toBe(2); - }); - - it("returns 3 when two steps passed", function() { - listener.witnessFailedStep(); - listener.witnessFailedStep(); - listener.witnessFailedStep(); - expect(listener.getFailedStepCount()).toBe(3); - }); - }); - }); - - describe("skipped step counting", function() { - describe("getSkippedStepCount()", function() { - it("returns 0 when no steps skipped", function() { - expect(listener.getSkippedStepCount()).toBe(0); - }); - - it("returns 1 when one step passed", function() { - listener.witnessSkippedStep(); - expect(listener.getSkippedStepCount()).toBe(1); - }); - - it("returns 2 when two steps passed", function() { - listener.witnessSkippedStep(); - listener.witnessSkippedStep(); - expect(listener.getSkippedStepCount()).toBe(2); - }); - - it("returns 3 when two steps passed", function() { - listener.witnessSkippedStep(); - listener.witnessSkippedStep(); - listener.witnessSkippedStep(); - expect(listener.getSkippedStepCount()).toBe(3); - }); - }); - }); - - describe("undefined step counting", function() { - describe("getUndefinedStepCount()", function() { - it("returns 0 when no steps undefined", function() { - expect(listener.getUndefinedStepCount()).toBe(0); - }); - - it("returns 1 when one step passed", function() { - listener.witnessUndefinedStep(); - expect(listener.getUndefinedStepCount()).toBe(1); - }); - - it("returns 2 when two steps passed", function() { - listener.witnessUndefinedStep(); - listener.witnessUndefinedStep(); - expect(listener.getUndefinedStepCount()).toBe(2); - }); - - it("returns 3 when two steps passed", function() { - listener.witnessUndefinedStep(); - listener.witnessUndefinedStep(); - listener.witnessUndefinedStep(); - expect(listener.getUndefinedStepCount()).toBe(3); - }); - }); - }); - - describe("pending step counting", function() { - describe("getPendingStepCount()", function() { - it("returns 0 when no steps pending", function() { - expect(listener.getPendingStepCount()).toBe(0); - }); - - it("returns 1 when one step passed", function() { - listener.witnessPendingStep(); - expect(listener.getPendingStepCount()).toBe(1); - }); - - it("returns 2 when two steps passed", function() { - listener.witnessPendingStep(); - listener.witnessPendingStep(); - expect(listener.getPendingStepCount()).toBe(2); - }); - - it("returns 3 when two steps passed", function() { - listener.witnessPendingStep(); - listener.witnessPendingStep(); - listener.witnessPendingStep(); - expect(listener.getPendingStepCount()).toBe(3); - }); - }); - }); - - describe("witnessedAnyFailedStep()", function() { - it("returns false when no failed step were encountered", function() { - expect(listener.witnessedAnyFailedStep()).toBeFalsy(); - }); - - it("returns true when one or more steps were witnessed", function() { - listener.witnessFailedStep(); - expect(listener.witnessedAnyFailedStep()).toBeTruthy(); - }); - }); - describe("witnessedAnyUndefinedStep()", function() { - it("returns false when no undefined step were encountered", function() { - expect(listener.witnessedAnyUndefinedStep()).toBeFalsy(); + it("gets the undefined steps log buffer", function () { + progressFormatter.logUndefinedStepSnippets(); + expect(progressFormatter.getUndefinedStepLogBuffer).toHaveBeenCalled(); }); - it("returns true when one or more steps were witnessed", function() { - listener.witnessUndefinedStep(); - expect(listener.witnessedAnyUndefinedStep()).toBeTruthy(); + it("logs the undefined steps", function () { + progressFormatter.logUndefinedStepSnippets(); + expect(progressFormatter.log).toHaveBeenCalledWith(undefinedStepLogBuffer); }); }); }); diff --git a/spec/cucumber/listener/stats_journal_spec.js b/spec/cucumber/listener/stats_journal_spec.js new file mode 100644 index 000000000..e231e4895 --- /dev/null +++ b/spec/cucumber/listener/stats_journal_spec.js @@ -0,0 +1,787 @@ +require('../../support/spec_helper'); + +describe("Cucumber.Listener.StatsJournal", function () { + var Cucumber = requireLib('cucumber'); + var statsJournal, listener; + + beforeEach(function () { + var StatsJournal = Cucumber.Listener.StatsJournal; + listener = createSpyWithStubs("listener"); + spyOn(Cucumber, 'Listener').andReturn(listener); + Cucumber.Listener.StatsJournal = StatsJournal; + statsJournal = Cucumber.Listener.StatsJournal(); + }); + + it("is based on the listener", function () { + expect(statsJournal).toBe(listener); + }); + + describe("handleStepResultEvent()", function () { + var event, callback, stepResult; + + beforeEach(function () { + stepResult = createSpyWithStubs("step result", { + isSuccessful: undefined, + isPending: undefined, + isFailed: undefined, + isSkipped: undefined, + isUndefined: undefined + }); + event = createSpyWithStubs("event", {getPayloadItem: stepResult}); + callback = createSpy("Callback"); + spyOn(statsJournal, 'handleFailedStepResult'); + }); + + it("gets the step result from the event payload", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(event.getPayloadItem).toHaveBeenCalledWith('stepResult'); + }); + + it("checks whether the step was successful or not", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(stepResult.isSuccessful).toHaveBeenCalled(); + }); + + describe("when the step passed", function () { + beforeEach(function () { + stepResult.isSuccessful.andReturn(true); + spyOn(statsJournal, 'handleSuccessfulStepResult'); + }); + + it("handles the successful step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleSuccessfulStepResult).toHaveBeenCalled(); + }); + }); + + describe("when the step did not pass", function () { + beforeEach(function () { + stepResult.isSuccessful.andReturn(false); + spyOn(statsJournal, 'handleSuccessfulStepResult'); + }); + + it("does not handle a successful step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleSuccessfulStepResult).not.toHaveBeenCalled(); + }); + + it("checks whether the step is pending", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(stepResult.isPending).toHaveBeenCalled(); + }); + + describe("when the step was pending", function () { + beforeEach(function () { + stepResult.isPending.andReturn(true); + spyOn(statsJournal, 'handlePendingStepResult'); + }); + + it("handles the pending step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handlePendingStepResult).toHaveBeenCalled(); + }); + }); + + describe("when the step was not pending", function () { + beforeEach(function () { + stepResult.isPending.andReturn(false); + spyOn(statsJournal, 'handlePendingStepResult'); + }); + + it("does not handle a pending step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handlePendingStepResult).not.toHaveBeenCalled(); + }); + + it("checks whether the step was skipped", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(stepResult.isSkipped).toHaveBeenCalled(); + }); + + describe("when the step was skipped", function () { + beforeEach(function () { + stepResult.isSkipped.andReturn(true); + spyOn(statsJournal, 'handleSkippedStepResult'); + }); + + it("handles the skipped step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleSkippedStepResult).toHaveBeenCalled(); + }); + }); + + describe("when the step was not skipped", function () { + beforeEach(function () { + stepResult.isSkipped.andReturn(false); + spyOn(statsJournal, 'handleSkippedStepResult'); + }); + + it("does not handle a skipped step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleSkippedStepResult).not.toHaveBeenCalled(); + }); + + it("checks whether the step was undefined", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(stepResult.isUndefined).toHaveBeenCalled(); + }); + + describe("when the step was undefined", function () { + beforeEach(function () { + stepResult.isUndefined.andReturn(true); + spyOn(statsJournal, 'handleUndefinedStepResult'); + }); + + it("handles the undefined step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleUndefinedStepResult).toHaveBeenCalledWith(stepResult); + }); + }); + + describe("when the step was not undefined", function () { + beforeEach(function () { + stepResult.isUndefined.andReturn(false); + spyOn(statsJournal, 'handleUndefinedStepResult'); + }); + + it("does not handle a skipped step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleSkippedStepResult).not.toHaveBeenCalled(); + }); + + it("handles a failed step result", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(statsJournal.handleFailedStepResult).toHaveBeenCalledWith(stepResult); + }); + }); + }); + }); + }); + + it("calls back", function () { + statsJournal.handleStepResultEvent(event, callback); + expect(callback).toHaveBeenCalled(); + }); + }); + + describe("handleSuccessfulStepResult()", function () { + beforeEach(function () { + spyOn(statsJournal, 'witnessPassedStep'); + }); + + it("witnesses a passed step", function () { + statsJournal.handleSuccessfulStepResult(); + expect(statsJournal.witnessPassedStep).toHaveBeenCalled(); + }); + }); + + describe("handlePendingStepResult()", function () { + beforeEach(function () { + spyOn(statsJournal, 'witnessPendingStep'); + spyOn(statsJournal, 'markCurrentScenarioAsPending'); + }); + + it("witnesses a pending step", function () { + statsJournal.handlePendingStepResult(); + expect(statsJournal.witnessPendingStep).toHaveBeenCalled(); + }); + + it("marks the current scenario as pending", function () { + statsJournal.handlePendingStepResult(); + expect(statsJournal.markCurrentScenarioAsPending).toHaveBeenCalled(); + }); + }); + + describe("handleSkippedStepResult()", function () { + beforeEach(function () { + spyOn(statsJournal, 'witnessSkippedStep'); + }); + + it("witnesses more skipped step", function () { + statsJournal.handleSkippedStepResult(); + expect(statsJournal.witnessSkippedStep).toHaveBeenCalled(); + }); + }); + + describe("handleUndefinedStepResult()", function () { + var stepResult, step; + + beforeEach(function () { + step = createSpy("step"); + stepResult = createSpyWithStubs("step result", {getStep: step}); + spyOn(statsJournal, 'witnessUndefinedStep'); + spyOn(statsJournal, 'markCurrentScenarioAsUndefined'); + }); + + it("gets the step from the step result", function () { + statsJournal.handleUndefinedStepResult(stepResult); + expect(stepResult.getStep).toHaveBeenCalled(); + }); + + it("witnesses an undefined step", function () { + statsJournal.handleUndefinedStepResult(stepResult); + expect(statsJournal.witnessUndefinedStep).toHaveBeenCalled(); + }); + + it("marks the current scenario as undefined", function () { + statsJournal.handleUndefinedStepResult(stepResult); + expect(statsJournal.markCurrentScenarioAsUndefined).toHaveBeenCalled(); + }); + }); + + describe("handleFailedStepResult()", function () { + var stepResult; + + beforeEach(function () { + stepResult = createSpy("failed step result"); + spyOn(statsJournal, 'witnessFailedStep'); + spyOn(statsJournal, 'markCurrentScenarioAsFailing'); + }); + + it("witnesses a failed step", function () { + statsJournal.handleFailedStepResult(stepResult); + expect(statsJournal.witnessFailedStep).toHaveBeenCalled(); + }); + + it("marks the current scenario as failing", function () { + statsJournal.handleFailedStepResult(stepResult); + expect(statsJournal.markCurrentScenarioAsFailing).toHaveBeenCalled(); + }); + }); + + describe("handleBeforeScenarioEvent", function () { + var event, callback; + + beforeEach(function () { + event = createSpy("event"); + callback = createSpy("callback"); + spyOn(statsJournal, 'prepareBeforeScenario'); + }); + + it("prepares for a new scenario", function () { + statsJournal.handleBeforeScenarioEvent(event, callback); + expect(statsJournal.prepareBeforeScenario).toHaveBeenCalled(); + }); + + it("calls back", function () { + statsJournal.handleBeforeScenarioEvent(event, callback); + expect(callback).toHaveBeenCalled(); + }); + }); + + describe("handleAfterScenarioEvent()", function () { + var event, callback; + + beforeEach(function () { + event = createSpy("event"); + callback = createSpy("callback"); + spyOn(statsJournal, 'isCurrentScenarioFailing'); + spyOn(statsJournal, 'witnessPassedScenario'); + spyOn(statsJournal, 'witnessUndefinedScenario'); + spyOn(statsJournal, 'witnessPendingScenario'); + spyOn(statsJournal, 'witnessFailedScenario'); + }); + + it("checks whether the current scenario failed", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.isCurrentScenarioFailing).toHaveBeenCalled(); + }); + + describe("when the current scenario failed", function () { + var scenario; + + beforeEach(function () { + scenario = createSpy("scenario"); + statsJournal.isCurrentScenarioFailing.andReturn(true); + spyOnStub(event, 'getPayloadItem').andReturn(scenario); + }); + + it("witnesses a failed scenario", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.witnessFailedScenario).toHaveBeenCalled(); + }); + + it("gets the scenario from the payload", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(event.getPayloadItem).toHaveBeenCalledWith('scenario'); + }); + }); + + describe("when the current scenario did not fail", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioFailing.andReturn(false); + spyOn(statsJournal, 'isCurrentScenarioUndefined'); + }); + + it("checks whether the current scenario is undefined", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.isCurrentScenarioUndefined).toHaveBeenCalled(); + }); + + describe("when the current scenario is undefined", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioUndefined.andReturn(true); + }); + + it("witnesses an undefined scenario", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.witnessUndefinedScenario).toHaveBeenCalled(); + }); + }); + + describe("when the current scenario is not undefined", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioUndefined.andReturn(false); + spyOn(statsJournal, 'isCurrentScenarioPending'); + }); + + it("checks whether the current scenario is pending", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.isCurrentScenarioPending).toHaveBeenCalled(); + }); + + describe("when the current scenario is pending", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioPending.andReturn(true); + }); + + it("witnesses a pending scenario", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.witnessPendingScenario).toHaveBeenCalled(); + }); + }); + + describe("when the current scenario is not pending (passed)", function () { + beforeEach(function () { + statsJournal.isCurrentScenarioPending.andReturn(false); + }); + + it("witnesses a passed scenario", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(statsJournal.witnessPassedScenario).toHaveBeenCalled(); + }); + }); + }); + }); + it("calls back", function () { + statsJournal.handleAfterScenarioEvent(event, callback); + expect(callback).toHaveBeenCalled(); + }); + }); + + describe("isCurrentScenarioFailing()", function () { + it("returns false when the current scenario did not fail yet", function () { + expect(statsJournal.isCurrentScenarioFailing()).toBeFalsy(); + }); + + it("returns true when a step in the current scenario failed", function () { + statsJournal.markCurrentScenarioAsFailing(); + expect(statsJournal.isCurrentScenarioFailing()).toBeTruthy(); + }); + }); + + describe("isCurrentScenarioPending()", function () { + it("returns false when the current scenario was not set pending yet", function () { + expect(statsJournal.isCurrentScenarioPending()).toBeFalsy(); + }); + + it("returns true when the current scenario was set pending", function () { + statsJournal.markCurrentScenarioAsPending(); + expect(statsJournal.isCurrentScenarioPending()).toBeTruthy(); + }); + }); + + describe("isCurrentScenarioUndefined()", function () { + it("returns false when the current scenario was not set undefined yet", function () { + expect(statsJournal.isCurrentScenarioUndefined()).toBeFalsy(); + }); + + it("returns true when the current scenario was set undefined", function () { + statsJournal.markCurrentScenarioAsUndefined(); + expect(statsJournal.isCurrentScenarioUndefined()).toBeTruthy(); + }); + }); + + describe("prepareBeforeScenario()", function () { + it("unmarks the current scenario as pending", function () { + statsJournal.markCurrentScenarioAsPending(); + statsJournal.prepareBeforeScenario(); + expect(statsJournal.isCurrentScenarioPending()).toBeFalsy(); + }); + + it("unmarks the current scenario as failing", function () { + statsJournal.markCurrentScenarioAsFailing(); + statsJournal.prepareBeforeScenario(); + expect(statsJournal.isCurrentScenarioFailing()).toBeFalsy(); + }); + + it("unmarks the current scenario as undefined", function () { + statsJournal.markCurrentScenarioAsUndefined(); + statsJournal.prepareBeforeScenario(); + expect(statsJournal.isCurrentScenarioUndefined()).toBeFalsy(); + }); + }); + + describe("getScenarioCount()", function () { + var passedScenarioCount, undefinedScenarioCount, pendingScenarioCount, failedScenarioCount; + + beforeEach(function () { + passedScenarioCount = Math.floor(Math.random()*11) + 1; + undefinedScenarioCount = Math.floor(Math.random()*11) + 1; + pendingScenarioCount = Math.floor(Math.random()*11) + 1; + failedScenarioCount = Math.floor(Math.random()*11) + 1; + spyOn(statsJournal, 'getPassedScenarioCount').andReturn(passedScenarioCount); + spyOn(statsJournal, 'getUndefinedScenarioCount').andReturn(undefinedScenarioCount); + spyOn(statsJournal, 'getPendingScenarioCount').andReturn(pendingScenarioCount); + spyOn(statsJournal, 'getFailedScenarioCount').andReturn(failedScenarioCount); + }); + + it("gets the number of passed scenarios", function () { + statsJournal.getScenarioCount(); + expect(statsJournal.getPassedScenarioCount).toHaveBeenCalled(); + }); + + it("gets the number of undefined scenarios", function () { + statsJournal.getScenarioCount(); + expect(statsJournal.getUndefinedScenarioCount).toHaveBeenCalled(); + }); + + it("gets the number of pending scenarios", function () { + statsJournal.getScenarioCount(); + expect(statsJournal.getPendingScenarioCount).toHaveBeenCalled(); + }); + + it("gets the number of failed scenarios", function () { + statsJournal.getScenarioCount(); + expect(statsJournal.getFailedScenarioCount).toHaveBeenCalled(); + }); + + it("returns the sum of passed, undefined, pending aand failed scenarios", function () { + expect(statsJournal.getScenarioCount()).toBe(passedScenarioCount + undefinedScenarioCount + pendingScenarioCount + failedScenarioCount); + }); + }); + + describe("getStepCount()", function () { + var passedStepCount, undefinedStepCount, skippedStepCount, pendingStepCount, failedStepCount, stepCount; + + beforeEach(function () { + passedStepCount = Math.floor(Math.random()*11) + 1; + undefinedStepCount = Math.floor(Math.random()*11) + 1; + skippedStepCount = Math.floor(Math.random()*11) + 1; + pendingStepCount = Math.floor(Math.random()*11) + 1; + failedStepCount = Math.floor(Math.random()*11) + 1; + stepCount = + undefinedStepCount + + passedStepCount + + skippedStepCount + + pendingStepCount + + failedStepCount; + spyOn(statsJournal, 'getPassedStepCount').andReturn(passedStepCount); + spyOn(statsJournal, 'getUndefinedStepCount').andReturn(undefinedStepCount); + spyOn(statsJournal, 'getSkippedStepCount').andReturn(skippedStepCount); + spyOn(statsJournal, 'getPendingStepCount').andReturn(pendingStepCount); + spyOn(statsJournal, 'getFailedStepCount').andReturn(failedStepCount); + }); + + it("gets the number of passed steps", function () { + statsJournal.getStepCount(); + expect(statsJournal.getPassedStepCount).toHaveBeenCalled(); + }); + + it("gets the number of undefined steps", function () { + statsJournal.getStepCount(); + expect(statsJournal.getUndefinedStepCount).toHaveBeenCalled(); + }); + + it("gets the number of skipped steps", function () { + statsJournal.getStepCount(); + expect(statsJournal.getSkippedStepCount).toHaveBeenCalled(); + }); + + it("gets the number of pending steps", function () { + statsJournal.getStepCount(); + expect(statsJournal.getPendingStepCount).toHaveBeenCalled(); + }); + + it("gets the number of failed steps", function () { + statsJournal.getStepCount(); + expect(statsJournal.getFailedStepCount).toHaveBeenCalled(); + }); + + it("returns the sum of passed steps and failed steps", function () { + expect(statsJournal.getStepCount()).toBe(stepCount); + }); + }); + + describe("passed scenario counting", function () { + describe("witnessPassedScenario()", function () { + it("counts one more passed scenario", function () { + var beforeCountOne = statsJournal.getPassedScenarioCount(); + statsJournal.witnessPassedScenario(); + expect(statsJournal.getPassedScenarioCount()).toBe(beforeCountOne + 1); + }); + }); + + describe("getPassedScenarioCount()", function () { + it("returns 0 when no scenario passed", function () { + expect(statsJournal.getPassedScenarioCount()).toBe(0); + }); + + it("returns 1 when one scenario passed", function () { + statsJournal.witnessPassedScenario(); + expect(statsJournal.getPassedScenarioCount()).toBe(1); + }); + + it("returns 2 when two scenarios passed", function () { + statsJournal.witnessPassedScenario(); + statsJournal.witnessPassedScenario(); + expect(statsJournal.getPassedScenarioCount()).toBe(2); + }); + + it("returns 3 when three scenarios passed", function () { + statsJournal.witnessPassedScenario(); + statsJournal.witnessPassedScenario(); + statsJournal.witnessPassedScenario(); + expect(statsJournal.getPassedScenarioCount()).toBe(3); + }); + }); + }); + + describe("undefined scenario counting", function () { + describe("getUndefinedScenarioCount()", function () { + it("returns 0 when no scenarios undefined", function () { + expect(statsJournal.getUndefinedScenarioCount()).toBe(0); + }); + + it("returns 1 when one scenario passed", function () { + statsJournal.witnessUndefinedScenario(); + expect(statsJournal.getUndefinedScenarioCount()).toBe(1); + }); + + it("returns 2 when two scenarios passed", function () { + statsJournal.witnessUndefinedScenario(); + statsJournal.witnessUndefinedScenario(); + expect(statsJournal.getUndefinedScenarioCount()).toBe(2); + }); + + it("returns 3 when two scenarios passed", function () { + statsJournal.witnessUndefinedScenario(); + statsJournal.witnessUndefinedScenario(); + statsJournal.witnessUndefinedScenario(); + expect(statsJournal.getUndefinedScenarioCount()).toBe(3); + }); + }); + }); + + describe("pending scenario counting", function () { + describe("getPendingScenarioCount()", function () { + it("returns 0 when no scenarios pending", function () { + expect(statsJournal.getPendingScenarioCount()).toBe(0); + }); + + it("returns 1 when one scenario passed", function () { + statsJournal.witnessPendingScenario(); + expect(statsJournal.getPendingScenarioCount()).toBe(1); + }); + + it("returns 2 when two scenarios passed", function () { + statsJournal.witnessPendingScenario(); + statsJournal.witnessPendingScenario(); + expect(statsJournal.getPendingScenarioCount()).toBe(2); + }); + + it("returns 3 when two scenarios passed", function () { + statsJournal.witnessPendingScenario(); + statsJournal.witnessPendingScenario(); + statsJournal.witnessPendingScenario(); + expect(statsJournal.getPendingScenarioCount()).toBe(3); + }); + }); + }); + + describe("failed scenario counting", function () { + describe("getFailedScenarioCount()", function () { + it("returns 0 when no scenarios failed", function () { + expect(statsJournal.getFailedScenarioCount()).toBe(0); + }); + + it("returns 1 when one scenario passed", function () { + statsJournal.witnessFailedScenario(); + expect(statsJournal.getFailedScenarioCount()).toBe(1); + }); + + it("returns 2 when two scenarios passed", function () { + statsJournal.witnessFailedScenario(); + statsJournal.witnessFailedScenario(); + expect(statsJournal.getFailedScenarioCount()).toBe(2); + }); + + it("returns 3 when two scenarios passed", function () { + statsJournal.witnessFailedScenario(); + statsJournal.witnessFailedScenario(); + statsJournal.witnessFailedScenario(); + expect(statsJournal.getFailedScenarioCount()).toBe(3); + }); + }); + }); + + describe("passed step counting", function () { + describe("witnessPassedStep()", function () { + it("counts one more passed step", function () { + var beforeCountOne = statsJournal.getPassedStepCount(); + statsJournal.witnessPassedStep(); + expect(statsJournal.getPassedStepCount()).toBe(beforeCountOne + 1); + }); + }); + + describe("getPassedStepCount()", function () { + it("returns 0 when no step passed", function () { + expect(statsJournal.getPassedStepCount()).toBe(0); + }); + + it("returns 1 when one step passed", function () { + statsJournal.witnessPassedStep(); + expect(statsJournal.getPassedStepCount()).toBe(1); + }); + + it("returns 2 when two steps passed", function () { + statsJournal.witnessPassedStep(); + statsJournal.witnessPassedStep(); + expect(statsJournal.getPassedStepCount()).toBe(2); + }); + + it("returns 3 when three steps passed", function () { + statsJournal.witnessPassedStep(); + statsJournal.witnessPassedStep(); + statsJournal.witnessPassedStep(); + expect(statsJournal.getPassedStepCount()).toBe(3); + }); + }); + }); + + describe("failed step counting", function () { + describe("getFailedStepCount()", function () { + it("returns 0 when no steps failed", function () { + expect(statsJournal.getFailedStepCount()).toBe(0); + }); + + it("returns 1 when one step passed", function () { + statsJournal.witnessFailedStep(); + expect(statsJournal.getFailedStepCount()).toBe(1); + }); + + it("returns 2 when two steps passed", function () { + statsJournal.witnessFailedStep(); + statsJournal.witnessFailedStep(); + expect(statsJournal.getFailedStepCount()).toBe(2); + }); + + it("returns 3 when two steps passed", function () { + statsJournal.witnessFailedStep(); + statsJournal.witnessFailedStep(); + statsJournal.witnessFailedStep(); + expect(statsJournal.getFailedStepCount()).toBe(3); + }); + }); + }); + + describe("skipped step counting", function () { + describe("getSkippedStepCount()", function () { + it("returns 0 when no steps skipped", function () { + expect(statsJournal.getSkippedStepCount()).toBe(0); + }); + + it("returns 1 when one step passed", function () { + statsJournal.witnessSkippedStep(); + expect(statsJournal.getSkippedStepCount()).toBe(1); + }); + + it("returns 2 when two steps passed", function () { + statsJournal.witnessSkippedStep(); + statsJournal.witnessSkippedStep(); + expect(statsJournal.getSkippedStepCount()).toBe(2); + }); + + it("returns 3 when two steps passed", function () { + statsJournal.witnessSkippedStep(); + statsJournal.witnessSkippedStep(); + statsJournal.witnessSkippedStep(); + expect(statsJournal.getSkippedStepCount()).toBe(3); + }); + }); + }); + + describe("undefined step counting", function () { + describe("getUndefinedStepCount()", function () { + it("returns 0 when no steps undefined", function () { + expect(statsJournal.getUndefinedStepCount()).toBe(0); + }); + + it("returns 1 when one step passed", function () { + statsJournal.witnessUndefinedStep(); + expect(statsJournal.getUndefinedStepCount()).toBe(1); + }); + + it("returns 2 when two steps passed", function () { + statsJournal.witnessUndefinedStep(); + statsJournal.witnessUndefinedStep(); + expect(statsJournal.getUndefinedStepCount()).toBe(2); + }); + + it("returns 3 when two steps passed", function () { + statsJournal.witnessUndefinedStep(); + statsJournal.witnessUndefinedStep(); + statsJournal.witnessUndefinedStep(); + expect(statsJournal.getUndefinedStepCount()).toBe(3); + }); + }); + }); + + describe("pending step counting", function () { + describe("getPendingStepCount()", function () { + it("returns 0 when no steps pending", function () { + expect(statsJournal.getPendingStepCount()).toBe(0); + }); + + it("returns 1 when one step passed", function () { + statsJournal.witnessPendingStep(); + expect(statsJournal.getPendingStepCount()).toBe(1); + }); + + it("returns 2 when two steps passed", function () { + statsJournal.witnessPendingStep(); + statsJournal.witnessPendingStep(); + expect(statsJournal.getPendingStepCount()).toBe(2); + }); + + it("returns 3 when two steps passed", function () { + statsJournal.witnessPendingStep(); + statsJournal.witnessPendingStep(); + statsJournal.witnessPendingStep(); + expect(statsJournal.getPendingStepCount()).toBe(3); + }); + }); + }); + + describe("witnessedAnyFailedStep()", function () { + it("returns false when no failed step were encountered", function () { + expect(statsJournal.witnessedAnyFailedStep()).toBeFalsy(); + }); + + it("returns true when one or more steps were witnessed", function () { + statsJournal.witnessFailedStep(); + expect(statsJournal.witnessedAnyFailedStep()).toBeTruthy(); + }); + }); + + describe("witnessedAnyUndefinedStep()", function () { + it("returns false when no undefined step were encountered", function () { + expect(statsJournal.witnessedAnyUndefinedStep()).toBeFalsy(); + }); + + it("returns true when one or more steps were witnessed", function () { + statsJournal.witnessUndefinedStep(); + expect(statsJournal.witnessedAnyUndefinedStep()).toBeTruthy(); + }); + }); +}); diff --git a/spec/cucumber/listener_spec.js b/spec/cucumber/listener_spec.js new file mode 100644 index 000000000..94578a41d --- /dev/null +++ b/spec/cucumber/listener_spec.js @@ -0,0 +1,148 @@ +require('../support/spec_helper'); + +describe("Cucumber.Listener", function() { + var Cucumber = requireLib('cucumber'); + + beforeEach(function() { + listener = Cucumber.Listener(); + }); + + describe("hear()", function () { + var event, callback; + var eventHandler; + + beforeEach(function () { + event = createSpy("event"); + callback = createSpy("callback"); + spyOn(listener, 'hasHandlerForEvent'); + spyOn(listener, 'getHandlerForEvent'); + }); + + it("checks whether there is a handler for the event", function () { + listener.hear(event, callback); + expect(listener.hasHandlerForEvent).toHaveBeenCalledWith(event); + }); + + describe("when there is a handler for that event", function () { + beforeEach(function () { + eventHandler = createSpy("Event handler (function)"); + listener.hasHandlerForEvent.andReturn(true); + listener.getHandlerForEvent.andReturn(eventHandler); + }); + + it("gets the handler for that event", function () { + listener.hear(event, callback); + expect(listener.getHandlerForEvent).toHaveBeenCalledWith(event); + }); + + it("calls the handler with the event and the callback", function () { + listener.hear(event, callback); + expect(eventHandler).toHaveBeenCalledWith(event, callback); + }); + + it("does not callback", function () { + listener.hear(event, callback); + expect(callback).not.toHaveBeenCalled(); + }); + }); + + describe("when there are no handlers for that event", function () { + beforeEach(function () { + listener.hasHandlerForEvent.andReturn(false); + }); + + it("calls back", function () { + listener.hear(event, callback); + expect(callback).toHaveBeenCalled(); + }); + + it("does not get the handler for the event", function () { + listener.hear(event, callback); + expect(listener.getHandlerForEvent).not.toHaveBeenCalled(); + }); + }); + }); + + describe("hasHandlerForEvent", function () { + var event, eventHandlerName, eventHandler; + + beforeEach(function () { + event = createSpy("Event"); + eventHandlerName = createSpy("event handler name"); + spyOn(listener, 'buildHandlerNameForEvent').andReturn(eventHandlerName); + }); + + it("builds the name of the handler for that event", function () { + listener.hasHandlerForEvent(event); + expect(listener.buildHandlerNameForEvent).toHaveBeenCalledWith(event); + }); + + describe("when the handler exists", function () { + beforeEach(function () { + eventHandler = createSpy("event handler"); + listener[eventHandlerName] = eventHandler; + }); + + it("returns true", function () { + expect(listener.hasHandlerForEvent(event)).toBeTruthy(); + }); + }); + + describe("when the handler does not exist", function () { + it("returns false", function () { + expect(listener.hasHandlerForEvent(event)).toBeFalsy(); + }); + }); + }); + + describe("buildHandlerNameForEvent", function () { + var event, eventName; + + beforeEach(function () { + eventName = "SomeEventName"; + event = createSpyWithStubs("Event", {getName: eventName}); + }); + + 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"); + }); + }); + + describe("getHandlerForEvent()", function () { + var event; + var eventHandlerName, eventHandler; + + beforeEach(function () { + event = createSpy("event"); + eventHandlerName = 'handleSomeEvent'; + eventHandler = createSpy("event handler"); + spyOn(listener, 'buildHandlerNameForEvent').andReturn(eventHandlerName); + }); + + it("gets the name of the handler for the event", function () { + listener.getHandlerForEvent(event); + expect(listener.buildHandlerNameForEvent).toHaveBeenCalledWith(event); + }); + + describe("when an event handler exists for the event", function () { + beforeEach(function () { + listener[eventHandlerName] = eventHandler; + }); + + it("returns the event handler", function () { + expect(listener.getHandlerForEvent(event)).toBe(eventHandler); + }); + }); + + describe("when no event handlers exist for the event", function () { + it("returns nothing", function () { + expect(listener.getHandlerForEvent(event)).toBeUndefined(); + }); + }); + }); +}); diff --git a/spec/cucumber/runtime/ast_tree_walker_spec.js b/spec/cucumber/runtime/ast_tree_walker_spec.js index bf3b8a2d5..88f903d4e 100644 --- a/spec/cucumber/runtime/ast_tree_walker_spec.js +++ b/spec/cucumber/runtime/ast_tree_walker_spec.js @@ -38,7 +38,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { spyOn(treeWalker, 'didAllFeaturesSucceed').andReturn(featuresResult); }); - it("checks wether all features were successful", function() { + it("checks whether all features were successful", function() { featuresVisitCallback(); expect(treeWalker.didAllFeaturesSucceed).toHaveBeenCalled(); }); @@ -308,7 +308,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { expect(treeWalker.broadcastEvent).toHaveBeenCalledWith(event, callback); }); - it("checks wether the step failed or not", function() { + it("checks whether the step failed or not", function() { treeWalker.visitStepResult(stepResult, callback); expect(stepResult.isFailed).toHaveBeenCalled(); }); @@ -335,7 +335,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { expect(treeWalker.witnessFailedStep).not.toHaveBeenCalled(); }); - it("checks wether the step was pending or not", function() { + it("checks whether the step was pending or not", function() { treeWalker.visitStepResult(stepResult, callback); expect(stepResult.isPending).toHaveBeenCalled(); }); @@ -579,7 +579,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { expect(step.getName).toHaveBeenCalled(); }); - it("asks the support code library wether a step definition is defined for that name", function() { + it("asks the support code library whether a step definition is defined for that name", function() { treeWalker.isStepUndefined(step); expect(supportCodeLibrary.isStepDefinitionNameDefined).toHaveBeenCalledWith(stepName); }); @@ -668,7 +668,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { spyOn(treeWalker, 'skipStep'); }); - it("checks wether the step is undefined or not", function() { + it("checks whether the step is undefined or not", function() { treeWalker.processStep(step, callback); expect(treeWalker.isStepUndefined).toHaveBeenCalledWith(step); }); @@ -705,7 +705,7 @@ describe("Cucumber.Runtime.AstTreeWalker", function() { treeWalker.isStepUndefined.andReturn(false); }); - it("checks wether the step should be skipped", function() { + it("checks whether the step should be skipped", function() { treeWalker.processStep(step, callback); expect(treeWalker.isSkippingSteps).toHaveBeenCalled(); }); diff --git a/spec/cucumber/support_code/hook_spec.js b/spec/cucumber/support_code/hook_spec.js index a2cbde5ae..ef551e1f1 100644 --- a/spec/cucumber/support_code/hook_spec.js +++ b/spec/cucumber/support_code/hook_spec.js @@ -20,7 +20,7 @@ describe("Cucumber.SupportCode.Hook", function() { spyOn(hook, 'appliesToScenario'); }); - it("checks wether the hook applies to this scenario or not", function() { + it("checks whether the hook applies to this scenario or not", function() { hook.invokeBesideScenario(scenario, world, callback); expect(hook.appliesToScenario).toHaveBeenCalledWith(scenario); }); @@ -90,7 +90,7 @@ describe("Cucumber.SupportCode.Hook", function() { expect(hook.getAstFilter).toHaveBeenCalled(); }); - it("asks the AST filter wether the scenario is enrolled or not", function() { + it("asks the AST filter whether the scenario is enrolled or not", function() { hook.appliesToScenario(scenario); expect(astFilter.isScenarioEnrolled).toHaveBeenCalledWith(scenario); }); diff --git a/spec/cucumber/support_code/step_definition_snippet_builder_spec.js b/spec/cucumber/support_code/step_definition_snippet_builder_spec.js index 9e844037a..cd41649ac 100644 --- a/spec/cucumber/support_code/step_definition_snippet_builder_spec.js +++ b/spec/cucumber/support_code/step_definition_snippet_builder_spec.js @@ -60,7 +60,7 @@ describe("Cucumber.SupportCode.StepDefinitionSnippetBuilder", function() { spyOnStub(step, 'isEventStep'); }); - it("checks wether the step is a context step", function() { + it("checks whether the step is a context step", function() { snippetBuilder.buildStepDefinitionFunctionName(); expect(step.isOutcomeStep).toHaveBeenCalled(); }); @@ -80,7 +80,7 @@ describe("Cucumber.SupportCode.StepDefinitionSnippetBuilder", function() { step.isOutcomeStep.andReturn(false); }); - it("checks wether the step is an event step", function() { + it("checks whether the step is an event step", function() { snippetBuilder.buildStepDefinitionFunctionName(); expect(step.isEventStep).toHaveBeenCalled(); }); @@ -183,12 +183,12 @@ describe("Cucumber.SupportCode.StepDefinitionSnippetBuilder", function() { expect(snippetBuilder.getStepDefinitionPatternMatchingGroupParameters).toHaveBeenCalled(); }); - it("checks wether the step has a doc string attached or not", function() { + it("checks whether the step has a doc string attached or not", function() { snippetBuilder.buildStepDefinitionParameters(); expect(step.hasDocString).toHaveBeenCalled(); }); - it("checks wether the step has a data table attached or not", function() { + it("checks whether the step has a data table attached or not", function() { snippetBuilder.buildStepDefinitionParameters(); expect(step.hasDataTable).toHaveBeenCalled(); }); diff --git a/spec/cucumber/support_code/step_definition_spec.js b/spec/cucumber/support_code/step_definition_spec.js index d43271c38..0ad90b5e4 100644 --- a/spec/cucumber/support_code/step_definition_spec.js +++ b/spec/cucumber/support_code/step_definition_spec.js @@ -266,7 +266,7 @@ describe("Cucumber.SupportCode.StepDefinition", function() { expect(matches.shift).toHaveBeenCalled(); }); - it("checks wether the step has an attachment or not", function() { + it("checks whether the step has an attachment or not", function() { stepDefinition.buildInvocationParameters(step, callback); expect(step.hasAttachment).toHaveBeenCalled(); });