diff --git a/.gitignore b/.gitignore index 1ffa2eee3..e8e57ec7e 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,4 @@ packages/Chocolatey/ !src/Pickles/packages/Fody*/build/* src/Pickles/.vs/config/applicationhost.config src/Pickles/Pickles/PortabilityAnalysis.html +src/Pickles/.vs/config/applicationhost.config diff --git a/CHANGELOG.md b/CHANGELOG.md index 39d360181..f0e3431e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,24 @@ Features in Experimental are subject to change and removal without being conside This document is formatted according to the principles of [Keep A CHANGELOG](http://keepachangelog.com). +## [2.6.0] - 2016-04-12 + +### Added + +- Support for multiple tags in DHTML version ([#283](https://github.com/picklesdoc/pickles/issues/283)) (by [@aaronjrich](https://github.com/aaronjrich)). +- Output commented lines ([#271](https://github.com/picklesdoc/pickles/issues/271)) (by [@ludwigjossieaux](https://github.com/ludwigjossieaux)). + +### Changed + +- Use version 4 of the Gherkin parser ([#322](https://github.com/picklesdoc/pickles/issues/322)) (by [@dirkrombauts](https://github.com/dirkrombauts)). +- Use new logo as icon and in nuget packages ([#323](https://github.com/picklesdoc/pickles/issues/323)) (by [@dirkrombauts](https://github.com/dirkrombauts)). +- Update external libraries ([#310](https://github.com/picklesdoc/pickles/issues/310)) (by [@dirkrombauts](https://github.com/dirkrombauts)). + +### Fixed + +- SpecFlow conformant name mapping in nUnit test result provider ([#315](https://github.com/picklesdoc/pickles/issues/315)) (by [@danielpullwitt](https://github.com/danielpullwitt)). +- Prevent crash when no Description is provided ([#314](https://github.com/picklesdoc/pickles/issues/314)) (by [@danielpullwitt](https://github.com/danielpullwitt)). + ## [2.5.0] - 2016-03-21 diff --git a/build.bat b/build.bat index 059610bdf..9e9868857 100644 --- a/build.bat +++ b/build.bat @@ -1,5 +1,5 @@ @echo off -set "picklesVersion=2.5.0" +set "picklesVersion=2.6.0" cls diff --git a/chocolatey/pickles.nuspec b/chocolatey/pickles.nuspec index ffcb9df71..2de1230ad 100644 --- a/chocolatey/pickles.nuspec +++ b/chocolatey/pickles.nuspec @@ -32,7 +32,7 @@ Optionally, *Pickles* can **integrate test results**, so that your stakeholders Copyright © 2010-2012 Jeffrey Cameron, Copyright © 2013-present PicklesDoc and contributors http://apache.org/licenses/LICENSE-2.0.html false - https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.jpeg + https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.png https://github.com/picklesdoc/pickles/blob/master/CHANGELOG.md diff --git a/chocolatey/picklesui.nuspec b/chocolatey/picklesui.nuspec index ce27c3da2..820602e19 100644 --- a/chocolatey/picklesui.nuspec +++ b/chocolatey/picklesui.nuspec @@ -32,7 +32,7 @@ Optionally, *Pickles* can **integrate test results**, so that your stakeholders Copyright © 2010-2012 Jeffrey Cameron, Copyright © 2013-present PicklesDoc and contributors http://apache.org/licenses/LICENSE-2.0.html false - https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.jpeg + https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.png https://github.com/picklesdoc/pickles/blob/master/CHANGELOG.md diff --git a/pickles.jpeg b/pickles.jpeg deleted file mode 100644 index 6c715d273..000000000 Binary files a/pickles.jpeg and /dev/null differ diff --git a/pickles.png b/pickles.png new file mode 100644 index 000000000..9a562a6a5 Binary files /dev/null and b/pickles.png differ diff --git a/src/Pickles/.vs/config/applicationhost.config b/src/Pickles/.vs/config/applicationhost.config index 5ac001ad4..78bf2029c 100644 --- a/src/Pickles/.vs/config/applicationhost.config +++ b/src/Pickles/.vs/config/applicationhost.config @@ -163,7 +163,15 @@ - + + + + + + + + + diff --git a/src/Pickles/Pickles.BaseDhtmlFiles/Index.html b/src/Pickles/Pickles.BaseDhtmlFiles/Index.html index 7b1c91122..49b86dae2 100644 --- a/src/Pickles/Pickles.BaseDhtmlFiles/Index.html +++ b/src/Pickles/Pickles.BaseDhtmlFiles/Index.html @@ -50,11 +50,27 @@ diff --git a/src/Pickles/Pickles.BaseDhtmlFiles/css/styles.css b/src/Pickles/Pickles.BaseDhtmlFiles/css/styles.css index 0f41b5d8c..1f5c182b9 100644 --- a/src/Pickles/Pickles.BaseDhtmlFiles/css/styles.css +++ b/src/Pickles/Pickles.BaseDhtmlFiles/css/styles.css @@ -72,6 +72,11 @@ li.step { padding: 0; } +.comment { + font-weight: bold; + color: #0088CC; +} + .keyword { font-weight: bold; color: #0000FF; diff --git a/src/Pickles/Pickles.BaseDhtmlFiles/js/featureSearch.js b/src/Pickles/Pickles.BaseDhtmlFiles/js/featureSearch.js index fed5f0c07..c9b762a2c 100644 --- a/src/Pickles/Pickles.BaseDhtmlFiles/js/featureSearch.js +++ b/src/Pickles/Pickles.BaseDhtmlFiles/js/featureSearch.js @@ -16,7 +16,7 @@ function findFeatureByRelativeFolder(path, features) { var feature = _.find(features, function(featureTesting) { - return featureTesting.RelativeFolder == path; + return featureTesting.RelativeFolder == path; }); return feature ? feature : null; } @@ -27,13 +27,20 @@ function matchesFeatureName(searchString, feature) { } function matchesFeatureTag(searchString, feature) { - var foundMatch = false; - $.each(feature.Feature.Tags, function (key, scenarioTag) { - var lowerCasedTag = scenarioTag.toLowerCase(); - if (lowerCasedTag.indexOf(searchString) > -1) { - foundMatch = true; + var foundMatch = false; + var tags = searchString.split(" "); + $.each(tags, function (index, tag) { + tag = tag.toLowerCase(); + if (tag.indexOf("@") > -1) { + $.each(feature.Feature.Tags, function (key, scenarioTag) { + var lowerCasedTag = scenarioTag.toLowerCase(); + if (lowerCasedTag.indexOf(tag) > -1) { + foundMatch = true; + } + }); } }); + return foundMatch; } @@ -48,15 +55,21 @@ function matchesScenarioName(searchString, feature) { } function matchesScenarioTag(searchString, feature) { - for (var i = 0; i < feature.Feature.FeatureElements.length; i++) { - var foundMatch = false; - $.each(feature.Feature.FeatureElements[i].Tags, function (key, scenarioTag) { - var lowerCasedTag = scenarioTag.toLowerCase(); - if (lowerCasedTag.indexOf(searchString) > -1) { - foundMatch = true; + var foundMatch = false; + var tags = searchString.split(" "); + $.each(tags, function (index, tag) { + tag = tag.toLowerCase(); + if (tag.indexOf("@") > -1) { + for (var i = 0; i < feature.Feature.FeatureElements.length; i++) { + $.each(feature.Feature.FeatureElements[i].Tags, function (key, scenarioTag) { + var lowerCasedTag = scenarioTag.toLowerCase(); + if (lowerCasedTag.indexOf(tag) > -1) { + foundMatch = true; + } + }); + if (foundMatch) { break; } } - }); - if (foundMatch) return true; - } - return false; + } + }); + return foundMatch; } diff --git a/src/Pickles/Pickles.BaseDhtmlFiles/js/featuresModel.js b/src/Pickles/Pickles.BaseDhtmlFiles/js/featuresModel.js index ccdd24895..4dee872e8 100644 --- a/src/Pickles/Pickles.BaseDhtmlFiles/js/featuresModel.js +++ b/src/Pickles/Pickles.BaseDhtmlFiles/js/featuresModel.js @@ -28,6 +28,12 @@ function Step(data) { this.NativeKeyword = data.NativeKeyword || ''; this.DocStringArgument = data.DocStringArgument || ''; this.TableArgument = data.TableArgument == null ? null : new TableArgument(data.TableArgument.HeaderRow, data.TableArgument.DataRows); + this.StepComments = data.StepComments == null ? null : $.map(data.StepComments, function (c) { return new Comment(c); }); + this.AfterLastStepComments = data.AfterLastStepComments == null ? null : $.map(data.AfterLastStepComments, function (c) { return new Comment(c); }); +} + +function Comment(data) { + this.Text = data.Text || ''; } function TableArgument(headerRow, dataRows) { diff --git a/src/Pickles/Pickles.BaseDhtmlFiles/tests/tests.js b/src/Pickles/Pickles.BaseDhtmlFiles/tests/tests.js index 2ba200bc5..6f858a69f 100644 --- a/src/Pickles/Pickles.BaseDhtmlFiles/tests/tests.js +++ b/src/Pickles/Pickles.BaseDhtmlFiles/tests/tests.js @@ -494,13 +494,15 @@ test("Can search for tags and feature/scenarios names", function () { "Feature level level tag search - across multiple features"); deepEqual(getFeaturesMatching('@doesnotexist', sampleJSONForSearch), [], "Neither a tag or feature in list."); + deepEqual(getFeaturesMatching('@clearing @nestedFolder', sampleJSONForSearch), sampleJSONForSearch, + "Can search using multiple tags - will or them"); }); test("Can find feature by RelativeFolder", function () { deepEqual(findFeatureByRelativeFolder('Workflow\\ClearingScreen.feature', sampleJSONForSearch), sampleJSONForSearch[0], - "Feature exists"); + "Feature exists"); deepEqual(findFeatureByRelativeFolder('Workflow\\ClearingScreen2.feature', sampleJSONForSearch), null, "Feature does not exist"); diff --git a/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.csproj b/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.csproj index 88a2970c4..b68706ef8 100644 --- a/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.csproj +++ b/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.csproj @@ -55,8 +55,8 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True diff --git a/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.nuspec b/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.nuspec index 68789592e..912e4ed6b 100644 --- a/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.nuspec +++ b/src/Pickles/Pickles.CommandLine/Pickles.CommandLine.nuspec @@ -33,7 +33,7 @@ A documentation generator for features written in the Gherkin language Copyright © 2010-2012 Jeffrey Cameron, Copyright © 2013-present PicklesDoc and contributors SpecificationByExample BDD SpecFlow Gherkin Cucumber SpecByEx LivingDocumentation Documentation - https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.jpeg + https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.png https://github.com/picklesdoc/pickles/blob/master/CHANGELOG.md diff --git a/src/Pickles/Pickles.CommandLine/packages.config b/src/Pickles/Pickles.CommandLine/packages.config index 265c21346..2d5e2a302 100644 --- a/src/Pickles/Pickles.CommandLine/packages.config +++ b/src/Pickles/Pickles.CommandLine/packages.config @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.csproj b/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.csproj index 0af6cb002..d350e0f79 100644 --- a/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.csproj +++ b/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.csproj @@ -46,8 +46,8 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True diff --git a/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.nuspec b/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.nuspec index 4caa6cad6..b8a93f542 100644 --- a/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.nuspec +++ b/src/Pickles/Pickles.MSBuild/Pickles.MSBuild.nuspec @@ -33,7 +33,7 @@ A documentation generator for features written in the Gherkin language Copyright © 2010-2012 Jeffrey Cameron, Copyright © 2013-present PicklesDoc and contributors SpecificationByExample BDD SpecFlow Gherkin Cucumber SpecByEx LivingDocumentation Documentation - https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.jpeg + https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.png https://github.com/picklesdoc/pickles/blob/master/CHANGELOG.md diff --git a/src/Pickles/Pickles.MSBuild/packages.config b/src/Pickles/Pickles.MSBuild/packages.config index 130d810d6..600d53435 100644 --- a/src/Pickles/Pickles.MSBuild/packages.config +++ b/src/Pickles/Pickles.MSBuild/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Comment.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Comment.cs new file mode 100644 index 000000000..d1a0afd88 --- /dev/null +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Comment.cs @@ -0,0 +1,44 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// 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. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace PicklesDoc.Pickles.ObjectModel +{ + public enum CommentType + { + Normal, + StepComment, + AfterLastStepComment + } + + public class Comment + { + public Comment() + { + // Set default + this.Type = CommentType.Normal; + } + + public string Text { get; set; } + + public Location Location { get; set; } + + public CommentType Type { get; set; } + } +} diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs index 7544d200e..1028133f7 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Feature.cs @@ -27,6 +27,7 @@ public class Feature public Feature() { this.FeatureElements = new List(); + this.Comments = new List(); this.Tags = new List(); } @@ -36,6 +37,8 @@ public Feature() public List FeatureElements { get; } + public List Comments { get; } + public Scenario Background { get; private set; } public TestResult Result { get; set; } diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/IFeatureElement.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/IFeatureElement.cs index 3242ce8c1..b510f8837 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/IFeatureElement.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/IFeatureElement.cs @@ -35,5 +35,7 @@ public interface IFeatureElement List Tags { get; set; } TestResult Result { get; set; } + + Location Location { get; set; } } } diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Location.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Location.cs new file mode 100644 index 000000000..61c92f4e6 --- /dev/null +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Location.cs @@ -0,0 +1,29 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// 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. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace PicklesDoc.Pickles.ObjectModel +{ + public class Location + { + public int Column { get; set; } + + public int Line { get; set; } + } +} diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Scenario.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Scenario.cs index 47b3e699c..9584dc739 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/Scenario.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Scenario.cs @@ -30,8 +30,6 @@ public Scenario() this.Tags = new List(); } - #region IFeatureElement Members - public string Name { get; set; } public string Description { get; set; } @@ -44,6 +42,6 @@ public Scenario() public Feature Feature { get; set; } - #endregion + public Location Location { get; set; } } } diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/ScenarioOutline.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/ScenarioOutline.cs index 0ec3f70e7..470d12532 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/ScenarioOutline.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/ScenarioOutline.cs @@ -43,5 +43,7 @@ public ScenarioOutline() public TestResult Result { get; set; } public Feature Feature { get; set; } + + public Location Location { get; set; } } } diff --git a/src/Pickles/Pickles.ObjectModel/ObjectModel/Step.cs b/src/Pickles/Pickles.ObjectModel/ObjectModel/Step.cs index 37629f545..b4c09ff98 100644 --- a/src/Pickles/Pickles.ObjectModel/ObjectModel/Step.cs +++ b/src/Pickles/Pickles.ObjectModel/ObjectModel/Step.cs @@ -18,10 +18,17 @@ // // -------------------------------------------------------------------------------------------------------------------- +using System.Collections.Generic; + namespace PicklesDoc.Pickles.ObjectModel { public class Step { + public Step() + { + this.Comments = new List(); + } + public Keyword Keyword { get; set; } public string NativeKeyword { get; set; } @@ -31,5 +38,9 @@ public class Step public Table TableArgument { get; set; } public string DocStringArgument { get; set; } + + public Location Location { get; set; } + + public List Comments { get; set; } } } diff --git a/src/Pickles/Pickles.ObjectModel/Pickles.ObjectModel.csproj b/src/Pickles/Pickles.ObjectModel/Pickles.ObjectModel.csproj index 3c74cf1cf..d74b23837 100644 --- a/src/Pickles/Pickles.ObjectModel/Pickles.ObjectModel.csproj +++ b/src/Pickles/Pickles.ObjectModel/Pickles.ObjectModel.csproj @@ -32,8 +32,8 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True @@ -46,6 +46,7 @@ + @@ -54,6 +55,7 @@ + diff --git a/src/Pickles/Pickles.ObjectModel/packages.config b/src/Pickles/Pickles.ObjectModel/packages.config index 4c7303ddf..b9aed6af2 100644 --- a/src/Pickles/Pickles.ObjectModel/packages.config +++ b/src/Pickles/Pickles.ObjectModel/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/Pickles/Pickles.PowerShell/Pickles.PowerShell.csproj b/src/Pickles/Pickles.PowerShell/Pickles.PowerShell.csproj index dd41e4131..ed7c2c2df 100644 --- a/src/Pickles/Pickles.PowerShell/Pickles.PowerShell.csproj +++ b/src/Pickles/Pickles.PowerShell/Pickles.PowerShell.csproj @@ -43,8 +43,8 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True diff --git a/src/Pickles/Pickles.PowerShell/Pickles.nuspec b/src/Pickles/Pickles.PowerShell/Pickles.nuspec index 3a2ca357b..b6d3a1c40 100644 --- a/src/Pickles/Pickles.PowerShell/Pickles.nuspec +++ b/src/Pickles/Pickles.PowerShell/Pickles.nuspec @@ -33,7 +33,7 @@ A documentation generator for features written in the Gherkin language Copyright © 2010-2012 Jeffrey Cameron, Copyright © 2013-present PicklesDoc and contributors SpecificationByExample BDD SpecFlow Gherkin Cucumber SpecByEx LivingDocumentation Documentation - https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.jpeg + https://cdn.rawgit.com/picklesdoc/pickles/master/pickles.png https://github.com/picklesdoc/pickles/blob/master/CHANGELOG.md diff --git a/src/Pickles/Pickles.PowerShell/packages.config b/src/Pickles/Pickles.PowerShell/packages.config index 130d810d6..600d53435 100644 --- a/src/Pickles/Pickles.PowerShell/packages.config +++ b/src/Pickles/Pickles.PowerShell/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/App.config b/src/Pickles/Pickles.Test/App.config index 162597a63..db0284d6d 100644 --- a/src/Pickles/Pickles.Test/App.config +++ b/src/Pickles/Pickles.Test/App.config @@ -15,7 +15,7 @@ - + diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/Excel/WhenAddingAStepToAWorksheet.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/Excel/WhenAddingAStepToAWorksheet.cs index 0020fd958..9bbec6250 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/Excel/WhenAddingAStepToAWorksheet.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/Excel/WhenAddingAStepToAWorksheet.cs @@ -19,6 +19,8 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Collections.Generic; +using System.Linq; using Autofac; using ClosedXML.Excel; using NFluent; @@ -47,5 +49,107 @@ public void ThenStepAddedSuccessfully() Check.That(worksheet.Cell("D5").Value).IsEqualTo(step.Name); } } + + [Test] + public void ThenStepCommentsAreAddedSuccessfully() + { + var excelStepFormatter = Container.Resolve(); + var step = new Step + { + NativeKeyword = "Given", + Name = "I have some precondition", + Comments = new List() + { + new Comment() + { + Text = "# A comment", + Type = CommentType.StepComment + } + } + }; + + using (var workbook = new XLWorkbook()) + { + IXLWorksheet worksheet = workbook.AddWorksheet("SHEET1"); + int row = 5; + excelStepFormatter.Format(worksheet, step, ref row); + + Check.That(worksheet.Cell("C5").Value).IsEqualTo(step.Comments.First().Text); + Check.That(worksheet.Cell("C6").Value).IsEqualTo(step.NativeKeyword); + Check.That(worksheet.Cell("D6").Value).IsEqualTo(step.Name); + } + } + + [Test] + public void ThenMultilineStepCommentsAreAddedSuccessfully() + { + var excelStepFormatter = Container.Resolve(); + var step = new Step + { + NativeKeyword = "Given", + Name = "I have some precondition", + Comments = new List() + { + new Comment() + { + Text = "# A comment - line 1", + Type = CommentType.StepComment + }, + new Comment() + { + Text = "# A comment - line 2", + Type = CommentType.StepComment + } + } + }; + + using (var workbook = new XLWorkbook()) + { + IXLWorksheet worksheet = workbook.AddWorksheet("SHEET1"); + int row = 5; + excelStepFormatter.Format(worksheet, step, ref row); + + Check.That(worksheet.Cell("C5").Value).IsEqualTo(step.Comments[0].Text); + Check.That(worksheet.Cell("C6").Value).IsEqualTo(step.Comments[1].Text); + Check.That(worksheet.Cell("C7").Value).IsEqualTo(step.NativeKeyword); + Check.That(worksheet.Cell("D7").Value).IsEqualTo(step.Name); + } + } + + [Test] + public void ThenCommentsAfterTheLastStepAreAddedSuccessfully() + { + var excelStepFormatter = Container.Resolve(); + var step = new Step + { + NativeKeyword = "Given", + Name = "I have some precondition", + Comments = new List() + { + new Comment() + { + Text = "# A comment", + Type = CommentType.StepComment + }, + new Comment() + { + Text = "# A comment the last step", + Type = CommentType.AfterLastStepComment + } + } + }; + + using (var workbook = new XLWorkbook()) + { + IXLWorksheet worksheet = workbook.AddWorksheet("SHEET1"); + int row = 5; + excelStepFormatter.Format(worksheet, step, ref row); + + Check.That(worksheet.Cell("C5").Value).IsEqualTo(step.Comments.First(o => o.Type == CommentType.StepComment).Text); + Check.That(worksheet.Cell("C6").Value).IsEqualTo(step.NativeKeyword); + Check.That(worksheet.Cell("D6").Value).IsEqualTo(step.Name); + Check.That(worksheet.Cell("C7").Value).IsEqualTo(step.Comments.First(o => o.Type == CommentType.AfterLastStepComment).Text); + } + } } } diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/CurrentScenarioContext.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/CurrentScenarioContext.cs index 0ed97adf0..0a6216046 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/CurrentScenarioContext.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/CurrentScenarioContext.cs @@ -19,23 +19,25 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Collections; using System.Xml.Linq; using Autofac; using PicklesDoc.Pickles.ObjectModel; -using TechTalk.SpecFlow; namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML.AutomationLayer { - public static class CurrentScenarioContext + public class CurrentScenarioContext { - public static Feature Feature + private Hashtable Current { get; } = new Hashtable(); + + public Feature Feature { get { - if (ScenarioContext.Current.ContainsKey("Feature")) + if (Current.ContainsKey("Feature")) { - return ScenarioContext.Current["Feature"] as Feature; + return Current["Feature"] as Feature; } else { @@ -45,19 +47,19 @@ public static Feature Feature set { - ScenarioContext.Current["Feature"] = value; + Current["Feature"] = value; } } - public static IContainer Container { get; set; } + public IContainer Container { get; set; } - public static XElement Html + public XElement Html { get { - if (ScenarioContext.Current.ContainsKey("Html")) + if (Current.ContainsKey("Html")) { - return ScenarioContext.Current["Html"] as XElement; + return Current["Html"] as XElement; } else { @@ -67,7 +69,7 @@ public static XElement Html set { - ScenarioContext.Current["Html"] = value; + Current["Html"] = value; } } } diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/Hooks.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/Hooks.cs index 2cf4f69aa..e0feb819a 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/Hooks.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/Hooks.cs @@ -28,6 +28,16 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML.AutomationLayer [Binding] public class Hooks { + private readonly ScenarioContext scenarioContext; + + public Hooks(CurrentScenarioContext currentScenarioContext, ScenarioContext scenarioContext) + { + this.CurrentScenarioContext = currentScenarioContext; + this.scenarioContext = scenarioContext; + } + + private CurrentScenarioContext CurrentScenarioContext { get; } + [BeforeScenario] public void BeforeScenario() { @@ -36,7 +46,7 @@ public void BeforeScenario() builder.RegisterModule(); CurrentScenarioContext.Container = builder.Build(); - if (ScenarioContext.Current.ScenarioInfo.Tags.Contains("enableExperimentalFeatures")) + if (this.scenarioContext.ScenarioInfo.Tags.Contains("enableExperimentalFeatures")) { var configuration = CurrentScenarioContext.Container.Resolve(); configuration.EnableExperimentalFeatures(); diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/StepDefinitions.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/StepDefinitions.cs index fda5fa0fd..f2a550fb8 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/StepDefinitions.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/AutomationLayer/StepDefinitions.cs @@ -31,6 +31,13 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML.AutomationLayer [Binding] public class StepDefinitions { + public StepDefinitions(CurrentScenarioContext currentScenarioContext) + { + this.CurrentScenarioContext = currentScenarioContext; + } + + private CurrentScenarioContext CurrentScenarioContext { get; } + [Given(@"I have this feature description")] public void GivenIHaveThisFeatureDescription(string multilineText) { diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeature.feature.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeature.feature.cs index 8355d687e..dc9d9d3d7 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeature.feature.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeature.feature.cs @@ -1,9 +1,8 @@ // ------------------------------------------------------------------------------ // // This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.9.0.77 -// SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.18034 +// 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. @@ -16,14 +15,14 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML using TechTalk.SpecFlow; - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")] + [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 static TechTalk.SpecFlow.ITestRunner testRunner; + private TechTalk.SpecFlow.ITestRunner testRunner; #line 1 "FormattingAFeature.feature" #line hidden @@ -32,7 +31,7 @@ public partial class FormattingAFeatureFeature 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", "", ProgrammingLanguage.CSharp, ((string[])(null))); + 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); } diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeatureUsingStrike.feature.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeatureUsingStrike.feature.cs index 3c56a165b..0557ecac0 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeatureUsingStrike.feature.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/FormattingAFeatureUsingStrike.feature.cs @@ -1,9 +1,8 @@ // ------------------------------------------------------------------------------ // // This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.9.0.77 -// SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.42000 +// 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. @@ -16,14 +15,14 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML using TechTalk.SpecFlow; - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "2.0.0.0")] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [NUnit.Framework.TestFixtureAttribute()] [NUnit.Framework.DescriptionAttribute("Formatting a Feature Using Strike")] public partial class FormattingAFeatureUsingStrikeFeature { - private static TechTalk.SpecFlow.ITestRunner testRunner; + private TechTalk.SpecFlow.ITestRunner testRunner; #line 1 "FormattingAFeatureUsingStrike.feature" #line hidden @@ -32,7 +31,7 @@ public partial class FormattingAFeatureUsingStrikeFeature 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 Using Strike", "", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Formatting a Feature Using Strike", null, ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/WhenFormattingStep.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/WhenFormattingStep.cs index 6f7aa0065..fa8e39609 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/WhenFormattingStep.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/HTML/WhenFormattingStep.cs @@ -33,6 +33,7 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.HTML public class WhenFormattingStep : BaseFixture { private const string ExpectedGivenHtml = "Given "; + private readonly XNamespace xmlns = XNamespace.Get("http://www.w3.org/1999/xhtml"); [Test] public void Multiline_strings_are_formatted_as_list_items_with_pre_elements_formatted_as_code_internal() @@ -49,7 +50,6 @@ public void Multiline_strings_are_formatted_as_list_items_with_pre_elements_form var formatter = Container.Resolve(); XElement actual = formatter.Format(step); - XNamespace xmlns = XNamespace.Get("http://www.w3.org/1999/xhtml"); var expected = new XElement( xmlns + "li", new XAttribute("class", "step"), @@ -84,7 +84,6 @@ public void Simple_steps_are_formatted_as_list_items() var formatter = Container.Resolve(); XElement actual = formatter.Format(step); - XNamespace xmlns = XNamespace.Get("http://www.w3.org/1999/xhtml"); var expected = new XElement( xmlns + "li", new XAttribute("class", "step"), @@ -112,7 +111,6 @@ public void Steps_get_selected_Language() var formatter = Container.Resolve(); XElement actual = formatter.Format(step); - XNamespace xmlns = XNamespace.Get("http://www.w3.org/1999/xhtml"); var expected = new XElement( xmlns + "li", new XAttribute("class", "step"), @@ -143,7 +141,6 @@ public void Tables_are_formatted_as_list_items_with_tables_internal() var formatter = Container.Resolve(); XElement actual = formatter.Format(step); - XNamespace xmlns = XNamespace.Get("http://www.w3.org/1999/xhtml"); var expected = new XElement( xmlns + "li", new XAttribute("class", "step"), @@ -181,5 +178,120 @@ public void Tables_are_formatted_as_list_items_with_tables_internal() Check.That(expected).IsDeeplyEqualTo(actual); } + + [Test] + public void Comments_are_displayed_above_their_related_step() + { + var step = new Step + { + Keyword = Keyword.Given, + NativeKeyword = "Given ", + Name = "a simple step", + TableArgument = null, + DocStringArgument = null, + Comments = new List + { + new Comment + { + Text = " # A simple comment", + Type = CommentType.StepComment + } + } + }; + + var formatter = Container.Resolve(); + XElement actual = formatter.Format(step); + + var expected = new XElement( + xmlns + "li", + new XAttribute("class", "step"), + new XElement(xmlns + "span", new XAttribute("class", "comment"), "# A simple comment"), + new XElement(xmlns + "span", new XAttribute("class", "keyword"), ExpectedGivenHtml), + "a simple step"); + + Check.That(expected).IsDeeplyEqualTo(actual); + } + + [Test] + public void Comments_after_the_last_step_are_displayed() + { + var step = new Step + { + Keyword = Keyword.Given, + NativeKeyword = "Given ", + Name = "a simple step", + TableArgument = null, + DocStringArgument = null, + Comments = new List + { + new Comment + { + Text = " # A simple comment", + Type = CommentType.StepComment + }, + new Comment + { + Text = " # A comment after the last step", + Type = CommentType.AfterLastStepComment + } + } + }; + + var formatter = Container.Resolve(); + XElement actual = formatter.Format(step); + + var expected = new XElement( + xmlns + "li", + new XAttribute("class", "step"), + new XElement(xmlns + "span", new XAttribute("class", "comment"), "# A simple comment"), + new XElement(xmlns + "span", new XAttribute("class", "keyword"), ExpectedGivenHtml), + "a simple step", + new XElement(xmlns + "span", new XAttribute("class", "comment"), "# A comment after the last step")); + + Check.That(expected).IsDeeplyEqualTo(actual); + } + + [Test] + public void Multiline_comments_are_displayed_in_the_same_element() + { + var step = new Step + { + Keyword = Keyword.Given, + NativeKeyword = "Given ", + Name = "a simple step", + TableArgument = null, + DocStringArgument = null, + Comments = new List + { + new Comment + { + Text = " # A first line", + Type = CommentType.StepComment + }, + new Comment + { + Text = " # A second line", + Type = CommentType.StepComment + } + } + }; + + var formatter = Container.Resolve(); + XElement actual = formatter.Format(step); + + var expected = new XElement( + xmlns + "li", + new XAttribute("class", "step"), + new XElement(xmlns + "span", new XAttribute("class", "comment"), + "# A first line", + new XElement(xmlns + "br"), + "# A second line" + ), + new XElement(xmlns + "span", new XAttribute("class", "keyword"), ExpectedGivenHtml), + "a simple step"); + + Check.That(expected).IsDeeplyEqualTo(actual); + } } } + diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature b/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature index 515d1ea99..5ff313a4b 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature @@ -17,7 +17,7 @@ Scenario: A simple feature When I press C Then the screen should be empty """ - When I generate the documentation + When I generate the documentation Then the JSON file should contain """ { @@ -35,22 +35,30 @@ Scenario: A simple feature { "Keyword": "Given", "NativeKeyword": "Given ", - "Name": "I have entered 50 into the calculator" + "Name": "I have entered 50 into the calculator", + "StepComments": [], + "AfterLastStepComments": [] }, { "Keyword": "And", "NativeKeyword": "And ", - "Name": "I have entered 70 into the calculator" + "Name": "I have entered 70 into the calculator", + "StepComments": [], + "AfterLastStepComments": [] }, { "Keyword": "When", "NativeKeyword": "When ", - "Name": "I press C" + "Name": "I press C", + "StepComments": [], + "AfterLastStepComments": [] }, { "Keyword": "Then", "NativeKeyword": "Then ", - "Name": "the screen should be empty" + "Name": "the screen should be empty", + "StepComments": [], + "AfterLastStepComments": [] } ], "Tags": [ @@ -75,7 +83,6 @@ Scenario: A simple feature } } ], - "Configuration": { """ @json @@ -117,7 +124,7 @@ Scenario: A feature with a table When I click on the table heading Then the table body should collapse """ - When I generate the documentation + When I generate the documentation Then the JSON file should contain """ { @@ -231,17 +238,23 @@ Scenario: A feature with a table "105" ] ] - } + }, + "StepComments": [], + "AfterLastStepComments": [] }, { "Keyword": "When", "NativeKeyword": "When ", - "Name": "I click on the table heading" + "Name": "I click on the table heading", + "StepComments": [], + "AfterLastStepComments": [] }, { "Keyword": "Then", "NativeKeyword": "Then ", - "Name": "the table body should collapse" + "Name": "the table body should collapse", + "StepComments": [], + "AfterLastStepComments": [] } ], "Tags": [], @@ -263,5 +276,4 @@ Scenario: A feature with a table } } ], - "Configuration": { """ \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature.cs b/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature.cs index 978dc95e8..8e70b1940 100644 --- a/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature.cs +++ b/src/Pickles/Pickles.Test/DocumentationBuilders/JSON/FormattingAFeature.feature.cs @@ -1,9 +1,8 @@ // ------------------------------------------------------------------------------ // // This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.9.0.77 -// SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34209 +// 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. @@ -16,14 +15,14 @@ namespace PicklesDoc.Pickles.Test.DocumentationBuilders.JSON using TechTalk.SpecFlow; - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")] + [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 static TechTalk.SpecFlow.ITestRunner testRunner; + private TechTalk.SpecFlow.ITestRunner testRunner; #line 1 "FormattingAFeature.feature" #line hidden @@ -32,7 +31,7 @@ public partial class FormattingAFeatureFeature 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", "", ProgrammingLanguage.CSharp, ((string[])(null))); + 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); } @@ -87,7 +86,7 @@ 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 "); + testRunner.When("I generate the documentation", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden #line 21 testRunner.Then("the JSON file should contain", "{\r\n \"Features\": [\r\n {\r\n \"RelativeFolder\": \"\",\r\n \"Feature\": {\r\n " + @@ -96,20 +95,24 @@ When I press C "r the screen\",\r\n \"FeatureElements\": [\r\n {\r\n \"Name\": \"" + "Clear the screen\",\r\n \"Description\": \"\",\r\n \"Steps\": [\r\n " + " {\r\n \"Keyword\": \"Given\",\r\n \"NativeKeyword" + - "\": \"Given \",\r\n \"Name\": \"I have entered 50 into the calculator\"\r\n " + - " },\r\n {\r\n \"Keyword\": \"And\",\r\n " + - " \"NativeKeyword\": \"And \",\r\n \"Name\": \"I have entered 70 into t" + - "he calculator\"\r\n },\r\n {\r\n \"Keyword\": \"W" + - "hen\",\r\n \"NativeKeyword\": \"When \",\r\n \"Name\": \"I pre" + - "ss C\"\r\n },\r\n {\r\n \"Keyword\": \"Then\",\r\n " + - " \"NativeKeyword\": \"Then \",\r\n \"Name\": \"the screen sho" + - "uld be empty\"\r\n }\r\n ],\r\n \"Tags\": [\r\n " + - " \"@workflow\",\r\n \"@slow\"\r\n ],\r\n \"Result\": " + - "{\r\n \"WasExecuted\": false,\r\n \"WasSuccessful\": false\r\n " + - " }\r\n }\r\n ],\r\n \"Result\": {\r\n \"WasExecute" + - "d\": false,\r\n \"WasSuccessful\": false\r\n },\r\n \"Tags\": []\r\n " + - " },\r\n \"Result\": {\r\n \"WasExecuted\": false,\r\n \"WasSuccessful" + - "\": false\r\n }\r\n }\r\n ],\r\n \"Configuration\": {", ((TechTalk.SpecFlow.Table)(null)), "Then "); + "\": \"Given \",\r\n \"Name\": \"I have entered 50 into the calculator\",\r\n" + + " \"StepComments\": [],\r\n \"AfterLastStepComments\": []" + + "\r\n },\r\n {\r\n \"Keyword\": \"And\",\r\n " + + " \"NativeKeyword\": \"And \",\r\n \"Name\": \"I have entered 70 int" + + "o the calculator\",\r\n \"StepComments\": [],\r\n \"AfterL" + + "astStepComments\": []\r\n },\r\n {\r\n \"Keywor" + + "d\": \"When\",\r\n \"NativeKeyword\": \"When \",\r\n \"Name\": " + + "\"I press C\",\r\n \"StepComments\": [],\r\n \"AfterLastSte" + + "pComments\": []\r\n },\r\n {\r\n \"Keyword\": \"T" + + "hen\",\r\n \"NativeKeyword\": \"Then \",\r\n \"Name\": \"the s" + + "creen should be empty\",\r\n \"StepComments\": [],\r\n \"A" + + "fterLastStepComments\": []\r\n }\r\n ],\r\n \"Tags\": " + + "[\r\n \"@workflow\",\r\n \"@slow\"\r\n ],\r\n " + + " \"Result\": {\r\n \"WasExecuted\": false,\r\n \"WasSuccessful" + + "\": false\r\n }\r\n }\r\n ],\r\n \"Result\": {\r\n " + + " \"WasExecuted\": false,\r\n \"WasSuccessful\": false\r\n },\r\n \"T" + + "ags\": []\r\n },\r\n \"Result\": {\r\n \"WasExecuted\": false,\r\n \"W" + + "asSuccessful\": false\r\n }\r\n }\r\n ],", ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } @@ -121,10 +124,10 @@ public virtual void AFeatureWithATable() { TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("A feature with a table", new string[] { "json"}); -#line 82 +#line 89 this.ScenarioSetup(scenarioInfo); #line hidden -#line 84 +#line 91 testRunner.Given("I have this feature description", @"Feature: Interactive DHTML View In order to increase stakeholder engagement with pickled specs As a SpecFlow evangelist @@ -158,10 +161,10 @@ I want to adjust the level of detail in the DHTML view to suit my audience | Chapter 22 | 105 | When I click on the table heading Then the table body should collapse", ((TechTalk.SpecFlow.Table)(null)), "Given "); -#line 120 - testRunner.When("I generate the documentation", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 127 + testRunner.When("I generate the documentation", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 121 +#line 128 testRunner.Then("the JSON file should contain", "{\r\n \"Features\": [\r\n {\r\n \"RelativeFolder\": \"\",\r\n \"Feature\": {\r\n " + " \"Name\": \"Interactive DHTML View\",\r\n \"Description\": \" In order to in" + "crease stakeholder engagement with pickled specs\\r\\n As a SpecFlow evangelist" + @@ -204,16 +207,19 @@ When I click on the table heading "[\r\n \"Chapter 21\",\r\n \"100\"\r\n " + " ],\r\n [\r\n \"Chapter 22\",\r\n " + " \"105\"\r\n ]\r\n ]\r\n " + - " }\r\n },\r\n {\r\n \"Keyword\": \"When\",\r\n " + - " \"NativeKeyword\": \"When \",\r\n \"Name\": \"I click on the t" + - "able heading\"\r\n },\r\n {\r\n \"Keyword\": \"Th" + - "en\",\r\n \"NativeKeyword\": \"Then \",\r\n \"Name\": \"the ta" + - "ble body should collapse\"\r\n }\r\n ],\r\n \"Tags\": " + - "[],\r\n \"Result\": {\r\n \"WasExecuted\": false,\r\n " + - " \"WasSuccessful\": false\r\n }\r\n }\r\n ],\r\n \"Result" + - "\": {\r\n \"WasExecuted\": false,\r\n \"WasSuccessful\": false\r\n " + - " },\r\n \"Tags\": []\r\n },\r\n \"Result\": {\r\n \"WasExecuted\": fal" + - "se,\r\n \"WasSuccessful\": false\r\n }\r\n }\r\n ],\r\n \"Configuration\": {", ((TechTalk.SpecFlow.Table)(null)), "Then "); + " },\r\n \"StepComments\": [],\r\n \"AfterLastStepComment" + + "s\": []\r\n },\r\n {\r\n \"Keyword\": \"When\",\r\n " + + " \"NativeKeyword\": \"When \",\r\n \"Name\": \"I click on th" + + "e table heading\",\r\n \"StepComments\": [],\r\n \"AfterLa" + + "stStepComments\": []\r\n },\r\n {\r\n \"Keyword" + + "\": \"Then\",\r\n \"NativeKeyword\": \"Then \",\r\n \"Name\": \"" + + "the table body should collapse\",\r\n \"StepComments\": [],\r\n " + + " \"AfterLastStepComments\": []\r\n }\r\n ],\r\n " + + " \"Tags\": [],\r\n \"Result\": {\r\n \"WasExecuted\": false,\r\n " + + " \"WasSuccessful\": false\r\n }\r\n }\r\n ],\r\n " + + " \"Result\": {\r\n \"WasExecuted\": false,\r\n \"WasSuccessful\": false" + + "\r\n },\r\n \"Tags\": []\r\n },\r\n \"Result\": {\r\n \"WasExecu" + + "ted\": false,\r\n \"WasSuccessful\": false\r\n }\r\n }\r\n ],", ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.feature b/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.feature new file mode 100644 index 000000000..88236250e --- /dev/null +++ b/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.feature @@ -0,0 +1,25 @@ +Feature: Test + In order to do something + As a user + I want to run this scenario + + Scenario: A scenario + # A single line comment + Given some feature + # A multiline comment - first line + # second line + And another feature + # + # Multiline with empty first line + # But the last lines are not empty + And another feature + # Multiline with empty last line + # But the first lines are not empty + # + When it runs + # Multiline with first and last last lines not empty + # + # But the middle line is empty + Then I should see that this thing happens + And there is no comment here + # A comment after the last step \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.html b/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.html new file mode 100644 index 000000000..0dd51bb87 --- /dev/null +++ b/src/Pickles/Pickles.Test/HtmlFormatterTestFiles/Comment.html @@ -0,0 +1,51 @@ + + + + + Feature: Test + + +
+

Feature: Test

+

In order to do something

+

As a user

+

I want to run this scenario

+
+
    +
  • +
    +

    Scenario: A scenario

    +

    +
    +
    +
      +
    • + # A single line comment + Given some feature +
    • +
    • + # A multiline comment - first line
      # second line
      + And another feature +
    • +
    • +
      # Multiline with empty first line
      # But the last lines are not empty
      + And another feature +
    • +
    • + # Multiline with empty last line
      # But the first lines are not empty

      + When it runs +
    • +
    • + # Multiline with first and last last lines not empty

      # But the middle line is empty
      + Then I should see that this thing happens +
    • +
    • + And there is no comment here + # A comment after the last step +
    • +
    +
    +
  • +
+ + \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/ObjectModel/Factory.cs b/src/Pickles/Pickles.Test/ObjectModel/Factory.cs index 04926abaa..b1ebcbc8a 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/Factory.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/Factory.cs @@ -66,6 +66,12 @@ internal G.Step CreateStep(string keyword, string text) return new G.Step(AnyLocation, keyword, text, null); } + internal G.Step CreateStep(string keyword, string text, int locationLine, int locationColumn) + { + var step = new G.Step(this.CreateLocation(locationLine, locationColumn), keyword, text, null); + return step; + } + internal G.Step CreateStep(string keyword, string text, string docString) { return new G.Step(AnyLocation, keyword, text, this.CreateDocString(docString)); @@ -81,11 +87,21 @@ internal G.Tag CreateTag(string tag) return new G.Tag(AnyLocation, tag); } - internal G.Scenario CreateScenario(string[] tags, string name, string description, G.Step[] steps) + internal G.Location CreateLocation(int line, int column) + { + return new G.Location(line, column); + } + + internal G.Comment CreateComment(string comment, int locationLine, int locationColumn) + { + return new G.Comment(this.CreateLocation(locationLine, locationColumn), comment); + } + + internal G.Scenario CreateScenario(string[] tags, string name, string description, G.Step[] steps, G.Location location = null) { G.Scenario scenario = new G.Scenario( tags.Select(this.CreateTag).ToArray(), - AnyLocation, + location ?? AnyLocation, "Scenario", name, description, @@ -131,9 +147,19 @@ internal G.Background CreateBackground(string name, string description, G.Step[] return background; } - internal G.Feature CreateFeature(string name, string description, string[] tags = null, G.Background background = null, G.ScenarioDefinition[] scenarioDefinitions = null) + internal G.GherkinDocument CreateGherkinDocument(string name, string description, string[] tags = null, G.Background background = null, G.ScenarioDefinition[] scenarioDefinitions = null, G.Comment[] comments = null, G.Location location = null) { - return new G.Feature((tags ?? new string[0]).Select(this.CreateTag).ToArray(), null, null, "Feature", name, description, background, scenarioDefinitions, null); + var nonNullScenarioDefinitions = scenarioDefinitions ?? new G.ScenarioDefinition[0]; + return new G.GherkinDocument( + new G.Feature( + (tags ?? new string[0]).Select(this.CreateTag).ToArray(), + location, + null, + "Feature", + name, + description, + background != null ? new G.ScenarioDefinition[] { background }.Concat(nonNullScenarioDefinitions).ToArray() : nonNullScenarioDefinitions), + comments); } } } diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForBackground.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForBackground.cs index 1cd7c6e17..057a6100e 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForBackground.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForBackground.cs @@ -97,7 +97,7 @@ public void MapToFeature_Always_MapsFeaturePropertyOfBackground() { this.factory.CreateStep("Given", "another unimportant step"), }); - var feature = this.factory.CreateFeature( + var gherkinDocument = this.factory.CreateGherkinDocument( "My Feature", "My Description", scenarioDefinitions: new G.ScenarioDefinition[] { scenario }, @@ -106,7 +106,7 @@ public void MapToFeature_Always_MapsFeaturePropertyOfBackground() var mapper = this.factory.CreateMapper(); - var mappedFeature = mapper.MapToFeature(feature); + var mappedFeature = mapper.MapToFeature(gherkinDocument); Check.That(mappedFeature.FeatureElements.Count).IsEqualTo(1); diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForComment.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForComment.cs new file mode 100644 index 000000000..97156349f --- /dev/null +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForComment.cs @@ -0,0 +1,35 @@ +using System; +using NFluent; +using NUnit.Framework; +using PicklesDoc.Pickles.ObjectModel; +using G = Gherkin.Ast; + +namespace PicklesDoc.Pickles.Test.ObjectModel +{ + [TestFixture] + public class MapperTestsForComment + { + private readonly Factory factory = new Factory(); + + [Test] + public void MapToComment_NullLocation_ReturnsNull() + { + var mapper = this.factory.CreateMapper(); + Comment result = mapper.MapToComment(null); + Check.That(result).IsNull(); + } + + [Test] + public void MapToComment_RegularComment_ReturnsComment() + { + var mapper = this.factory.CreateMapper(); + G.Comment comment = this.factory.CreateComment("# A comment", 1, 2); + Comment result = mapper.MapToComment(comment); + Check.That(result).IsNotNull(); + Check.That(result.Text).IsEqualTo("# A comment"); + Check.That(result.Location.Line).IsEqualTo(1); + Check.That(result.Location.Column).IsEqualTo(2); + Check.That(result.Type).IsEqualTo(CommentType.Normal); + } + } +} diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForFeature.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForFeature.cs index 765be28fd..ab99086d5 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForFeature.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForFeature.cs @@ -19,6 +19,7 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Linq; using NFluent; using NUnit.Framework; using PicklesDoc.Pickles.ObjectModel; @@ -44,11 +45,11 @@ public void MapToFeature_NullFeature_ReturnsNull() [Test] public void MapToFeature_FeatureWithSimpleProperties_ReturnsFeaturesWithThoseProperties() { - G.Feature feature = this.factory.CreateFeature("Title of the feature", "Description of the feature"); + var gherkinDocument = this.factory.CreateGherkinDocument("Title of the feature", "Description of the feature"); var mapper = this.factory.CreateMapper(); - var result = mapper.MapToFeature(feature); + var result = mapper.MapToFeature(gherkinDocument); Check.That(result.Name).IsEqualTo("Title of the feature"); Check.That(result.Description).IsEqualTo("Description of the feature"); @@ -57,7 +58,7 @@ public void MapToFeature_FeatureWithSimpleProperties_ReturnsFeaturesWithThosePro [Test] public void MapToFeature_FeatureWithScenarioDefinitions_ReturnsFeatureWithFeatureElements() { - var feature = this.factory.CreateFeature( + var gherkinDocument = this.factory.CreateGherkinDocument( "My Feature", string.Empty, scenarioDefinitions: new G.ScenarioDefinition[] @@ -68,7 +69,7 @@ public void MapToFeature_FeatureWithScenarioDefinitions_ReturnsFeatureWithFeatur var mapper = this.factory.CreateMapper(); - var result = mapper.MapToFeature(feature); + var result = mapper.MapToFeature(gherkinDocument); Check.That(result.FeatureElements.Count).IsEqualTo(2); Check.That(result.FeatureElements[0].Name).IsEqualTo("My scenario"); @@ -78,14 +79,14 @@ public void MapToFeature_FeatureWithScenarioDefinitions_ReturnsFeatureWithFeatur [Test] public void MapToFeature_FeatureWithBackground_ReturnsFeatureWithBackground() { - var feature = this.factory.CreateFeature( + var gherkinDocument = this.factory.CreateGherkinDocument( "My Feature", string.Empty, background: this.factory.CreateBackground("My background", "My description", new G.Step[0])); var mapper = this.factory.CreateMapper(); - var result = mapper.MapToFeature(feature); + var result = mapper.MapToFeature(gherkinDocument); Check.That(result.Background.Name).IsEqualTo("My background"); Check.That(result.Background.Description).IsEqualTo("My description"); @@ -94,13 +95,82 @@ public void MapToFeature_FeatureWithBackground_ReturnsFeatureWithBackground() [Test] public void MapToFeature_FeatureWithTags_ReturnsFeatureWithTags() { - var feature = this.factory.CreateFeature("My Feature", string.Empty, tags: new[] { "my tag 1", "my tag 2" }); + var gherkinDocument = this.factory.CreateGherkinDocument("My Feature", string.Empty, tags: new[] { "my tag 1", "my tag 2" }); var mapper = this.factory.CreateMapper(); - var result = mapper.MapToFeature(feature); + var result = mapper.MapToFeature(gherkinDocument); Check.That(result.Tags).ContainsExactly("my tag 1", "my tag 2"); } + + [Test] + public void MapToFeature_FeatureWithNullDescription_ReturnsFeatureWithEmptyDescription() + { + var gherkinDocument = this.factory.CreateGherkinDocument("My Feature", null); + + var mapper = this.factory.CreateMapper(); + + var result = mapper.MapToFeature(gherkinDocument); + + Check.That(result.Description).Equals(string.Empty); + } + + [Test] + public void MapToFeature_FeatureWithComments_ReturnsFeatureWithComments() + { + var gherkinDocument = this.factory.CreateGherkinDocument( + "My Feature", + string.Empty, + location: new G.Location(2, 0), + comments: new G.Comment[] + { + this.factory.CreateComment("# single line comment before the given step", 4, 4), + this.factory.CreateComment("# multiline comment before the then step - line 1", 6, 4), + this.factory.CreateComment("# multiline comment before the then step - line 2", 7, 4), + this.factory.CreateComment("# line comment before the last step", 10, 4), + this.factory.CreateComment("# line comment after the last step", 12, 4), + }, + scenarioDefinitions: new G.ScenarioDefinition[] + { + this.factory.CreateScenario( + new string[0], "My scenario", string.Empty, + new G.Step[] + { + this.factory.CreateStep("Given", "I am on the first step", 5, 4), + this.factory.CreateStep("When", "I am on the second step", 8, 4), + this.factory.CreateStep("When", "there is a third step without comment", 9, 4), + this.factory.CreateStep("Then", "I am on the last step", 11, 4) + }, + location: new G.Location(3, 0) + ) + }); + + var mapper = this.factory.CreateMapper(); + + var result = mapper.MapToFeature(gherkinDocument); + var scenario = result.FeatureElements[0]; + + Check.That(scenario.Steps[0].Comments.Count).IsEqualTo(1); + Check.That(scenario.Steps[0].Comments.Count(o => o.Type == CommentType.StepComment)).IsEqualTo(1); + Check.That(scenario.Steps[0].Comments.Count(o => o.Type == CommentType.AfterLastStepComment)).IsEqualTo(0); + Check.That(scenario.Steps[0].Comments[0].Text).IsEqualTo("# single line comment before the given step"); + + Check.That(scenario.Steps[1].Comments.Count).IsEqualTo(2); + Check.That(scenario.Steps[1].Comments.Count(o => o.Type == CommentType.StepComment)).IsEqualTo(2); + Check.That(scenario.Steps[1].Comments.Count(o => o.Type == CommentType.AfterLastStepComment)).IsEqualTo(0); + Check.That(scenario.Steps[1].Comments[0].Text).IsEqualTo("# multiline comment before the then step - line 1"); + Check.That(scenario.Steps[1].Comments[1].Text).IsEqualTo("# multiline comment before the then step - line 2"); + + Check.That(scenario.Steps[2].Comments.Count).IsEqualTo(0); + Check.That(scenario.Steps[2].Comments.Count(o => o.Type == CommentType.StepComment)).IsEqualTo(0); + Check.That(scenario.Steps[2].Comments.Count(o => o.Type == CommentType.AfterLastStepComment)).IsEqualTo(0); + + Check.That(scenario.Steps[3].Comments.Count).IsEqualTo(2); + Check.That(scenario.Steps[3].Comments.Count(o => o.Type == CommentType.StepComment)).IsEqualTo(1); + Check.That(scenario.Steps[3].Comments.Count(o => o.Type == CommentType.AfterLastStepComment)).IsEqualTo(1); + Check.That(scenario.Steps[3].Comments[0].Text).IsEqualTo("# line comment before the last step"); + Check.That(scenario.Steps[3].Comments[1].Text).IsEqualTo("# line comment after the last step"); + } } -} +} \ No newline at end of file diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForLocation.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForLocation.cs new file mode 100644 index 000000000..235d5b97f --- /dev/null +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForLocation.cs @@ -0,0 +1,33 @@ +using System; +using NFluent; +using NUnit.Framework; +using PicklesDoc.Pickles.ObjectModel; +using G = Gherkin.Ast; + +namespace PicklesDoc.Pickles.Test.ObjectModel +{ + [TestFixture] + public class MapperTestsForLocation + { + private readonly Factory factory = new Factory(); + + [Test] + public void MapToLocation_NullLocation_ReturnsNull() + { + var mapper = this.factory.CreateMapper(); + Location result = mapper.MapToLocation(null); + Check.That(result).IsNull(); + } + + [Test] + public void MapToLocation_RegularLocation_ReturnsLocation() + { + var mapper = this.factory.CreateMapper(); + G.Location location = this.factory.CreateLocation(1, 2); + Location result = mapper.MapToLocation(location); + Check.That(result).IsNotNull(); + Check.That(result.Line).IsEqualTo(1); + Check.That(result.Column).IsEqualTo(2); + } + } +} diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenario.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenario.cs index 5af569b8c..dddcb1a48 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenario.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenario.cs @@ -100,7 +100,7 @@ public void MapToScenario_Always_MapsFeatureProperty() "My scenario title", null, new[] { this.factory.CreateStep("Given", "unimportant step") }); - var feature = this.factory.CreateFeature( + var gherkinDocument = this.factory.CreateGherkinDocument( "My Feature", "My Description", scenarioDefinitions: new G.ScenarioDefinition[] { scenario }); @@ -108,7 +108,7 @@ public void MapToScenario_Always_MapsFeatureProperty() var mapper = this.factory.CreateMapper(); - var mappedFeature = mapper.MapToFeature(feature); + var mappedFeature = mapper.MapToFeature(gherkinDocument); Check.That(mappedFeature.FeatureElements.Count).IsEqualTo(1); diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenarioOutline.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenarioOutline.cs index 0825e0ac9..d0e4c6097 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenarioOutline.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForScenarioOutline.cs @@ -122,7 +122,7 @@ public void MapToScenarioOutline_Always_MapsFeatureProperty() null, new[] { this.factory.CreateStep("Given", "unimportant step") }, null); - var feature = this.factory.CreateFeature( + var gherkinDocument = this.factory.CreateGherkinDocument( "My Feature", "My Description", scenarioDefinitions: new G.ScenarioDefinition[] { scenarioOutline }); @@ -130,7 +130,7 @@ public void MapToScenarioOutline_Always_MapsFeatureProperty() var mapper = this.factory.CreateMapper(); - var mappedFeature = mapper.MapToFeature(feature); + var mappedFeature = mapper.MapToFeature(gherkinDocument); Check.That(mappedFeature.FeatureElements.Count).IsEqualTo(1); diff --git a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForStep.cs b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForStep.cs index d41579509..2ee25a1a1 100644 --- a/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForStep.cs +++ b/src/Pickles/Pickles.Test/ObjectModel/MapperTestsForStep.cs @@ -55,6 +55,8 @@ public void MapToStep_StepWithoutArgument_ReturnStep() Check.That(result.Name).IsEqualTo("I enter '50' in the calculator"); Check.That(result.DocStringArgument).IsNull(); Check.That(result.TableArgument).IsNull(); + Check.That(result.Location).IsNull(); + Check.That(result.Comments).IsEmpty(); } [Test] @@ -71,6 +73,8 @@ public void MapToStep_StepWithWhen_ReturnStep() Check.That(result.Name).IsEqualTo("I press 'enter'"); Check.That(result.DocStringArgument).IsNull(); Check.That(result.TableArgument).IsNull(); + Check.That(result.Location).IsNull(); + Check.That(result.Comments).IsEmpty(); } [Test] @@ -107,6 +111,8 @@ public void MapToStep_StepWithDocStringArgument_ReturnStepWithDocString() Check.That(result.Name).IsEqualTo("I see this value on the screen"); Check.That(result.DocStringArgument).IsEqualTo("120"); Check.That(result.TableArgument).IsNull(); + Check.That(result.Location).IsNull(); + Check.That(result.Comments).IsEmpty(); } [Test] @@ -132,6 +138,30 @@ public void MapToStep_StepWithTableArgument_ReturnStepWithTable() Check.That(result.TableArgument.DataRows).HasSize(1); Check.That(result.TableArgument.DataRows[0].Cells).ContainsExactly("Value 1", "Value 2"); Check.That(result.DocStringArgument).IsNull(); + Check.That(result.Location).IsNull(); + Check.That(result.Comments).IsEmpty(); + } + + [Test] + public void MapToStep_StepWithLocation_ReturnStepWithLocation() + { + var mapper = this.factory.CreateMapper(); + + G.Step step = this.factory.CreateStep( + "Given", "I am on a step", 3, 4 + ); + + var result = mapper.MapToStep(step); + + Check.That(result.Keyword).IsEqualTo(Keyword.Given); + Check.That(result.NativeKeyword).IsEqualTo("Given"); + Check.That(result.Name).IsEqualTo("I am on a step"); + Check.That(result.DocStringArgument).IsNull(); + Check.That(result.TableArgument).IsNull(); + Check.That(result.Location).IsNotNull(); + Check.That(result.Location.Line).IsEqualTo(3); + Check.That(result.Location.Column).IsEqualTo(4); + Check.That(result.Comments).IsEmpty(); } } } diff --git a/src/Pickles/Pickles.Test/Pickles.Test.csproj b/src/Pickles/Pickles.Test/Pickles.Test.csproj index 3e4854a19..021a922e8 100644 --- a/src/Pickles/Pickles.Test/Pickles.Test.csproj +++ b/src/Pickles/Pickles.Test/Pickles.Test.csproj @@ -48,7 +48,7 @@ True
- ..\packages\Gherkin.3.2.0\lib\net45\Gherkin.dll + ..\packages\Gherkin.4.0.0\lib\net45\Gherkin.dll True @@ -56,7 +56,7 @@ True - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True @@ -67,27 +67,28 @@ False ..\packages\NGenerics.1.4.1.0\lib\net35\NGenerics.dll - - False - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + + ..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll + True - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True - - ..\packages\System.IO.Abstractions.TestingHelpers.2.0.0.123\lib\net40\System.IO.Abstractions.TestingHelpers.dll + + ..\packages\System.IO.Abstractions.TestingHelpers.2.0.0.124\lib\net40\System.IO.Abstractions.TestingHelpers.dll True - - ..\packages\SpecFlow.1.9.0\lib\net35\TechTalk.SpecFlow.dll + + ..\packages\SpecFlow.2.0.0\lib\net45\TechTalk.SpecFlow.dll + True
@@ -115,11 +116,13 @@ + + @@ -217,6 +220,7 @@ SpecFlowSingleFileGenerator FormattingAFeature.feature.cs + ResXFileCodeGenerator @@ -226,6 +230,7 @@ SimplestFile.feature.cs + SimplestFile.feature.cs diff --git a/src/Pickles/Pickles.Test/TestResultExtensionsTests.cs b/src/Pickles/Pickles.Test/TestResultExtensionsTests.cs index e307ec25e..a7ff1bde3 100644 --- a/src/Pickles/Pickles.Test/TestResultExtensionsTests.cs +++ b/src/Pickles/Pickles.Test/TestResultExtensionsTests.cs @@ -30,10 +30,9 @@ namespace PicklesDoc.Pickles.Test public class TestResultExtensionsTests { [Test] - [ExpectedException(typeof(ArgumentNullException))] public void Merge_NullReference_ThrowsArgumentNullException() { - TestResultExtensions.Merge(null); + Check.ThatCode(() => TestResultExtensions.Merge(null)).Throws(); } [Test] diff --git a/src/Pickles/Pickles.Test/WhenParsingFeatureFiles.cs b/src/Pickles/Pickles.Test/WhenParsingFeatureFiles.cs index 79bfd49f7..c5f62dbd6 100644 --- a/src/Pickles/Pickles.Test/WhenParsingFeatureFiles.cs +++ b/src/Pickles/Pickles.Test/WhenParsingFeatureFiles.cs @@ -353,5 +353,47 @@ When it runs Check.That(feature.FeatureElements[0].Tags[0]).IsEqualTo("@scenario-tag-1"); Check.That(feature.FeatureElements[0].Tags[1]).IsEqualTo("@scenario-tag-2"); } + + [Test] + public void Then_can_parse_scenario_with_comments_successfully() + { + string featureText = + @"# ignore this comment +Feature: Test + In order to do something + As a user + I want to run this scenario + + Scenario: A scenario + # A single line comment + Given some feature + # A multiline comment - first line + # Second line + When it runs + Then I should see that this thing happens + # A last comment after the scenario"; + + var parser = Container.Resolve(); + Feature feature = parser.Parse(new StringReader(featureText)); + + IFeatureElement scenario = feature.FeatureElements.First(); + + Step stepGiven = scenario.Steps[0]; + Check.That(stepGiven.Comments.Count).IsEqualTo(1); + Check.That(stepGiven.Comments[0].Text).IsEqualTo("# A single line comment"); + + Step stepWhen = scenario.Steps[1]; + Check.That(stepWhen.Comments.Count).IsEqualTo(2); + Check.That(stepWhen.Comments[0].Text).IsEqualTo("# A multiline comment - first line"); + Check.That(stepWhen.Comments[1].Text).IsEqualTo("# Second line"); + + Step stepThen = scenario.Steps[2]; + Check.That(stepThen.Comments.Count).IsEqualTo(1); + Check.That(stepThen.Comments.Count(o => o.Type == CommentType.StepComment)).IsEqualTo(0); + Check.That(stepThen.Comments.Count(o => o.Type == CommentType.AfterLastStepComment)).IsEqualTo(1); + Check.That(stepThen.Comments[0].Text = "# A last comment after the scenario"); + } + + } } diff --git a/src/Pickles/Pickles.Test/packages.config b/src/Pickles/Pickles.Test/packages.config index cefbd6f92..2e1033e13 100644 --- a/src/Pickles/Pickles.Test/packages.config +++ b/src/Pickles/Pickles.Test/packages.config @@ -3,13 +3,13 @@ - + - + - - - - + + + + \ No newline at end of file diff --git a/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit2/WhenDeterminingTheSignatureOfAnNUnitExampleRow.cs b/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit2/WhenDeterminingTheSignatureOfAnNUnitExampleRow.cs index 4610cddaf..3f26f3ee3 100644 --- a/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit2/WhenDeterminingTheSignatureOfAnNUnitExampleRow.cs +++ b/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit2/WhenDeterminingTheSignatureOfAnNUnitExampleRow.cs @@ -48,5 +48,18 @@ public void ThenCanSuccessfullyMatch() var isMatch = signature.IsMatch("Pickles.TestHarness.AdditionFeature.AddingSeveralNumbers(\"40\",\"50\",\"90\",System.String[])".ToLowerInvariant()); Check.That(isMatch).IsTrue(); } + + [Test] + public void ThenCanSuccessfullyMatchSpecialCharacters() + { + var scenarioOutline = new ScenarioOutline { Name = "Adding several numbers (foo-bar, foo bar)" }; + var exampleRow = new[] { "40", "50", "90" }; + + var signatureBuilder = new NUnitExampleSignatureBuilder(); + Regex signature = signatureBuilder.Build(scenarioOutline, exampleRow); + + var isMatch = signature.IsMatch("Pickles.TestHarness.AdditionFeature.AddingSeveralNumbersFoo_BarFooBar(\"40\",\"50\",\"90\",System.String[])".ToLowerInvariant()); + Check.That(isMatch).IsTrue(); + } } } diff --git a/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit3/WhenDeterminingTheSignatureOfAnNunit3ExampleRow.cs b/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit3/WhenDeterminingTheSignatureOfAnNunit3ExampleRow.cs index e7e96aa64..cb3137517 100644 --- a/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit3/WhenDeterminingTheSignatureOfAnNunit3ExampleRow.cs +++ b/src/Pickles/Pickles.TestFrameworks.UnitTests/NUnit/NUnit3/WhenDeterminingTheSignatureOfAnNunit3ExampleRow.cs @@ -48,5 +48,18 @@ public void ThenCanSuccessfullyMatch() var isMatch = signature.IsMatch("AddingSeveralNumbers(\"40\",\"50\",\"90\",System.String[])".ToLowerInvariant()); Check.That(isMatch).IsTrue(); } + + [Test] + public void ThenCanSuccessfullyMatchSpecialCharacters() + { + var scenarioOutline = new ScenarioOutline { Name = "Adding several numbers (foo-bar, foo bar)" }; + var exampleRow = new[] { "40", "50", "90" }; + + var signatureBuilder = new NUnitExampleSignatureBuilder(); + Regex signature = signatureBuilder.Build(scenarioOutline, exampleRow); + + var isMatch = signature.IsMatch("AddingSeveralNumbersFoo_BarFooBar(\"40\",\"50\",\"90\",System.String[])".ToLowerInvariant()); + Check.That(isMatch).IsTrue(); + } } } diff --git a/src/Pickles/Pickles.TestFrameworks.UnitTests/Pickles.TestFrameworks.UnitTests.csproj b/src/Pickles/Pickles.TestFrameworks.UnitTests/Pickles.TestFrameworks.UnitTests.csproj index 47c6514c3..742e31015 100644 --- a/src/Pickles/Pickles.TestFrameworks.UnitTests/Pickles.TestFrameworks.UnitTests.csproj +++ b/src/Pickles/Pickles.TestFrameworks.UnitTests/Pickles.TestFrameworks.UnitTests.csproj @@ -42,19 +42,19 @@ ..\packages\NFluent.1.3.1.0\lib\net40\NFluent.dll True
- - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + + ..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll True - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True - - ..\packages\System.IO.Abstractions.TestingHelpers.2.0.0.123\lib\net40\System.IO.Abstractions.TestingHelpers.dll + + ..\packages\System.IO.Abstractions.TestingHelpers.2.0.0.124\lib\net40\System.IO.Abstractions.TestingHelpers.dll True diff --git a/src/Pickles/Pickles.TestFrameworks.UnitTests/app.config b/src/Pickles/Pickles.TestFrameworks.UnitTests/app.config index adf336ea8..9f64d3070 100644 --- a/src/Pickles/Pickles.TestFrameworks.UnitTests/app.config +++ b/src/Pickles/Pickles.TestFrameworks.UnitTests/app.config @@ -4,7 +4,7 @@ - + diff --git a/src/Pickles/Pickles.TestFrameworks.UnitTests/packages.config b/src/Pickles/Pickles.TestFrameworks.UnitTests/packages.config index 9674201ef..f0de9e7c6 100644 --- a/src/Pickles/Pickles.TestFrameworks.UnitTests/packages.config +++ b/src/Pickles/Pickles.TestFrameworks.UnitTests/packages.config @@ -3,7 +3,7 @@ - - - + + + \ No newline at end of file diff --git a/src/Pickles/Pickles.TestFrameworks/NUnit/NUnitExampleSignatureBuilder.cs b/src/Pickles/Pickles.TestFrameworks/NUnit/NUnitExampleSignatureBuilder.cs index 6c845c8b9..663a326ad 100644 --- a/src/Pickles/Pickles.TestFrameworks/NUnit/NUnitExampleSignatureBuilder.cs +++ b/src/Pickles/Pickles.TestFrameworks/NUnit/NUnitExampleSignatureBuilder.cs @@ -27,10 +27,17 @@ namespace PicklesDoc.Pickles.TestFrameworks.NUnit { public class NUnitExampleSignatureBuilder { + private static readonly Regex PunctuationCharactersRegex = new Regex(@"[\n\.-]+", RegexOptions.Compiled); + private static readonly Regex NonIdentifierCharacterRegex = new Regex(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Nd}\p{Pc}]", RegexOptions.Compiled); + public Regex Build(ScenarioOutline scenarioOutline, string[] row) { var stringBuilder = new StringBuilder(); - stringBuilder.Append(scenarioOutline.Name.ToLowerInvariant().Replace(" ", string.Empty) + "\\("); + + var name = scenarioOutline.Name.ToLowerInvariant(); + name = PunctuationCharactersRegex.Replace(name, "_"); + name = NonIdentifierCharacterRegex.Replace(name, string.Empty); + stringBuilder.Append(name).Append("\\("); foreach (string value in row) { diff --git a/src/Pickles/Pickles.TestFrameworks/Pickles.TestFrameworks.csproj b/src/Pickles/Pickles.TestFrameworks/Pickles.TestFrameworks.csproj index 5fa51d9b4..f3d1d8e74 100644 --- a/src/Pickles/Pickles.TestFrameworks/Pickles.TestFrameworks.csproj +++ b/src/Pickles/Pickles.TestFrameworks/Pickles.TestFrameworks.csproj @@ -31,14 +31,14 @@ - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True diff --git a/src/Pickles/Pickles.TestFrameworks/packages.config b/src/Pickles/Pickles.TestFrameworks/packages.config index 1cc9bd3a9..b8c73332b 100644 --- a/src/Pickles/Pickles.TestFrameworks/packages.config +++ b/src/Pickles/Pickles.TestFrameworks/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/src/Pickles/Pickles.UserInterface/Pickles.UserInterface.csproj b/src/Pickles/Pickles.UserInterface/Pickles.UserInterface.csproj index 571a49f9b..68d4c5b40 100644 --- a/src/Pickles/Pickles.UserInterface/Pickles.UserInterface.csproj +++ b/src/Pickles/Pickles.UserInterface/Pickles.UserInterface.csproj @@ -60,8 +60,8 @@ ..\packages\MvvmLightLibs.5.2.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll True - - ..\packages\MahApps.Metro.1.2.2.0\lib\net45\MahApps.Metro.dll + + ..\packages\MahApps.Metro.1.2.4.0\lib\net45\MahApps.Metro.dll True @@ -81,13 +81,13 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True - ..\packages\MahApps.Metro.1.2.2.0\lib\net45\System.Windows.Interactivity.dll + ..\packages\MahApps.Metro.1.2.4.0\lib\net45\System.Windows.Interactivity.dll True diff --git a/src/Pickles/Pickles.UserInterface/Pickles.ico b/src/Pickles/Pickles.UserInterface/Pickles.ico index 4d154e851..3b00583b6 100644 Binary files a/src/Pickles/Pickles.UserInterface/Pickles.ico and b/src/Pickles/Pickles.UserInterface/Pickles.ico differ diff --git a/src/Pickles/Pickles.UserInterface/app.config b/src/Pickles/Pickles.UserInterface/app.config index 2ed47dc48..8532e644c 100644 --- a/src/Pickles/Pickles.UserInterface/app.config +++ b/src/Pickles/Pickles.UserInterface/app.config @@ -18,26 +18,6 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/Pickles/Pickles.UserInterface/packages.config b/src/Pickles/Pickles.UserInterface/packages.config index d351b1c2b..321019580 100644 --- a/src/Pickles/Pickles.UserInterface/packages.config +++ b/src/Pickles/Pickles.UserInterface/packages.config @@ -2,12 +2,12 @@ - + - + \ No newline at end of file diff --git a/src/Pickles/Pickles.sln.GhostDoc.xml b/src/Pickles/Pickles.sln.GhostDoc.xml index 4f471f9da..fab28c848 100644 --- a/src/Pickles/Pickles.sln.GhostDoc.xml +++ b/src/Pickles/Pickles.sln.GhostDoc.xml @@ -44,6 +44,10 @@ true + + + + diff --git a/src/Pickles/Pickles.v2.ncrunchsolution b/src/Pickles/Pickles.v2.ncrunchsolution index fcf533251..6fe82b758 100644 --- a/src/Pickles/Pickles.v2.ncrunchsolution +++ b/src/Pickles/Pickles.v2.ncrunchsolution @@ -1,12 +1,17 @@ - + 1 + false true true UseDynamicAnalysis UseStaticAnalysis UseStaticAnalysis UseStaticAnalysis + UseDynamicAnalysis + Run all tests automatically:BFRydWU=;Run all tests manually:BUZhbHNl;Run impacted tests automatically, others manually (experimental!):CklzSW1wYWN0ZWQ=;Run pinned tests automatically, others manually:CElzUGlubmVk +Pickles.Test\Pickles.Test.csproj +Pickles.TestFrameworks.UnitTests\Pickles.TestFrameworks.UnitTests.csproj \ No newline at end of file diff --git a/src/Pickles/Pickles/DocumentationBuilders/Excel/ExcelStepFormatter.cs b/src/Pickles/Pickles/DocumentationBuilders/Excel/ExcelStepFormatter.cs index 7306cf7c6..63aaf51cc 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/Excel/ExcelStepFormatter.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/Excel/ExcelStepFormatter.cs @@ -19,6 +19,7 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Linq; using ClosedXML.Excel; using PicklesDoc.Pickles.ObjectModel; @@ -40,11 +41,35 @@ public ExcelStepFormatter( public void Format(IXLWorksheet worksheet, Step step, ref int row) { + // Add comments + if (step.Comments.Any(o => o.Type == CommentType.StepComment)) + { + foreach (var comment in step.Comments.Where(o => o.Type == CommentType.StepComment)) + { + worksheet.Cell(row, "C").Style.Font.SetItalic(); + worksheet.Cell(row, "C").Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Left); + worksheet.Cell(row, "C").Value = comment.Text; + row++; + } + } + worksheet.Cell(row, "C").Style.Font.SetBold(); worksheet.Cell(row, "C").Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right); worksheet.Cell(row, "C").Value = step.NativeKeyword; worksheet.Cell(row++, "D").Value = step.Name; + if (step.Comments.Any(o => o.Type == CommentType.AfterLastStepComment)) + { + foreach (var comment in step.Comments.Where(o => o.Type == CommentType.AfterLastStepComment)) + { + worksheet.Cell(row, "C").Style.Font.SetItalic(); + worksheet.Cell(row, "C").Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Left); + worksheet.Cell(row, "C").Value = comment.Text; + row++; + } + } + + if (step.TableArgument != null) { this.excelTableFormatter.Format(worksheet, step.TableArgument, ref row); diff --git a/src/Pickles/Pickles/DocumentationBuilders/HTML/HtmlStepFormatter.cs b/src/Pickles/Pickles/DocumentationBuilders/HTML/HtmlStepFormatter.cs index 2a4d9883d..0024f4c62 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/HTML/HtmlStepFormatter.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/HTML/HtmlStepFormatter.cs @@ -19,8 +19,8 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Linq; using System.Xml.Linq; - using PicklesDoc.Pickles.ObjectModel; namespace PicklesDoc.Pickles.DocumentationBuilders.HTML @@ -45,13 +45,42 @@ public HtmlStepFormatter( this.xmlns = HtmlNamespace.Xhtml; } + protected XElement FormatComments(Step step, CommentType type) + { + XElement comment = new XElement(this.xmlns + "span", new XAttribute("class", "comment")); + + foreach (var stepComment in step.Comments.Where(o => o.Type == type)) + { + comment.Add(stepComment.Text.Trim()); + comment.Add(new XElement(this.xmlns + "br")); + } + comment.LastNode.Remove(); + + return comment; + } + public XElement Format(Step step) { - var li = new XElement( - this.xmlns + "li", - new XAttribute("class", "step"), - new XElement(this.xmlns + "span", new XAttribute("class", "keyword"), step.NativeKeyword), - step.Name); + XElement li; + + XElement beforeStepComments = null; + XElement afterStepComments = null; + if (step.Comments.Any(o => o.Type == CommentType.StepComment)) + { + beforeStepComments = this.FormatComments(step, CommentType.StepComment); + } + if (step.Comments.Any(o => o.Type == CommentType.AfterLastStepComment)) + { + afterStepComments = this.FormatComments(step, CommentType.AfterLastStepComment); + } + + li = new XElement( + this.xmlns + "li", + new XAttribute("class", "step"), + beforeStepComments, + new XElement(this.xmlns + "span", new XAttribute("class", "keyword"), step.NativeKeyword), + step.Name, + afterStepComments); if (step.TableArgument != null) { diff --git a/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonComment.cs b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonComment.cs new file mode 100644 index 000000000..2d6efde3f --- /dev/null +++ b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonComment.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// 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.Collections.Generic; +using PicklesDoc.Pickles.ObjectModel; + +namespace PicklesDoc.Pickles.DocumentationBuilders.JSON +{ + public class JsonComment + { + public string Text { get; set; } + } +} diff --git a/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonMapper.cs b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonMapper.cs index 1010a036b..48751a5dc 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonMapper.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonMapper.cs @@ -19,6 +19,8 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Collections.Generic; +using System.Linq; using AutoMapper; using AutoMapper.Mappers; using PicklesDoc.Pickles.ObjectModel; @@ -52,7 +54,17 @@ public JsonMapper() .ForMember(t => t.Feature, opt => opt.Ignore()); configurationStore.CreateMap() .ForMember(t => t.Feature, opt => opt.Ignore()); - configurationStore.CreateMap(); + configurationStore.CreateMap(); + configurationStore.CreateMap() + .ForMember(t => t.StepComments, opt => opt.UseValue(new List())) + .ForMember(t => t.AfterLastStepComments, opt => opt.UseValue(new List())) + .AfterMap( + (sourceStep, targetStep) => + { + this.mapper.Map(sourceStep.Comments.Where(o => o.Type == CommentType.StepComment), targetStep.StepComments); + this.mapper.Map(sourceStep.Comments.Where(o => o.Type == CommentType.AfterLastStepComment), targetStep.AfterLastStepComments); + } + ); configurationStore.CreateMap(); configurationStore.CreateMap().ConstructUsing(ToJsonTestResult); diff --git a/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonStep.cs b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonStep.cs index cbe1d3854..142880616 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonStep.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/JSON/JsonStep.cs @@ -19,6 +19,8 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Collections.Generic; +using PicklesDoc.Pickles.ObjectModel; namespace PicklesDoc.Pickles.DocumentationBuilders.JSON { @@ -33,5 +35,9 @@ public class JsonStep public JsonTable TableArgument { get; set; } public string DocStringArgument { get; set; } + + public List StepComments { get; set; } + + public List AfterLastStepComments { get; set; } } } diff --git a/src/Pickles/Pickles/DocumentationBuilders/Word/WordStepFormatter.cs b/src/Pickles/Pickles/DocumentationBuilders/Word/WordStepFormatter.cs index 05300dcef..13ac60dae 100644 --- a/src/Pickles/Pickles/DocumentationBuilders/Word/WordStepFormatter.cs +++ b/src/Pickles/Pickles/DocumentationBuilders/Word/WordStepFormatter.cs @@ -19,6 +19,7 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Linq; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Wordprocessing; using PicklesDoc.Pickles.Extensions; @@ -61,10 +62,35 @@ public static Paragraph GenerateStepParagraph(Step step) { // HACK - We need to generate a custom paragraph here because 2 Run objects are needed to allow for the bolded keyword var paragraph = new Paragraph(new ParagraphProperties(new ParagraphStyleId { Val = "Normal" })); + + // Add comments before step + if (step.Comments.Any(o => o.Type == CommentType.StepComment)) + { + foreach (var comment in step.Comments.Where(o => o.Type == CommentType.StepComment)) + { + paragraph.Append(new Run(new RunProperties(new Italic()), new Text(comment.Text))); + paragraph.Append(new Break()); + } + } + + // Add step paragraph.Append(new Run(new RunProperties(new Bold()), new Text(step.NativeKeyword))); var nameText = new Text { Space = SpaceProcessingModeValues.Preserve }; nameText.Text = " " + step.Name; paragraph.Append(new Run(nameText)); + + // Add comments after step + if (step.Comments.Any(o => o.Type == CommentType.AfterLastStepComment)) + { + paragraph.Append(new Break()); + + foreach (var comment in step.Comments.Where(o => o.Type == CommentType.AfterLastStepComment)) + { + paragraph.Append(new Run(new RunProperties(new Italic()), new Text(comment.Text))); + paragraph.Append(new Break()); + } + } + return paragraph; } } diff --git a/src/Pickles/Pickles/FeatureParser.cs b/src/Pickles/Pickles/FeatureParser.cs index 2077575bf..9aa5afa9a 100644 --- a/src/Pickles/Pickles/FeatureParser.cs +++ b/src/Pickles/Pickles/FeatureParser.cs @@ -67,11 +67,11 @@ public Feature Parse(TextReader featureFileReader) var language = this.DetermineLanguage(); var gherkinParser = new Gherkin.Parser(); - Gherkin.Ast.Feature feature = gherkinParser.Parse( + Gherkin.Ast.GherkinDocument gherkinDocument = gherkinParser.Parse( new Gherkin.TokenScanner(featureFileReader), new Gherkin.TokenMatcher(language)); - Feature result = new Mapper(feature.Language).MapToFeature(feature); + Feature result = new Mapper(gherkinDocument.Feature.Language).MapToFeature(gherkinDocument); return result; } diff --git a/src/Pickles/Pickles/ObjectModel/Mapper.cs b/src/Pickles/Pickles/ObjectModel/Mapper.cs index ef77feef8..5adc54a03 100644 --- a/src/Pickles/Pickles/ObjectModel/Mapper.cs +++ b/src/Pickles/Pickles/ObjectModel/Mapper.cs @@ -51,9 +51,24 @@ public Mapper(string featureLanguage = LanguageServices.DefaultLanguage) configurationStore.CreateMap().ConstructUsing(docString => docString.Content); + configurationStore.CreateMap() + .ForMember(t => t.Column, opt => opt.MapFrom(s => s.Column)) + .ForMember(t => t.Line, opt => opt.MapFrom(s => s.Line)); + + configurationStore.CreateMap() + .ForMember(t => t.Text, opt => opt.MapFrom(s => s.Text)) + .ForMember(t => t.Location, opt => opt.MapFrom(s => s.Location)) + .AfterMap( + (sourceComment, targetComment) => + { + targetComment.Text = targetComment.Text.Trim(); + } + ); + configurationStore.CreateMap() .ForMember(t => t.NativeKeyword, opt => opt.MapFrom(s => s.Keyword)) .ForMember(t => t.Name, opt => opt.MapFrom(s => s.Text)) + .ForMember(t => t.Location, opt => opt.MapFrom(s => s.Location)) .ForMember(t => t.DocStringArgument, opt => opt.MapFrom(s => s.Argument is G.DocString ? s.Argument : null)) .ForMember(t => t.TableArgument, opt => opt.MapFrom(s => s.Argument is G.DataTable ? s.Argument : null)); @@ -61,7 +76,8 @@ public Mapper(string featureLanguage = LanguageServices.DefaultLanguage) .ConstructUsing(tag => tag.Name); configurationStore.CreateMap() - .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)); + .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)) + .ForMember(t => t.Location, opt => opt.MapFrom(s => s.Location)); configurationStore.CreateMap, Table>() .ForMember(t => t.HeaderRow, opt => opt.MapFrom(s => s.Take(1).Single())) @@ -71,7 +87,8 @@ public Mapper(string featureLanguage = LanguageServices.DefaultLanguage) .ForMember(t => t.TableArgument, opt => opt.MapFrom(s => ((G.IHasRows)s).Rows)); configurationStore.CreateMap() - .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)); + .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)) + .ForMember(t => t.Location, opt => opt.MapFrom(s => s.Location)); configurationStore.CreateMap() .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)); @@ -79,6 +96,11 @@ public Mapper(string featureLanguage = LanguageServices.DefaultLanguage) configurationStore.CreateMap().ConvertUsing( sd => { + if (sd == null) + { + return null; + } + var scenario = sd as G.Scenario; if (scenario != null) { @@ -91,14 +113,56 @@ public Mapper(string featureLanguage = LanguageServices.DefaultLanguage) return this.mapper.Map(scenarioOutline); } - throw new ArgumentException("Only arguments of type Scenario and ScenarioOutline are supported."); + var background = sd as G.Background; + if (background != null) + { + return this.mapper.Map(background); + } + + throw new ArgumentException("Only arguments of type Scenario, ScenarioOutline and Background are supported."); }); - configurationStore.CreateMap() - .ForMember(t => t.FeatureElements, opt => opt.ResolveUsing(s => s.ScenarioDefinitions)) + configurationStore.CreateMap() + .ForMember(t => t.Background, opt => opt.ResolveUsing(s => s.Feature.Children.SingleOrDefault(c => c is G.Background) as G.Background)) + .ForMember(t => t.Comments, opt => opt.ResolveUsing(s => s.Comments)) + .ForMember(t => t.Description, opt => opt.ResolveUsing(s => s.Feature.Description)) + .ForMember(t => t.FeatureElements, opt => opt.ResolveUsing(s => s.Feature.Children.Where(c => !(c is G.Background)))) + .ForMember(t => t.Name, opt => opt.ResolveUsing(s => s.Feature.Name)) + .ForMember(t => t.Tags, opt => opt.ResolveUsing(s => s.Feature.Tags)) + + + .ForMember(t => t.Description, opt => opt.NullSubstitute(string.Empty)) .AfterMap( (sourceFeature, targetFeature) => { + foreach (var comment in targetFeature.Comments.ToArray()) + { + // Find the related feature + var relatedFeatureElement = targetFeature.FeatureElements.LastOrDefault(x => x.Location.Line < comment.Location.Line); + // Find the step to which the comment is related to + if (relatedFeatureElement != null) + { + var stepAfterComment = relatedFeatureElement.Steps.FirstOrDefault(x => x.Location.Line > comment.Location.Line); + if (stepAfterComment != null) + { + // Comment is before a step + comment.Type = CommentType.StepComment; + stepAfterComment.Comments.Add(comment); + } + else + { + // Comment is located after the last step + var stepBeforeComment = relatedFeatureElement.Steps.LastOrDefault(x => x.Location.Line < comment.Location.Line); + if (stepBeforeComment != null && stepBeforeComment == relatedFeatureElement.Steps.Last()) + { + + comment.Type = CommentType.AfterLastStepComment; + stepBeforeComment.Comments.Add(comment); + } + } + } + } + foreach (var featureElement in targetFeature.FeatureElements.ToArray()) { featureElement.Feature = targetFeature; @@ -146,6 +210,16 @@ public string MapToString(G.Tag tag) return this.mapper.Map(tag); } + public Comment MapToComment(G.Comment comment) + { + return this.mapper.Map(comment); + } + + public Location MapToLocation(G.Location location) + { + return this.mapper.Map(location); + } + public Scenario MapToScenario(G.Scenario scenario) { return this.mapper.Map(scenario); @@ -166,9 +240,9 @@ public Scenario MapToScenario(G.Background background) return this.mapper.Map(background); } - public Feature MapToFeature(G.Feature feature) + public Feature MapToFeature(G.GherkinDocument gherkinDocument) { - return this.mapper.Map(feature); + return this.mapper.Map(gherkinDocument); } public void Dispose() diff --git a/src/Pickles/Pickles/Pickles.csproj b/src/Pickles/Pickles/Pickles.csproj index b92a5ec1a..72d526b45 100644 --- a/src/Pickles/Pickles/Pickles.csproj +++ b/src/Pickles/Pickles/Pickles.csproj @@ -56,7 +56,7 @@ True - ..\packages\Gherkin.3.2.0\lib\net45\Gherkin.dll + ..\packages\Gherkin.4.0.0\lib\net45\Gherkin.dll True @@ -71,7 +71,7 @@ ..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True @@ -88,8 +88,8 @@ - - ..\packages\System.IO.Abstractions.2.0.0.123\lib\net40\System.IO.Abstractions.dll + + ..\packages\System.IO.Abstractions.2.0.0.124\lib\net40\System.IO.Abstractions.dll True @@ -152,6 +152,7 @@ + diff --git a/src/Pickles/Pickles/Resources/Html/css/structure.css b/src/Pickles/Pickles/Resources/Html/css/structure.css index a63b0b0cf..c217734cb 100644 --- a/src/Pickles/Pickles/Resources/Html/css/structure.css +++ b/src/Pickles/Pickles/Resources/Html/css/structure.css @@ -232,6 +232,12 @@ li.scenario, div.scenario { font-weight: bold; } +.comment { + display: block; + font-weight: normal; + color: gray; +} + /************************************************************************* * Footer *************************************************************************/ diff --git a/src/Pickles/Pickles/packages.config b/src/Pickles/Pickles/packages.config index f9386b37c..cd431daef 100644 --- a/src/Pickles/Pickles/packages.config +++ b/src/Pickles/Pickles/packages.config @@ -5,11 +5,11 @@ - + - + - + \ No newline at end of file diff --git a/src/Pickles/VersionInfo.cs b/src/Pickles/VersionInfo.cs index e70e1b716..a1f229883 100644 --- a/src/Pickles/VersionInfo.cs +++ b/src/Pickles/VersionInfo.cs @@ -8,10 +8,11 @@ [assembly: AssemblyTrademarkAttribute("")] [assembly: AssemblyCultureAttribute("")] [assembly: ComVisibleAttribute(false)] -[assembly: AssemblyVersionAttribute("2.5.0")] -[assembly: AssemblyFileVersionAttribute("2.5.0")] +[assembly: AssemblyVersionAttribute("2.6.0")] +[assembly: AssemblyFileVersionAttribute("2.6.0")] namespace System { internal static class AssemblyVersionInformation { - internal const string Version = "2.5.0"; + internal const string Version = "2.6.0"; + internal const string InformationalVersion = "2.6.0"; } } diff --git a/testRunnerMsBuild.cmd b/testRunnerMsBuild.cmd index d67c93773..3a8dce95c 100644 --- a/testRunnerMsBuild.cmd +++ b/testRunnerMsBuild.cmd @@ -1,4 +1,4 @@ -"\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" testOutput.proj /p:Version=%1 /p:ShouldIncludeExperimentalFeatures=false -"\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" testOutput.proj /p:Version=%1 /p:ShouldIncludeExperimentalFeatures=true +"\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" testOutput.proj /p:Version=%1 /p:ShouldIncludeExperimentalFeatures=false +"\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" testOutput.proj /p:Version=%1 /p:ShouldIncludeExperimentalFeatures=true if errorlevel 1 exit /b 1 exit /b 0