diff --git a/index.html b/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/src/Pickles/.vs/config/applicationhost.config b/src/Pickles/.vs/config/applicationhost.config index cd120d363..a1d283040 100644 --- a/src/Pickles/.vs/config/applicationhost.config +++ b/src/Pickles/.vs/config/applicationhost.config @@ -163,7 +163,7 @@ - + diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs index 1028133f7..0b2cd6e18 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs @@ -35,15 +35,15 @@ public Feature() public string Description { get; set; } - public List FeatureElements { get; } + public List FeatureElements { get; private set; } - public List Comments { get; } + public List Comments { get; private set; } public Scenario Background { get; private set; } public TestResult Result { get; set; } - public List Tags { get; } + public List Tags { get; private set; } public void AddTag(string tag) { diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/AutomationLayer/StepDefinitions.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/AutomationLayer/StepDefinitions.cs new file mode 100644 index 000000000..d9a87a371 --- /dev/null +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/AutomationLayer/StepDefinitions.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright 2011 Jeffrey Cameron +// Copyright 2012-present PicklesDoc team and community contributors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.IO; +using Autofac; +using NFluent; +using NGenerics.DataStructures.Trees; +using PicklesDoc.Pickles.DirectoryCrawler; +using PicklesDoc.Pickles.DocumentationBuilders.Cucumber; +using PicklesDoc.Pickles.DocumentationBuilders.JSON; +using TechTalk.SpecFlow; + +namespace PicklesDoc.Pickles.Test.DocumentationBuilders.Cucumber.AutomationLayer +{ + [Binding] + [Scope(Tag = "cucumber")] + public sealed class StepDefinitions : BaseFixture /* God object antipattern */ + { + private GeneralTree nodes; + + [Given("I have this feature description")] + public void IHaveThisFeatureDescription(string featureDescription) + { + var configuration = this.Configuration; + FeatureParser parser = new FeatureParser(this.FileSystem, configuration); + + var feature = parser.Parse(new StringReader(featureDescription)); + + this.nodes = new GeneralTree(new FeatureNode(this.FileSystem.DirectoryInfo.FromDirectoryName(@"c:\output\"), string.Empty, feature)); + } + + [When(@"I generate the documentation")] + public void WhenIGenerateTheJsonDocumentation() + { + var configuration = this.Configuration; + configuration.OutputFolder = this.FileSystem.DirectoryInfo.FromDirectoryName(@"c:\output\"); + var jsonDocumentationBuilder = this.Container.Resolve(); + + jsonDocumentationBuilder.Build(this.nodes); + } + + [Then("the JSON file should contain")] + public void ThenTheResultShouldBe(string expectedResult) + { + var actualResult = this.FileSystem.File.ReadAllText(@"c:\output\cucumberResult.json"); + + Console.WriteLine("----------------------------------------------------"); + Console.WriteLine(actualResult); + actualResult = actualResult.Replace("{", "{{").Replace("}", "}}"); + expectedResult = expectedResult.Replace("{", "{{").Replace("}", "}}"); + Check.That(actualResult).Contains(expectedResult); + } + } +} diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature new file mode 100644 index 000000000..e2fb05b60 --- /dev/null +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature @@ -0,0 +1,165 @@ +Feature: Formatting A Feature + +@cucumber +Scenario: A simple feature + + Given I have this feature description + """ + Feature: Clearing Screen + In order to restart a new set of calculations + As a math idiot + I want to be able to clear the screen + + @workflow @slow + Scenario: Clear the screen + Given I have entered 50 into the calculator + And I have entered 70 into the calculator + When I press C + Then the screen should be empty + """ + When I generate the documentation + Then the JSON file should contain +""" +[ + { + "keyword": "Feature", + "name": "Clearing Screen", + "tags": [], + "line": 1, + "elements": [ + { + "keyword": "Scenario", + "name": "Clear the screen", + "line": 7, + "type": "scenario", + "tags": [ + { + "name": "@workflow" + }, + { + "name": "@slow" + } + ], + "steps": [ + { + "keyword": "Given", + "name": "I have entered 50 into the calculator", + "line": 8, + "result": { + "status": "inconclusive", + "duration": 1 + } + }, + { + "keyword": "And", + "name": "I have entered 70 into the calculator", + "line": 9, + "result": { + "status": "inconclusive", + "duration": 1 + } + }, + { + "keyword": "When", + "name": "I press C", + "line": 10, + "result": { + "status": "inconclusive", + "duration": 1 + } + }, + { + "keyword": "Then", + "name": "the screen should be empty", + "line": 11, + "result": { + "status": "inconclusive", + "duration": 1 + } + } +""" + +@cucumber +Scenario: A feature with a table + + Given I have this feature description + """ + Feature: Interactive DHTML View + In order to increase stakeholder engagement with pickled specs + As a SpecFlow evangelist + I want to adjust the level of detail in the DHTML view to suit my audience + So that I do not overwhelm them. + + Scenario: Scenario with large data table + Given a feature with a large table of data: + | heading | page # | + | Chapter 1 | 1 | + | Chapter 2 | 5 | + | Chapter 3 | 10 | + | Chapter 4 | 15 | + | Chapter 5 | 20 | + | Chapter 6 | 25 | + | Chapter 7 | 30 | + | Chapter 8 | 35 | + | Chapter 9 | 40 | + | Chapter 10 | 45 | + | Chapter 11 | 50 | + | Chapter 12 | 55 | + | Chapter 13 | 60 | + | Chapter 14 | 65 | + | Chapter 15 | 70 | + | Chapter 16 | 75 | + | Chapter 17 | 80 | + | Chapter 18 | 85 | + | Chapter 19 | 90 | + | Chapter 20 | 95 | + | Chapter 21 | 100 | + | Chapter 22 | 105 | + When I click on the table heading + Then the table body should collapse + """ + When I generate the documentation + Then the JSON file should contain +""" +[ + { + "keyword": "Feature", + "name": "Interactive DHTML View", + "tags": [], + "line": 1, + "elements": [ + { + "keyword": "Scenario", + "name": "Scenario with large data table", + "line": 7, + "type": "scenario", + "tags": [], + "steps": [ + { + "keyword": "Given", + "name": "a feature with a large table of data:", + "line": 8, + "result": { + "status": "inconclusive", + "duration": 1 + } + }, + { + "keyword": "When", + "name": "I click on the table heading", + "line": 32, + "result": { + "status": "inconclusive", + "duration": 1 + } + }, + { + "keyword": "Then", + "name": "the table body should collapse", + "line": 33, + "result": { + "status": "inconclusive", + "duration": 1 + } + } +""" \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature.cs new file mode 100644 index 000000000..39e9ba678 --- /dev/null +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/Cucumber/FormattingAFeature.feature.cs @@ -0,0 +1,248 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (http://www.specflow.org/). +// SpecFlow Version:2.0.0.0 +// SpecFlow Generator Version:2.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace PicklesDoc.Pickles.Test.DocumentationBuilders.Cucumber +{ + using TechTalk.SpecFlow; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "2.0.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Formatting A Feature")] + public partial class FormattingAFeatureFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + +#line 1 "FormattingAFeature.feature" +#line hidden + + [NUnit.Framework.TestFixtureSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Formatting A Feature", null, ProgrammingLanguage.CSharp, ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.TestFixtureTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public virtual void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public virtual void ScenarioTearDown() + { + testRunner.OnScenarioEnd(); + } + + public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioStart(scenarioInfo); + } + + public virtual void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("A simple feature")] + [NUnit.Framework.CategoryAttribute("cucumber")] + public virtual void ASimpleFeature() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("A simple feature", new string[] { + "cucumber"}); +#line 4 +this.ScenarioSetup(scenarioInfo); +#line hidden +#line 6 + testRunner.Given("I have this feature description", @"Feature: Clearing Screen + In order to restart a new set of calculations + As a math idiot + I want to be able to clear the screen + +@workflow @slow +Scenario: Clear the screen + Given I have entered 50 into the calculator + And I have entered 70 into the calculator + When I press C + Then the screen should be empty", ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 20 + testRunner.When("I generate the documentation", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 21 + testRunner.Then("the JSON file should contain", @"[ + { + ""keyword"": ""Feature"", + ""name"": ""Clearing Screen"", + ""tags"": [], + ""line"": 1, + ""elements"": [ + { + ""keyword"": ""Scenario"", + ""name"": ""Clear the screen"", + ""line"": 7, + ""type"": ""scenario"", + ""tags"": [ + { + ""name"": ""@workflow"" + }, + { + ""name"": ""@slow"" + } + ], + ""steps"": [ + { + ""keyword"": ""Given"", + ""name"": ""I have entered 50 into the calculator"", + ""line"": 8, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }, + { + ""keyword"": ""And"", + ""name"": ""I have entered 70 into the calculator"", + ""line"": 9, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }, + { + ""keyword"": ""When"", + ""name"": ""I press C"", + ""line"": 10, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }, + { + ""keyword"": ""Then"", + ""name"": ""the screen should be empty"", + ""line"": 11, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }", ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("A feature with a table")] + [NUnit.Framework.CategoryAttribute("cucumber")] + public virtual void AFeatureWithATable() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("A feature with a table", new string[] { + "cucumber"}); +#line 83 +this.ScenarioSetup(scenarioInfo); +#line hidden +#line 85 + testRunner.Given("I have this feature description", @"Feature: Interactive DHTML View + In order to increase stakeholder engagement with pickled specs + As a SpecFlow evangelist + I want to adjust the level of detail in the DHTML view to suit my audience + So that I do not overwhelm them. + +Scenario: Scenario with large data table + Given a feature with a large table of data: + | heading | page # | + | Chapter 1 | 1 | + | Chapter 2 | 5 | + | Chapter 3 | 10 | + | Chapter 4 | 15 | + | Chapter 5 | 20 | + | Chapter 6 | 25 | + | Chapter 7 | 30 | + | Chapter 8 | 35 | + | Chapter 9 | 40 | + | Chapter 10 | 45 | + | Chapter 11 | 50 | + | Chapter 12 | 55 | + | Chapter 13 | 60 | + | Chapter 14 | 65 | + | Chapter 15 | 70 | + | Chapter 16 | 75 | + | Chapter 17 | 80 | + | Chapter 18 | 85 | + | Chapter 19 | 90 | + | Chapter 20 | 95 | + | Chapter 21 | 100 | + | Chapter 22 | 105 | + When I click on the table heading + Then the table body should collapse", ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 121 + testRunner.When("I generate the documentation", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 122 + testRunner.Then("the JSON file should contain", @"[ + { + ""keyword"": ""Feature"", + ""name"": ""Interactive DHTML View"", + ""tags"": [], + ""line"": 1, + ""elements"": [ + { + ""keyword"": ""Scenario"", + ""name"": ""Scenario with large data table"", + ""line"": 7, + ""type"": ""scenario"", + ""tags"": [], + ""steps"": [ + { + ""keyword"": ""Given"", + ""name"": ""a feature with a large table of data:"", + ""line"": 8, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }, + { + ""keyword"": ""When"", + ""name"": ""I click on the table heading"", + ""line"": 32, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }, + { + ""keyword"": ""Then"", + ""name"": ""the table body should collapse"", + ""line"": 33, + ""result"": { + ""status"": ""inconclusive"", + ""duration"": 1 + } + }", ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/Pickles/Pickles.Test/Pickles.Test.csproj b/src/Pickles/Pickles.Test/Pickles.Test.csproj index f77c66876..a3ca99542 100644 --- a/src/Pickles/Pickles.Test/Pickles.Test.csproj +++ b/src/Pickles/Pickles.Test/Pickles.Test.csproj @@ -99,12 +99,18 @@ + + FormattingAFeature.feature + True + True + FormattingAFeatureUsingStrike.feature True True + True @@ -208,6 +214,10 @@ + + SpecFlowSingleFileGenerator + FormattingAFeature.feature.cs + SpecFlowSingleFileGenerator FormattingAFeatureUsingStrike.feature.cs diff --git a/src/Pickles/Pickles/DocumentationBuilders/Cucumber/CucumberDocumentationBuilder.cs b/src/Pickles/Pickles/DocumentationBuilders/Cucumber/CucumberDocumentationBuilder.cs index e467ca73f..442d65ab7 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/Cucumber/CucumberDocumentationBuilder.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/Cucumber/CucumberDocumentationBuilder.cs @@ -36,45 +36,21 @@ namespace PicklesDoc.Pickles.DocumentationBuilders.Cucumber public class CucumberDocumentationBuilder : IDocumentationBuilder { - #region Private Constants public const string CucumberFileName = @"cucumberResult.json"; - #endregion - #region Private Fields private static readonly Logger Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType?.Name); private readonly IConfiguration configuration; private readonly IFileSystem fileSystem; - #endregion - - #region Public Properties - /// - /// Gets the output file path. - /// - /// - /// The output file path. - /// + + public string OutputFilePath => this.fileSystem.Path.Combine(this.configuration.OutputFolder.FullName, CucumberFileName); - #endregion - - #region Constructor - /// - /// Initializes a new instance of the class. - /// - /// The configuration. - /// The file system. + public CucumberDocumentationBuilder(IConfiguration configuration, IFileSystem fileSystem) { this.configuration = configuration; this.fileSystem = fileSystem; } - #endregion - #region IDocumentationBuilder Members - - /// - /// Builds the specified features. - /// - /// The features. public void Build(GeneralTree features) { if (Log.IsInfoEnabled) @@ -99,14 +75,6 @@ public void Build(GeneralTree features) this.CreateFile(this.OutputFilePath, this.GenerateJson(featuresToFormat)); } - #endregion - - #region Private Methods - /// - /// Generates the json. - /// - /// The features. - /// private string GenerateJson(List features) { var toOutPut = features.Select(f => new @@ -150,11 +118,6 @@ private string GenerateJson(List features) return JsonConvert.SerializeObject(toOutPut, Formatting.Indented, settings); } - /// - /// Creates the file. - /// - /// Name of the output folder. - /// The json to write. private void CreateFile(string outputFolderName, string jsonToWrite) { using (StreamWriter writer = this.fileSystem.File.CreateText(outputFolderName)) @@ -163,6 +126,5 @@ private void CreateFile(string outputFolderName, string jsonToWrite) writer.Close(); } } - #endregion } } diff --git a/testOutput.ps1 b/testOutput.ps1 index 00e8b23c3..f963a42a7 100644 --- a/testOutput.ps1 +++ b/testOutput.ps1 @@ -1,5 +1,5 @@ $version = $args[0] -$formats = @("Html", "Dhtml", "Word", "Excel", "JSON") +$formats = @("Html", "Dhtml", "Word", "Excel", "JSON", "Cucumber") $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent Try