From 4fba75bb80990e802afbfc973fc3e666aa736ccf Mon Sep 17 00:00:00 2001 From: Stefan Jansen Date: Tue, 27 May 2014 21:47:38 +0200 Subject: [PATCH] Added support for writing output to file (close #90) --- lib/cucumber/cli/argument_parser.js | 7 +++ lib/cucumber/cli/configuration.js | 4 ++ lib/cucumber/runtime.js | 22 +++++++- lib/cucumber/volatile_configuration.js | 5 ++ spec/cucumber/cli/argument_parser_spec.js | 23 +++++++++ spec/cucumber/cli/configuration_spec.js | 17 +++++++ spec/cucumber/runtime_spec.js | 51 ++++++++++++++++++- spec/cucumber/volatile_configuration_spec.js | 16 +++++- .../support/configurations_shared_examples.js | 4 ++ 9 files changed, 145 insertions(+), 4 deletions(-) diff --git a/lib/cucumber/cli/argument_parser.js b/lib/cucumber/cli/argument_parser.js index d13c731d40..ccd87a2320 100644 --- a/lib/cucumber/cli/argument_parser.js +++ b/lib/cucumber/cli/argument_parser.js @@ -62,11 +62,17 @@ var ArgumentParser = function(argv) { return format; }, + getReportFile: function getReportFile() { + var reportFile = self.getOptionOrDefault(ArgumentParser.REPORT_FILE_OPTION_NAME, null); + return reportFile; + }, + getKnownOptionDefinitions: function getKnownOptionDefinitions() { var definitions = {}; definitions[ArgumentParser.REQUIRE_OPTION_NAME] = [path, Array]; definitions[ArgumentParser.TAGS_OPTION_NAME] = [String, Array]; definitions[ArgumentParser.FORMAT_OPTION_NAME] = String; + definitions[ArgumentParser.REPORT_FILE_OPTION_NAME] = String; definitions[ArgumentParser.HELP_FLAG_NAME] = Boolean; definitions[ArgumentParser.VERSION_FLAG_NAME] = Boolean; definitions[ArgumentParser.COFFEE_SCRIPT_SNIPPETS_FLAG_NAME] = Boolean; @@ -124,6 +130,7 @@ ArgumentParser.FORMAT_OPTION_SHORT_NAME = "f"; ArgumentParser.DEFAULT_FORMAT_VALUE = "progress"; ArgumentParser.TAGS_OPTION_NAME = "tags"; ArgumentParser.TAGS_OPTION_SHORT_NAME = "t"; +ArgumentParser.REPORT_FILE_OPTION_NAME = "report"; ArgumentParser.HELP_FLAG_NAME = "help"; ArgumentParser.HELP_FLAG_SHORT_NAME = "h"; ArgumentParser.DEFAULT_HELP_FLAG_VALUE = false; diff --git a/lib/cucumber/cli/configuration.js b/lib/cucumber/cli/configuration.js index d10d79df65..1f8176005d 100644 --- a/lib/cucumber/cli/configuration.js +++ b/lib/cucumber/cli/configuration.js @@ -64,6 +64,10 @@ var Configuration = function(argv) { return rule; }, + getReportFile: function getReportFile() { + return argumentParser.getReportFile(); + }, + isHelpRequested: function isHelpRequested() { var isHelpRequested = argumentParser.isHelpRequested(); return isHelpRequested; diff --git a/lib/cucumber/runtime.js b/lib/cucumber/runtime.js index 4b8d1371b1..be8e729588 100644 --- a/lib/cucumber/runtime.js +++ b/lib/cucumber/runtime.js @@ -1,6 +1,9 @@ var Runtime = function(configuration) { var Cucumber = require('../cucumber'); + var fs = require('fs'); + + var callback; var listeners = Cucumber.Type.Collection(); var self = { @@ -10,13 +13,30 @@ var Runtime = function(configuration) { var features = self.getFeatures(); var supportCodeLibrary = self.getSupportCodeLibrary(); var astTreeWalker = Runtime.AstTreeWalker(features, supportCodeLibrary, listeners); - astTreeWalker.walk(callback); + + self.setCallback(callback); + astTreeWalker.walk(self.finish); + }, + + finish: function finish(result) { + if (configuration.getReportFile() !== null) { + fs.writeFileSync(configuration.getReportFile(), listeners.getLast().getLogs(), { flag: 'w' }); + } + self.getCallback()(result); }, attachListener: function attachListener(listener) { listeners.add(listener); }, + setCallback: function setCallback(newCallback) { + callback = newCallback; + }, + + getCallback: function getCallback() { + return callback; + }, + getFeatures: function getFeatures() { var featureSources = configuration.getFeatureSources(); var astFilter = configuration.getAstFilter(); diff --git a/lib/cucumber/volatile_configuration.js b/lib/cucumber/volatile_configuration.js index 82f7fb908e..6ec73abb52 100644 --- a/lib/cucumber/volatile_configuration.js +++ b/lib/cucumber/volatile_configuration.js @@ -4,6 +4,7 @@ var VolatileConfiguration = function VolatileConfiguration(features, supportCode options = options || {}; var tagGroupStrings = options['tags'] || []; + var reportFile = options['report'] || null; var self = { getFeatureSources: function getFeatureSources() { @@ -39,6 +40,10 @@ var VolatileConfiguration = function VolatileConfiguration(features, supportCode var tagGroup = tagGroupParser.parse(); var rule = Cucumber.Ast.Filter.AnyOfTagsRule(tagGroup); return rule; + }, + + getReportFile: function getReportFile() { + return reportFile; } }; return self; diff --git a/spec/cucumber/cli/argument_parser_spec.js b/spec/cucumber/cli/argument_parser_spec.js index 34bdc83807..3ebb2d5426 100644 --- a/spec/cucumber/cli/argument_parser_spec.js +++ b/spec/cucumber/cli/argument_parser_spec.js @@ -69,6 +69,11 @@ describe("Cucumber.Cli.ArgumentParser", function () { expect(knownOptionDefinitions[Cucumber.Cli.ArgumentParser.FORMAT_OPTION_NAME]).toEqual(String); }); + it("defines a --report flag", function () { + var knownOptionDefinitions = argumentParser.getKnownOptionDefinitions(); + expect(knownOptionDefinitions[Cucumber.Cli.ArgumentParser.REPORT_FILE_OPTION_NAME]).toEqual(String); + }); + it("defines a --help flag", function () { var knownOptionDefinitions = argumentParser.getKnownOptionDefinitions(); expect(knownOptionDefinitions[Cucumber.Cli.ArgumentParser.HELP_FLAG_NAME]).toEqual(Boolean); @@ -303,6 +308,24 @@ describe("Cucumber.Cli.ArgumentParser", function () { }); }); + describe("getReportFile()", function () { + var reportFile; + + beforeEach(function () { + reportFile = createSpy("reportFile"); + spyOn(argumentParser, 'getOptionOrDefault').andReturn(reportFile); + }); + + it("gets the reportFile option value", function () { + argumentParser.getReportFile(); + expect(argumentParser.getOptionOrDefault).toHaveBeenCalledWith(Cucumber.Cli.ArgumentParser.REPORT_FILE_OPTION_NAME, null); + }); + + it("returns the reportFile", function () { + expect(argumentParser.getReportFile()).toBe(reportFile); + }); + }); + describe("isHelpRequested()", function () { var isHelpRequested; diff --git a/spec/cucumber/cli/configuration_spec.js b/spec/cucumber/cli/configuration_spec.js index aee89aff0f..7dea73b85f 100644 --- a/spec/cucumber/cli/configuration_spec.js +++ b/spec/cucumber/cli/configuration_spec.js @@ -260,6 +260,23 @@ describe("Cucumber.Cli.Configuration", function () { }); }); + describe("getReportFile()", function () { + beforeEach(function () { + spyOnStub(argumentParser, "getReportFile"); + }); + + it("asks the argument parser for the report file path", function () { + configuration.getReportFile(); + expect(argumentParser.getReportFile).toHaveBeenCalled(); + }); + + it("returns the answer from the argument parser", function () { + var reportFile = createSpy("report file path"); + argumentParser.getReportFile.andReturn(reportFile); + expect(configuration.getReportFile()).toBe(reportFile); + }); + }); + describe("isHelpRequired()", function () { beforeEach(function () { spyOnStub(argumentParser, 'isHelpRequested'); diff --git a/spec/cucumber/runtime_spec.js b/spec/cucumber/runtime_spec.js index 5d81feac88..505d73770d 100644 --- a/spec/cucumber/runtime_spec.js +++ b/spec/cucumber/runtime_spec.js @@ -4,9 +4,10 @@ describe("Cucumber.Runtime", function() { var Cucumber = requireLib('cucumber'); var configuration; var runtime; - var supportCodeLibrary, listeners; + var supportCodeLibrary, listeners, fs; beforeEach(function() { + fs = require("fs"); listeners = createSpyWithStubs("listener collection", {add: null}); configuration = createSpy("configuration"); spyOn(Cucumber.Type, 'Collection').andReturn(listeners); @@ -69,7 +70,53 @@ describe("Cucumber.Runtime", function() { it("tells the AST tree walker to walk", function() { runtime.start(callback); - expect(astTreeWalker.walk).toHaveBeenCalledWith(callback); + expect(astTreeWalker.walk).toHaveBeenCalledWith(runtime.finish); + }); + }); + + describe("finish()", function () { + var result, callback, formatter, logs; + + beforeEach(function () { + result = createSpy("AST tree walker result"); + callback = createSpy("callback"); + formatter = createSpy("formatter"); + logs = createSpy("formatter logs"); + spyOnStub(listeners, "getLast").andReturn(formatter); + spyOnStub(formatter, "getLogs").andReturn(logs); + spyOn(fs, "writeFileSync"); + spyOn(runtime, "getCallback").andReturn(callback); + }); + + it("calls the callback", function() { + spyOnStub(configuration, "getReportFile").andReturn(null); + runtime.finish(result); + expect(callback).toHaveBeenCalled(); + }); + + it("does write to output to file", function () { + spyOnStub(configuration, "getReportFile").andReturn("reportFile"); + runtime.finish(result); + expect(fs.writeFileSync).toHaveBeenCalledWith("reportFile", logs, { flag: "w" }); + }); + + it("does not write to output to file if not specified", function () { + spyOnStub(configuration, "getReportFile").andReturn(null); + runtime.finish(result); + expect(fs.writeFileSync).not.toHaveBeenCalled(); + }); + }); + + describe("getCallback() [setCallback()]", function() { + var callback; + + beforeEach(function() { + callback = createSpy("callback"); + }); + + it("returns the callback set with setCallback()", function() { + runtime.setCallback(callback); + expect(runtime.getCallback()).toBe(callback); }); }); diff --git a/spec/cucumber/volatile_configuration_spec.js b/spec/cucumber/volatile_configuration_spec.js index 2753378dd5..7e60a0b6ab 100644 --- a/spec/cucumber/volatile_configuration_spec.js +++ b/spec/cucumber/volatile_configuration_spec.js @@ -11,7 +11,7 @@ describe("Cucumber.VolatileConfiguration", function() { beforeEach(function() { supportCodeLibrary = createSpy("support code library"); spyOn(Cucumber.SupportCode, 'Library').andReturn(supportCodeLibrary); - featureSources = createSpy("feature source"); + featureSources = createSpy("feature source"); supportCodeInitializer = createSpy("support code initializer"); configuration = Cucumber.VolatileConfiguration(featureSources, supportCodeInitializer); context.configuration = configuration; @@ -138,4 +138,18 @@ describe("Cucumber.VolatileConfiguration", function() { expect(returned).toBe(rule); }); }); + + describe("getReportFile()", function () { + var reportFile; + + it("returns 'null' when no report specified", function () { + expect(configuration.getReportFile()).toEqual(null); + }); + + it("returns the specified reports", function () { + reportFile = createSpy("report file path"); + configuration = Cucumber.VolatileConfiguration(featureSources, supportCodeInitializer, {report: reportFile}); + expect(configuration.getReportFile()).toEqual(reportFile); + }); + }); }); diff --git a/spec/support/configurations_shared_examples.js b/spec/support/configurations_shared_examples.js index cbe755948a..28432a392f 100644 --- a/spec/support/configurations_shared_examples.js +++ b/spec/support/configurations_shared_examples.js @@ -16,4 +16,8 @@ itBehavesLikeAllCucumberConfigurations = function itBehavesLikeAllCucumberConfig it("supplies the AST filter", function() { expect(configuration.getAstFilter).toBeAFunction(); }); + + it("supplies the report file location", function() { + expect(configuration.getReportFile).toBeAFunction(); + }); }