From 8104b9e9a3abac3e3dcafecfe0c98a16b301cf40 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 8 Jul 2025 09:26:19 -0500 Subject: [PATCH 1/8] Initial commit of project structure. --- dotnet/.gitignore | 176 +++++++++++++++++++++++ dotnet/Query/Query.sln | 31 ++++ dotnet/Query/Query/Query.csproj | 7 + dotnet/Query/QueryTest/MSTestSettings.cs | 1 + dotnet/Query/QueryTest/QueryTest.csproj | 29 ++++ 5 files changed, 244 insertions(+) create mode 100644 dotnet/.gitignore create mode 100644 dotnet/Query/Query.sln create mode 100644 dotnet/Query/Query/Query.csproj create mode 100644 dotnet/Query/QueryTest/MSTestSettings.cs create mode 100644 dotnet/Query/QueryTest/QueryTest.csproj diff --git a/dotnet/.gitignore b/dotnet/.gitignore new file mode 100644 index 00000000..91fa9507 --- /dev/null +++ b/dotnet/.gitignore @@ -0,0 +1,176 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +*.ide + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Oo]bj/ +*/**/bin + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +packages/ +acceptance/ +output/ +.built +.compared +.sln_built_debug +*.userprefs +*.nupkg +Gherkin.NuGetPackages/bin/ +.build* +.built* +.vscode +.run_tests +.generated +.packed +.tested +.fixprotoc +.vs/ diff --git a/dotnet/Query/Query.sln b/dotnet/Query/Query.sln new file mode 100644 index 00000000..59ccba02 --- /dev/null +++ b/dotnet/Query/Query.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36221.1 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Query", "Query\Query.csproj", "{01EF081E-A17A-4630-9C7D-40BA4BE3F9BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QueryTest", "QueryTest\QueryTest.csproj", "{F0EA5832-C5B7-42CF-9BDB-6EE21C589C8B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01EF081E-A17A-4630-9C7D-40BA4BE3F9BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01EF081E-A17A-4630-9C7D-40BA4BE3F9BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01EF081E-A17A-4630-9C7D-40BA4BE3F9BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01EF081E-A17A-4630-9C7D-40BA4BE3F9BC}.Release|Any CPU.Build.0 = Release|Any CPU + {F0EA5832-C5B7-42CF-9BDB-6EE21C589C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0EA5832-C5B7-42CF-9BDB-6EE21C589C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0EA5832-C5B7-42CF-9BDB-6EE21C589C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0EA5832-C5B7-42CF-9BDB-6EE21C589C8B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {923928DC-6FB0-4C25-9B2B-721A9B60C602} + EndGlobalSection +EndGlobal diff --git a/dotnet/Query/Query/Query.csproj b/dotnet/Query/Query/Query.csproj new file mode 100644 index 00000000..dbdcea46 --- /dev/null +++ b/dotnet/Query/Query/Query.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/dotnet/Query/QueryTest/MSTestSettings.cs b/dotnet/Query/QueryTest/MSTestSettings.cs new file mode 100644 index 00000000..aaf278c8 --- /dev/null +++ b/dotnet/Query/QueryTest/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/dotnet/Query/QueryTest/QueryTest.csproj b/dotnet/Query/QueryTest/QueryTest.csproj new file mode 100644 index 00000000..0138d060 --- /dev/null +++ b/dotnet/Query/QueryTest/QueryTest.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + latest + enable + enable + true + Exe + true + + true + + + + + + + + + + + + + + From 8a7a7e9e14ed932af67ea1169396d5a712b2c4bc Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 8 Jul 2025 09:47:12 -0500 Subject: [PATCH 2/8] first class ported --- dotnet/Query/Query/Lineage.cs | 99 +++++++++++++++++++++++++++ dotnet/Query/Query/PortingTemplate.cs | 8 +++ dotnet/Query/Query/Query.csproj | 6 ++ 3 files changed, 113 insertions(+) create mode 100644 dotnet/Query/Query/Lineage.cs create mode 100644 dotnet/Query/Query/PortingTemplate.cs diff --git a/dotnet/Query/Query/Lineage.cs b/dotnet/Query/Query/Lineage.cs new file mode 100644 index 00000000..7d0a7eca --- /dev/null +++ b/dotnet/Query/Query/Lineage.cs @@ -0,0 +1,99 @@ +using System.ComponentModel.DataAnnotations; +using System; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query; + +/// +/// A structure containing all ancestors of a given +/// element or . +/// +/// +/// See . +/// +public sealed class Lineage +{ + private readonly GherkinDocument _document; + private readonly Feature? _feature; + private readonly Rule? _rule; + private readonly Scenario? _scenario; + private readonly Examples? _examples; + private readonly int? _examplesIndex; + private readonly TableRow? _example; + private readonly int? _exampleIndex; + + internal Lineage([Required] GherkinDocument document) + { + _document = document ?? throw new ArgumentNullException(nameof(document)); + _feature = null; + _rule = null; + _scenario = null; + _examples = null; + _examplesIndex = null; + _example = null; + _exampleIndex = null; + } + + internal Lineage(Lineage parent, Feature feature) + : this(parent._document, feature, null, null, null, null, null, null) { } + + internal Lineage(Lineage parent, Rule rule) + : this(parent._document, parent._feature, rule, null, null, null, null, null) { } + + internal Lineage(Lineage parent, Scenario scenario) + : this(parent._document, parent._feature, parent._rule, scenario, null, null, null, null) { } + + internal Lineage(Lineage parent, Examples examples, int examplesIndex) + : this(parent._document, parent._feature, parent._rule, parent._scenario, examples, examplesIndex, null, null) { } + + internal Lineage(Lineage parent, TableRow example, int exampleIndex) + : this(parent._document, parent._feature, parent._rule, parent._scenario, parent._examples, parent._examplesIndex, example, exampleIndex) { } + + private Lineage( + [Required] GherkinDocument document, + Feature? feature, + Rule? rule, + Scenario? scenario, + Examples? examples, + int? examplesIndex, + TableRow? example, + int? exampleIndex) + { + _document = document ?? throw new ArgumentNullException(nameof(document)); + _feature = feature; + _rule = rule; + _scenario = scenario; + _examples = examples; + _examplesIndex = examplesIndex; + _example = example; + _exampleIndex = exampleIndex; + } + + public GherkinDocument Document => _document; + public Feature? Feature => _feature; + public Rule? Rule => _rule; + public Scenario? Scenario => _scenario; + public Examples? Examples => _examples; + public TableRow? Example => _example; + public int? ExamplesIndex => _examplesIndex; + public int? ExampleIndex => _exampleIndex; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(this, obj)) return true; + if (obj is not Lineage other) return false; + return Equals(_document, other._document) + && Equals(_feature, other._feature) + && Equals(_rule, other._rule) + && Equals(_scenario, other._scenario) + && Equals(_examples, other._examples) + && Equals(_example, other._example) + && Equals(_examplesIndex, other._examplesIndex) + && Equals(_exampleIndex, other._exampleIndex); + } + + public override int GetHashCode() + { + return HashCode.Combine(_document, _feature, _rule, _scenario, _examples, _example, _examplesIndex, _exampleIndex); + } +} diff --git a/dotnet/Query/Query/PortingTemplate.cs b/dotnet/Query/Query/PortingTemplate.cs new file mode 100644 index 00000000..c037ba10 --- /dev/null +++ b/dotnet/Query/Query/PortingTemplate.cs @@ -0,0 +1,8 @@ +// File-scoped namespace for all ported classes +namespace Io.Cucumber.Query; + +// ...existing code... +// This file will be used as a template for porting Java classes to C# +// Each Java class will be ported as a public C# class in this namespace +// Nullable types and [Required] attributes will be used as specified +// Implementation will follow idiomatic C# and .NET Standard 2.0 compatibility diff --git a/dotnet/Query/Query/Query.csproj b/dotnet/Query/Query/Query.csproj index dbdcea46..e05b0404 100644 --- a/dotnet/Query/Query/Query.csproj +++ b/dotnet/Query/Query/Query.csproj @@ -2,6 +2,12 @@ netstandard2.0 + latest + + + + + From 281e078cd7327aceb0f9c30e48d4b14d66130601 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 8 Jul 2025 14:44:53 -0500 Subject: [PATCH 3/8] Implementation plus tests --- dotnet/Query/Query/Lineage.cs | 17 +- dotnet/Query/Query/LineageReducer.cs | 25 + dotnet/Query/Query/LineageReducerAscending.cs | 47 ++ .../Query/Query/LineageReducerDescending.cs | 47 ++ dotnet/Query/Query/Lineages.cs | 105 ++++ dotnet/Query/Query/NamingCollector.cs | 109 ++++ dotnet/Query/Query/NamingStrategy.cs | 93 +++ dotnet/Query/Query/PortingTemplate.cs | 5 +- dotnet/Query/Query/Query.cs | 565 ++++++++++++++++++ dotnet/Query/Query/Query.csproj | 4 + dotnet/Query/Query/TimestampComparer.cs | 30 + dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 199 ++++++ dotnet/Query/QueryTest/QueryTest.cs | 64 ++ dotnet/Query/QueryTest/QueryTest.csproj | 10 +- .../Resources/attachments.feature.ndjson | 77 +++ .../attachments.feature.query-results.json | 407 +++++++++++++ .../QueryTest/Resources/cdata.feature.ndjson | 12 + .../Resources/data-tables.feature.ndjson | 15 + .../QueryTest/Resources/empty.feature.ndjson | 9 + .../empty.feature.query-results.json | 91 +++ .../examples-tables-attachment.feature.ndjson | 21 + .../Resources/examples-tables.feature.ndjson | 100 ++++ ...examples-tables.feature.query-results.json | 513 ++++++++++++++++ .../Resources/hooks-attachment.feature.ndjson | 20 + .../hooks-conditional.feature.ndjson | 36 ++ .../Resources/hooks-named.feature.ndjson | 18 + .../QueryTest/Resources/hooks.feature.ndjson | 39 ++ .../hooks.feature.query-results.json | 221 +++++++ .../Resources/markdown.feature.md.ndjson | 35 ++ .../Resources/minimal.feature.ndjson | 12 + .../minimal.feature.query-results.json | 111 ++++ .../Resources/parameter-types.feature.ndjson | 13 + .../Resources/pending.feature.ndjson | 30 + .../QueryTest/Resources/retry.feature.ndjson | 59 ++ .../QueryTest/Resources/rules.feature.ndjson | 47 ++ .../rules.feature.query-results.json | 252 ++++++++ .../Resources/skipped.feature.ndjson | 33 + .../Resources/stack-traces.feature.ndjson | 12 + .../Resources/undefined.feature.ndjson | 29 + .../unknown-parameter-type.feature.ndjson | 12 + .../Query/QueryTest/TimestampComparerTest.cs | 46 ++ 41 files changed, 3576 insertions(+), 14 deletions(-) create mode 100644 dotnet/Query/Query/LineageReducer.cs create mode 100644 dotnet/Query/Query/LineageReducerAscending.cs create mode 100644 dotnet/Query/Query/LineageReducerDescending.cs create mode 100644 dotnet/Query/Query/Lineages.cs create mode 100644 dotnet/Query/Query/NamingCollector.cs create mode 100644 dotnet/Query/Query/NamingStrategy.cs create mode 100644 dotnet/Query/Query/Query.cs create mode 100644 dotnet/Query/Query/TimestampComparer.cs create mode 100644 dotnet/Query/QueryTest/QueryAcceptanceTest.cs create mode 100644 dotnet/Query/QueryTest/QueryTest.cs create mode 100644 dotnet/Query/QueryTest/Resources/attachments.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/cdata.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/empty.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/empty.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/hooks.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/minimal.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/pending.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/retry.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/rules.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/rules.feature.query-results.json create mode 100644 dotnet/Query/QueryTest/Resources/skipped.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/undefined.feature.ndjson create mode 100644 dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson create mode 100644 dotnet/Query/QueryTest/TimestampComparerTest.cs diff --git a/dotnet/Query/Query/Lineage.cs b/dotnet/Query/Query/Lineage.cs index 7d0a7eca..e40f8822 100644 --- a/dotnet/Query/Query/Lineage.cs +++ b/dotnet/Query/Query/Lineage.cs @@ -1,3 +1,4 @@ +#nullable enable using System.ComponentModel.DataAnnotations; using System; using Io.Cucumber.Messages.Types; @@ -22,17 +23,7 @@ public sealed class Lineage private readonly TableRow? _example; private readonly int? _exampleIndex; - internal Lineage([Required] GherkinDocument document) - { - _document = document ?? throw new ArgumentNullException(nameof(document)); - _feature = null; - _rule = null; - _scenario = null; - _examples = null; - _examplesIndex = null; - _example = null; - _exampleIndex = null; - } + internal Lineage([Required] GherkinDocument document) : this(document, null, null, null, null, null, null, null) { } internal Lineage(Lineage parent, Feature feature) : this(parent._document, feature, null, null, null, null, null, null) { } @@ -92,8 +83,10 @@ public override bool Equals(object? obj) && Equals(_exampleIndex, other._exampleIndex); } + // Rest of the code remains unchanged + public override int GetHashCode() { - return HashCode.Combine(_document, _feature, _rule, _scenario, _examples, _example, _examplesIndex, _exampleIndex); + return (_document, _feature, _rule, _scenario, _examples, _example, _examplesIndex, _exampleIndex).GetHashCode(); } } diff --git a/dotnet/Query/Query/LineageReducer.cs b/dotnet/Query/Query/LineageReducer.cs new file mode 100644 index 00000000..39848491 --- /dev/null +++ b/dotnet/Query/Query/LineageReducer.cs @@ -0,0 +1,25 @@ +using System; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + // port of io.cucumber.query.LineageReducer (Java) + public interface ILineageReducer + { + T Reduce(Lineage lineage); + T Reduce(Lineage lineage, Pickle pickle); + } + + // port of io.cucumber.query.LineageReducer.Collector (Java) + public interface ICollector + { + void Add(GherkinDocument document); + void Add(Feature feature); + void Add(Rule rule); + void Add(Scenario scenario); + void Add(Examples examples, int index); + void Add(TableRow example, int index); + void Add(Pickle pickle); + T Finish(); + } +} diff --git a/dotnet/Query/Query/LineageReducerAscending.cs b/dotnet/Query/Query/LineageReducerAscending.cs new file mode 100644 index 00000000..b3c9f10b --- /dev/null +++ b/dotnet/Query/Query/LineageReducerAscending.cs @@ -0,0 +1,47 @@ +using System; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + // Faithful port of io.cucumber.query.LineageReducerAscending (Java) + public class LineageReducerAscending : ILineageReducer + { + private readonly Func> _collectorSupplier; + + public LineageReducerAscending(Func> collectorSupplier) + { + _collectorSupplier = collectorSupplier ?? throw new ArgumentNullException(nameof(collectorSupplier)); + } + + public T Reduce(Lineage lineage) + { + var collector = _collectorSupplier(); + ReduceAddLineage(collector, lineage); + return collector.Finish(); + } + + public T Reduce(Lineage lineage, Pickle pickle) + { + var collector = _collectorSupplier(); + collector.Add(pickle); + ReduceAddLineage(collector, lineage); + return collector.Finish(); + } + + private static void ReduceAddLineage(ICollector collector, Lineage lineage) + { + if (lineage.Example != null) + collector.Add(lineage.Example, lineage.ExampleIndex ?? 0); + if (lineage.Examples != null) + collector.Add(lineage.Examples, lineage.ExamplesIndex ?? 0); + if (lineage.Scenario != null) + collector.Add(lineage.Scenario); + if (lineage.Rule != null) + collector.Add(lineage.Rule); + if (lineage.Feature != null) + collector.Add(lineage.Feature); + if (lineage.Document != null) + collector.Add(lineage.Document); + } + } +} diff --git a/dotnet/Query/Query/LineageReducerDescending.cs b/dotnet/Query/Query/LineageReducerDescending.cs new file mode 100644 index 00000000..a525458e --- /dev/null +++ b/dotnet/Query/Query/LineageReducerDescending.cs @@ -0,0 +1,47 @@ +using System; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + // Faithful port of io.cucumber.query.LineageReducerDescending (Java) + public class LineageReducerDescending : ILineageReducer + { + private readonly Func> _collectorSupplier; + + public LineageReducerDescending(Func> collectorSupplier) + { + _collectorSupplier = collectorSupplier ?? throw new ArgumentNullException(nameof(collectorSupplier)); + } + + public T Reduce(Lineage lineage) + { + var collector = _collectorSupplier(); + ReduceAddLineage(collector, lineage); + return collector.Finish(); + } + + public T Reduce(Lineage lineage, Pickle pickle) + { + var collector = _collectorSupplier(); + ReduceAddLineage(collector, lineage); + collector.Add(pickle); + return collector.Finish(); + } + + private static void ReduceAddLineage(ICollector collector, Lineage lineage) + { + if (lineage.Document != null) + collector.Add(lineage.Document); + if (lineage.Feature != null) + collector.Add(lineage.Feature); + if (lineage.Rule != null) + collector.Add(lineage.Rule); + if (lineage.Scenario != null) + collector.Add(lineage.Scenario); + if (lineage.Examples != null) + collector.Add(lineage.Examples, lineage.ExamplesIndex ?? 0); + if (lineage.Example != null) + collector.Add(lineage.Example, lineage.ExampleIndex ?? 0); + } + } +} diff --git a/dotnet/Query/Query/Lineages.cs b/dotnet/Query/Query/Lineages.cs new file mode 100644 index 00000000..37611579 --- /dev/null +++ b/dotnet/Query/Query/Lineages.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + // port of io.cucumber.query.Lineages (Java) + internal static class Lineages + { + /// + /// Create map of a GherkinDocument element to its Lineage in that document. + /// + /// The GherkinDocument to create the lineage of. + /// A map of the document elements to their lineage. + public static Dictionary Of(GherkinDocument document) + { + var elements = new Dictionary(); + var lineage = new Lineage(document); + var uri = document.Uri ?? throw new ArgumentException("document.uri must not be null"); + elements[uri] = lineage; + if (document.Feature != null) + OfFeature(lineage, elements)(document.Feature); + return elements; + } + + private static Action OfFeature(Lineage parent, Dictionary elements) + { + return feature => + { + var lineage = new Lineage(parent, feature); + foreach (var child in feature.Children) + OfFeatureChild(lineage, elements)(child); + }; + } + + private static Action OfFeatureChild(Lineage parent, Dictionary elements) + { + return featureChild => + { + if (featureChild.Scenario != null) + OfScenario(parent, elements)(featureChild.Scenario); + if (featureChild.Rule != null) + OfRule(parent, elements)(featureChild.Rule); + }; + } + + private static Action OfRule(Lineage parent, Dictionary elements) + { + return rule => + { + var lineage = new Lineage(parent, rule); + elements[rule.Id] = lineage; + foreach (var child in rule.Children) + OfRuleChild(lineage, elements)(child); + }; + } + + private static Action OfRuleChild(Lineage parent, Dictionary elements) + { + return ruleChild => + { + if (ruleChild.Scenario != null) + OfScenario(parent, elements)(ruleChild.Scenario); + }; + } + + private static Action OfScenario(Lineage parent, Dictionary elements) + { + return scenario => + { + var lineage = new Lineage(parent, scenario); + elements[scenario.Id] = lineage; + ForEachIndexed(scenario.Examples, OfExamples(lineage, elements)); + }; + } + + private static Action OfExamples(Lineage parent, Dictionary elements) + { + return (examples, examplesIndex) => + { + var lineage = new Lineage(parent, examples, examplesIndex); + elements[examples.Id] = lineage; + ForEachIndexed(examples.TableBody, OfExample(lineage, elements)); + }; + } + + private static Action OfExample(Lineage parent, Dictionary elements) + { + return (example, exampleIndex) => + { + var lineage = new Lineage(parent, example, exampleIndex); + elements[example.Id] = lineage; + }; + } + + private static void ForEachIndexed(IList items, Action consumer) + { + if (items == null) return; + for (int i = 0; i < items.Count; i++) + { + consumer(items[i], i); + } + } + } +} \ No newline at end of file diff --git a/dotnet/Query/Query/NamingCollector.cs b/dotnet/Query/Query/NamingCollector.cs new file mode 100644 index 00000000..6d518123 --- /dev/null +++ b/dotnet/Query/Query/NamingCollector.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + /// + /// Names GherkinDocument elements or Pickles. + /// + internal class NamingCollector : ICollector + { + // There are at most 5 levels to a feature file. + private readonly List parts = new List(5); + private readonly string delimiter = " - "; + private readonly Strategy strategy; + private readonly FeatureName featureName; + private readonly ExampleName exampleName; + + private string scenarioName; + private bool isExample; + private int examplesIndex; + + public static Func Of(Strategy strategy, FeatureName featureName, ExampleName exampleName) + { + return () => new NamingCollector(strategy, featureName, exampleName); + } + + public NamingCollector(Strategy strategy, FeatureName featureName, ExampleName exampleName) + { + this.strategy = strategy; + this.featureName = featureName; + this.exampleName = exampleName; + } + + public void Add(GherkinDocument document) { } + public void Add(Feature feature) + { + if (featureName == FeatureName.INCLUDE || strategy == Strategy.SHORT) + { + parts.Add(feature.Name); + } + } + public void Add(Rule rule) + { + parts.Add(rule.Name); + } + public void Add(Scenario scenario) + { + scenarioName = scenario.Name; + parts.Add(scenarioName); + } + public void Add(Examples examples, int index) + { + parts.Add(examples.Name); + this.examplesIndex = index; + } + public void Add(TableRow example, int index) + { + isExample = true; + parts.Add("#" + (examplesIndex + 1) + "." + (index + 1)); + } + public void Add(Pickle pickle) + { + string pickleName = pickle.Name; + + // Case 0: Pickles with an empty lineage + if (scenarioName == null) + { + parts.Add(pickleName); + return; + } + + // Case 1: Pickles from a scenario outline + if (isExample) + { + switch (exampleName) + { + case ExampleName.NUMBER: + break; + case ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED: + bool parameterized = !scenarioName.Equals(pickleName); + if (parameterized) + { + string exampleNumber = parts[parts.Count - 1]; + parts.RemoveAt(parts.Count - 1); + parts.Add(exampleNumber + ": " + pickleName); + } + break; + case ExampleName.PICKLE: + parts.RemoveAt(parts.Count - 1); // Remove example number + parts.Add(pickleName); + break; + } + } + // Case 2: Pickles from a scenario + // Nothing to do, scenario name and pickle name are the same. + } + + public string Finish() + { + if (strategy == Strategy.SHORT) + { + return parts.Count > 0 ? parts[parts.Count - 1] : string.Empty; + } + return string.Join(delimiter, parts.Where(s => !string.IsNullOrEmpty(s))); + } + } +} \ No newline at end of file diff --git a/dotnet/Query/Query/NamingStrategy.cs b/dotnet/Query/Query/NamingStrategy.cs new file mode 100644 index 00000000..73af2f03 --- /dev/null +++ b/dotnet/Query/Query/NamingStrategy.cs @@ -0,0 +1,93 @@ +using System; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + /// + /// Names Pickles and other elements in a GherkinDocument. + /// + public enum Strategy + { + LONG, + SHORT + } + + public enum ExampleName + { + NUMBER, + PICKLE, + NUMBER_AND_PICKLE_IF_PARAMETERIZED + } + + public enum FeatureName + { + INCLUDE, + EXCLUDE + } + public abstract class NamingStrategy : ILineageReducer + { + + public static Builder Create(Strategy strategy) + { + return new Builder(strategy); + } + + protected NamingStrategy() { } + + public abstract string Reduce(Lineage lineage); + public abstract string Reduce(Lineage lineage, Pickle pickle); + + public class Builder + { + private readonly Strategy _strategy; + private FeatureName _featureName = Io.Cucumber.Query.FeatureName.INCLUDE; + private ExampleName _exampleName = Io.Cucumber.Query.ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED; + + public Builder(Strategy strategy) + { + _strategy = strategy; + } + + public Builder ExampleName(ExampleName exampleName) + { + _exampleName = exampleName; + return this; + } + + public Builder FeatureName(FeatureName featureName) + { + _featureName = featureName; + return this; + } + + public NamingStrategy Build() + { + return new Adaptor( + new LineageReducerDescending( + () => new NamingCollector((Strategy)_strategy, (FeatureName)_featureName, (ExampleName)_exampleName) + ) + ); + } + } + + private class Adaptor : NamingStrategy + { + private readonly ILineageReducer _delegate; + + public Adaptor(ILineageReducer del) + { + _delegate = del; + } + + public override string Reduce(Lineage lineage) + { + return _delegate.Reduce(lineage); + } + + public override string Reduce(Lineage lineage, Pickle pickle) + { + return _delegate.Reduce(lineage, pickle); + } + } + } +} diff --git a/dotnet/Query/Query/PortingTemplate.cs b/dotnet/Query/Query/PortingTemplate.cs index c037ba10..8d9aa534 100644 --- a/dotnet/Query/Query/PortingTemplate.cs +++ b/dotnet/Query/Query/PortingTemplate.cs @@ -1,7 +1,10 @@ // File-scoped namespace for all ported classes namespace Io.Cucumber.Query; -// ...existing code... +using System; +using System.Collections.Generic; +using Io.Cucumber.Messages.Types; + // This file will be used as a template for porting Java classes to C# // Each Java class will be ported as a public C# class in this namespace // Nullable types and [Required] attributes will be used as specified diff --git a/dotnet/Query/Query/Query.cs b/dotnet/Query/Query/Query.cs new file mode 100644 index 00000000..7210cfaa --- /dev/null +++ b/dotnet/Query/Query/Query.cs @@ -0,0 +1,565 @@ +#nullable enable +using System; +using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.Linq; +using Io.Cucumber.Messages.Types; +using System.Collections.Concurrent; + +namespace Io.Cucumber.Query; + +// Ported from io.cucumber.query.Query (Java) +public class Query +{ + // Internal state for queries + private readonly List _gherkinDocuments = new(); + private readonly List _pickles = new(); + private readonly List _testCases = new(); + private readonly List _testStepFinished = new(); + private readonly List _testCaseFinished = new(); + private readonly List _testCaseStarted = new(); + + // Additional internal state for queries (to be expanded as needed) + private readonly ConcurrentDictionary _testCaseStartedById = new(); + private readonly ConcurrentDictionary _testCaseFinishedByTestCaseStartedId = new(); + private readonly ConcurrentDictionary> _testStepsFinishedByTestCaseStartedId = new(); + private readonly ConcurrentDictionary> _testStepsStartedByTestCaseStartedId = new(); + private readonly ConcurrentDictionary _pickleById = new(); + private readonly ConcurrentDictionary _testCaseById = new(); + private readonly ConcurrentDictionary _stepById = new(); + private readonly ConcurrentDictionary _testStepById = new(); + private readonly ConcurrentDictionary _pickleStepById = new(); + private readonly ConcurrentDictionary _hookById = new(); + private readonly ConcurrentDictionary> _attachmentsByTestCaseStartedId = new(); + private readonly ConcurrentDictionary _lineageById = new(); + private Meta? _meta; + private TestRunStarted? _testRunStarted; + private TestRunFinished? _testRunFinished; + + public Query() { } + + // Property getters for counts + public int MostSevereTestStepResultStatusCount => CountMostSevereTestStepResultStatus().Count; + public int TestCasesStartedCount => FindAllTestCaseStarted().Count; + + // Ported methods (incrementally implemented) + public IDictionary CountMostSevereTestStepResultStatus() + { + var statusCounts = new Dictionary(); + foreach (var testCaseStarted in FindAllTestCaseStarted()) + { + var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); + if (finishedSteps.Count == 0) + continue; + // Find the most severe status (lowest enum value) + var mostSevere = finishedSteps + .Select(f => f.TestStepResult.Status) + .Min(); + if (statusCounts.ContainsKey(mostSevere)) + statusCounts[mostSevere]++; + else + statusCounts[mostSevere] = 1; + } + return statusCounts; + } + + public IList FindAllPickles() => _pickleById.Values.OrderBy(p => p.Id).ToList(); + + public IList FindAllPickleSteps() => _pickleStepById.Values.OrderBy(ps => ps.Id).ToList(); + + public IList FindAllTestCaseStarted() => _testCaseStartedById.Values + .OrderBy(tcs => tcs.Timestamp, new TimestampComparer()) + .ThenBy(tcs => tcs.Id) + .Where(tcs => !FindTestCaseFinishedBy(tcs)?.WillBeRetried ?? true) // Exclude finished cases that will be retried + .ToList(); + + public IList FindAllTestSteps() => _testStepById.Values.OrderBy(ts => ts.Id).ToList(); + + public IDictionary> FindAllTestCaseStartedGroupedByFeature() + { + // Group TestCaseStarted by Feature (null if not found) + return FindAllTestCaseStarted() + .GroupBy(tcs => FindFeatureBy(tcs)) + .ToDictionary(g => g.Key, g => g.ToList()); + } + + public Meta? FindMeta() => _meta; + public TestRunStarted? FindTestRunStarted() => _testRunStarted; + public TestRunFinished? FindTestRunFinished() => _testRunFinished; + + public IList FindAttachmentsBy(TestStepFinished testStepFinished) => + _attachmentsByTestCaseStartedId.TryGetValue(testStepFinished.TestCaseStartedId, out var attachments) + ? attachments.Where(a => a.TestStepId == testStepFinished.TestStepId).ToList() + : new List(); + + public Feature? FindFeatureBy(TestCaseStarted testCaseStarted) + { + // Find the TestCase for this TestCaseStarted + if (_testCaseById.TryGetValue(testCaseStarted.TestCaseId, out var testCase)) + { + // Find the Pickle for this TestCase + if (_pickleById.TryGetValue(testCase.PickleId, out var pickle)) + { + // Find the GherkinDocument for this Pickle + var doc = _gherkinDocuments.FirstOrDefault(d => d.Uri == pickle.Uri); + return doc?.Feature; + } + } + return null; + } + + public Hook? FindHookBy(TestStep testStep) + { + // Java: testStep.getHookId().map(hookById::get) + if (!string.IsNullOrEmpty(testStep.HookId) && _hookById.TryGetValue(testStep.HookId, out var hook)) + { + return hook; + } + return null; + } + + public Pickle? FindPickleBy(TestCaseStarted testCaseStarted) + { + // Java: findTestCaseBy(testCaseStarted).map(TestCase::getPickleId).map(pickleById::get) + var testCase = FindTestCaseBy(testCaseStarted); + if (testCase != null && _pickleById.TryGetValue(testCase.PickleId, out var pickle)) + { + return pickle; + } + return null; + } + + public Pickle? FindPickleBy(TestStepStarted testStepStarted) + { + // Java: findTestCaseBy(testStepStarted).map(TestCase::getPickleId).map(pickleById::get) + var testCaseStarted = FindTestCaseStartedBy(testStepStarted); + if (testCaseStarted != null) + { + return FindPickleBy(testCaseStarted); + } + return null; + } + + public TestCase? FindTestCaseBy(TestCaseStarted testCaseStarted) + { + // Java: testCaseById.get(testCaseStarted.getTestCaseId()) + if (_testCaseById.TryGetValue(testCaseStarted.TestCaseId, out var testCase)) + { + return testCase; + } + return null; + } + + public TestCaseStarted? FindTestCaseStartedBy(TestStepStarted testStepStarted) + { + // Java: testCaseStartedById.get(testStepStarted.getTestCaseStartedId()) + return _testCaseStartedById.TryGetValue(testStepStarted.TestCaseStartedId, out var tcs) ? tcs : null; + } + + public TestCase? FindTestCaseBy(TestStepStarted testStepStarted) + { + // Java: findTestCaseStartedBy(testStepStarted).flatMap(this::findTestCaseBy) + var testCaseStarted = FindTestCaseStartedBy(testStepStarted); + return testCaseStarted != null ? FindTestCaseBy(testCaseStarted) : null; + } + + public TestStep? FindTestStepBy(TestStepStarted testStepStarted) + { + // Java: testStepById.get(testStepStarted.getTestStepId()) + return _testStepById.TryGetValue(testStepStarted.TestStepId, out var testStep) ? testStep : null; + } + + public TestStep? FindTestStepBy(TestStepFinished testStepFinished) + { + // Java: testStepById.get(testStepFinished.getTestStepId()) + return _testStepById.TryGetValue(testStepFinished.TestStepId, out var testStep) ? testStep : null; + } + + public PickleStep? FindPickleStepBy(TestStep testStep) + { + // Java: testStep.getPickleStepId().map(pickleStepById::get) + if (!string.IsNullOrEmpty(testStep.PickleStepId)) + { + if (_pickleStepById.TryGetValue(testStep.PickleStepId, out var pickleStep)) + { + return pickleStep; + } + } + return null; + } + + public Step? FindStepBy(PickleStep pickleStep) + { + // Java: String stepId = pickleStep.getAstNodeIds().get(0); stepById.get(stepId) + if (pickleStep.AstNodeIds != null && pickleStep.AstNodeIds.Count > 0) + { + var stepId = pickleStep.AstNodeIds[0]; + if (!string.IsNullOrEmpty(stepId) && _stepById.TryGetValue(stepId, out var step)) + { + return step; + } + } + return null; + } + + public System.TimeSpan? FindTestCaseDurationBy(TestCaseStarted testCaseStarted) + { + var started = testCaseStarted.Timestamp; + var finished = FindTestCaseFinishedBy(testCaseStarted)?.Timestamp; + if (finished != null) + { + var startTime = TimestampToDateTimeOffset(started); + var finishTime = TimestampToDateTimeOffset(finished); + return finishTime - startTime; + } + return null; + } + + public TestCaseFinished? FindTestCaseFinishedBy(TestCaseStarted testCaseStarted) + { + // Java: testCaseFinishedByTestCaseStartedId.get(testCaseStarted.getId()) + return _testCaseFinishedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var finished) ? finished : null; + } + + public System.TimeSpan? FindTestRunDuration() + { + // Java: if (testRunStarted == null || testRunFinished == null) return Optional.empty(); + if (_testRunStarted == null || _testRunFinished == null) + return null; + var start = TimestampToDateTimeOffset(_testRunStarted.Timestamp); + var finish = TimestampToDateTimeOffset(_testRunFinished.Timestamp); + return finish - start; + } + + public IList FindTestStepsStartedBy(TestCaseStarted testCaseStarted) + { + // Java: testStepsStartedByTestCaseStartedId.getOrDefault(testCaseStarted.getId(), emptyList()) + if (_testStepsStartedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var steps)) + { + // Return a copy for concurrency safety + return new List(steps); + } + return new List(); + } + + public IList FindTestStepsFinishedBy(TestCaseStarted testCaseStarted) + { + // Java: testStepsFinishedByTestCaseStartedId.getOrDefault(testCaseStarted.getId(), emptyList()) + if (_testStepsFinishedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var steps)) + { + // Return a copy for concurrency safety + return new List(steps); + } + return new List(); + } + + public IList<(TestStepFinished, TestStep)> FindTestStepFinishedAndTestStepBy(TestCaseStarted testCaseStarted) + { + // Java: findTestStepsFinishedBy(testCaseStarted).stream() + // .map(testStepFinished -> findTestStepBy(testStepFinished).map(testStep -> new SimpleEntry<>(testStepFinished, testStep))) + // .filter(Optional::isPresent) + // .map(Optional::get) + // .collect(toList()); + var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); + var result = new List<(TestStepFinished, TestStep)>(); + foreach (var testStepFinished in finishedSteps) + { + var testStep = FindTestStepBy(testStepFinished); + if (testStep != null) + { + result.Add((testStepFinished, testStep)); + } + } + return result; + } + + public TestStepResult? FindMostSevereTestStepResultBy(TestCaseStarted testCaseStarted) + { + var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); + if (finishedSteps.Count == 0) + return null; + // Find the TestStepFinished with the most severe status (lowest enum value) + var mostSevere = finishedSteps + .OrderBy(f => f.TestStepResult.Status) + .FirstOrDefault(); + return mostSevere?.TestStepResult; + } + + private static DateTimeOffset TimestampToDateTimeOffset(Timestamp timestamp) + { + // Java: Convertor.toInstant(timestamp) + // C#: Timestamp has Seconds and Nanos + var dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp.Seconds); + return dateTime.AddTicks(timestamp.Nanos / 100); + } + + // Update methods for each message type (ported from Java) + internal void UpdateAttachment(Attachment attachment) + { + if (attachment.TestCaseStartedId != null) + { + _attachmentsByTestCaseStartedId.AddOrUpdate( + attachment.TestCaseStartedId, + _ => new List { attachment }, + (_, list) => { list.Add(attachment); return list; }); + } + } + + internal void UpdateHook(Hook hook) + { + _hookById[hook.Id] = hook; + } + + internal void UpdateTestCaseStarted(TestCaseStarted testCaseStarted) + { + _testCaseStartedById[testCaseStarted.Id] = testCaseStarted; + _testCaseStarted.Add(testCaseStarted); + } + + internal void UpdateTestCase(TestCase testCase) + { + _testCaseById[testCase.Id] = testCase; + _testCases.Add(testCase); + foreach (var testStep in testCase.TestSteps) + { + _testStepById[testStep.Id] = testStep; + } + } + + internal void UpdatePickle(Pickle pickle) + { + _pickleById[pickle.Id] = pickle; + _pickles.Add(pickle); + foreach (var step in pickle.Steps) + { + _pickleStepById[step.Id] = step; + } + } + + internal void UpdateGherkinDocument(GherkinDocument document) + { + _gherkinDocuments.Add(document); + if (document.Feature != null) + { + UpdateFeature(document.Feature); + } + // Lineage population would go here if implemented + } + + internal void UpdateFeature(Feature feature) + { + foreach (var child in feature.Children) + { + if (child.Background != null) + { + UpdateSteps(child.Background.Steps); + } + if (child.Scenario != null) + { + UpdateScenario(child.Scenario); + } + if (child.Rule != null) + { + foreach (var ruleChild in child.Rule.Children) + { + if (ruleChild.Background != null) + { + UpdateSteps(ruleChild.Background.Steps); + } + if (ruleChild.Scenario != null) + { + UpdateScenario(ruleChild.Scenario); + } + } + } + } + } + + internal void UpdateTestStepStarted(TestStepStarted testStepStarted) + { + _testStepsStartedByTestCaseStartedId.AddOrUpdate( + testStepStarted.TestCaseStartedId, + _ => new List { testStepStarted }, + (_, list) => { list.Add(testStepStarted); return list; }); + } + + internal void UpdateTestStepFinished(TestStepFinished testStepFinished) + { + _testStepsFinishedByTestCaseStartedId.AddOrUpdate( + testStepFinished.TestCaseStartedId, + _ => new List { testStepFinished }, + (_, list) => { list.Add(testStepFinished); return list; }); + _testStepFinished.Add(testStepFinished); + } + + internal void UpdateTestCaseFinished(TestCaseFinished testCaseFinished) + { + _testCaseFinishedByTestCaseStartedId[testCaseFinished.TestCaseStartedId] = testCaseFinished; + _testCaseFinished.Add(testCaseFinished); + } + + internal void UpdateTestRunFinished(TestRunFinished testRunFinished) + { + _testRunFinished = testRunFinished; + } + + internal void UpdateTestRunStarted(TestRunStarted testRunStarted) + { + _testRunStarted = testRunStarted; + } + + internal void UpdateScenario(Scenario scenario) + { + UpdateSteps(scenario.Steps); + } + + internal void UpdateSteps(IList steps) + { + foreach (var step in steps) + { + _stepById[step.Id] = step; + } + } + + internal void UpdateMeta(Meta meta) + { + _meta = meta; + } + + public void Update(Envelope envelope) + { + if (envelope.Meta != null) UpdateMeta(envelope.Meta); + if (envelope.TestRunStarted != null) UpdateTestRunStarted(envelope.TestRunStarted); + if (envelope.TestRunFinished != null) UpdateTestRunFinished(envelope.TestRunFinished); + if (envelope.TestCaseStarted != null) UpdateTestCaseStarted(envelope.TestCaseStarted); + if (envelope.TestCaseFinished != null) UpdateTestCaseFinished(envelope.TestCaseFinished); + if (envelope.TestStepStarted != null) UpdateTestStepStarted(envelope.TestStepStarted); + if (envelope.TestStepFinished != null) UpdateTestStepFinished(envelope.TestStepFinished); + if (envelope.GherkinDocument != null) UpdateGherkinDocument(envelope.GherkinDocument); + if (envelope.Pickle != null) UpdatePickle(envelope.Pickle); + if (envelope.TestCase != null) UpdateTestCase(envelope.TestCase); + if (envelope.Hook != null) UpdateHook(envelope.Hook); + if (envelope.Attachment != null) UpdateAttachment(envelope.Attachment); + } + + // FindLineageBy methods + public Lineage? FindLineageBy(GherkinDocument element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(Feature element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(Rule element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(Scenario element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(Examples element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(TableRow element) + { + _lineageById.TryGetValue(element, out var lineage); + return lineage; + } + + public Lineage? FindLineageBy(Pickle pickle) + { + _lineageById.TryGetValue(pickle, out var lineage); + return lineage; + } + + public string FindNameOf(GherkinDocument element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(Feature element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(Rule element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(Scenario element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(Examples element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(TableRow element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + return GetNameFromStrategy(element, lineage, namingStrategy); + } + + public string FindNameOf(Pickle element, NamingStrategy namingStrategy) + { + if (element == null) return string.Empty; + var lineage = FindLineageBy(element); + var result = namingStrategy.Reduce(lineage, element); + if (result == null) + { + throw new ArgumentException("Element was not part of this query object"); + } + return result; + + } + + public Location? FindLocationOf(Pickle pickle) + { + var lineage = FindLineageBy(pickle); + if (lineage == null) + return null; + if (lineage.Example != null) + return lineage.Example.Location; + if (lineage.Scenario != null) + return lineage.Scenario.Location; + return null; + } + + // Placeholder for actual naming strategy logic + private string GetNameFromStrategy(object element, Lineage? lineage, NamingStrategy namingStrategy) + { + var result = namingStrategy.Reduce(lineage); + if (result == null) + { + throw new ArgumentException("Element was not part of this query object"); + } + return result; + } +} diff --git a/dotnet/Query/Query/Query.csproj b/dotnet/Query/Query/Query.csproj index e05b0404..70348462 100644 --- a/dotnet/Query/Query/Query.csproj +++ b/dotnet/Query/Query/Query.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/dotnet/Query/Query/TimestampComparer.cs b/dotnet/Query/Query/TimestampComparer.cs new file mode 100644 index 00000000..1cd133e4 --- /dev/null +++ b/dotnet/Query/Query/TimestampComparer.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using Io.Cucumber.Messages.Types; + +namespace Io.Cucumber.Query +{ + // Port of io.cucumber.query.TimestampComparator (Java) + public class TimestampComparer : IComparer + { + public int Compare(Timestamp a, Timestamp b) + { + long sa = a.Seconds; + long sb = b.Seconds; + + if (sa < sb) + return -1; + else if (sb < sa) + return 1; + + long na = a.Nanos; + long nb = b.Nanos; + + if (na < nb) + return -1; + else if (nb < na) + return 1; + + return 0; + } + } +} diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs new file mode 100644 index 00000000..7a09ac07 --- /dev/null +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Io.Cucumber.Messages.Types; +using Io.Cucumber.Query; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace QueryTest +{ + [TestClass] + public class QueryAcceptanceTest + { + private static readonly string[] TestFiles = new[] + { + "attachments.feature.ndjson", + "empty.feature.ndjson", + "hooks.feature.ndjson", + "minimal.feature.ndjson", + "rules.feature.ndjson", + "examples-tables.feature.ndjson" + }; + + public static IEnumerable Acceptance() + { + foreach (var file in TestFiles) + { + yield return new object[] { new TestCase(file) }; + } + } + + [TestMethod] + [DynamicData(nameof(Acceptance), DynamicDataSourceType.Method)] + public void Test(TestCase testCase) + { + var actual = WriteQueryResults(testCase); + var expected = ReadResourceAsString(testCase.ExpectedResourceName); + + // Compare as JSON for robust diff + var actualJson = JsonNode.Parse(actual); + var expectedJson = JsonNode.Parse(expected); + + Assert.AreEqual(expectedJson.ToJsonString(), actualJson.ToJsonString()); + } + + private static string WriteQueryResults(TestCase testCase) + { + using var inStream = ReadResourceAsStream(testCase.SourceResourceName); + using var reader = new StreamReader(inStream, Encoding.UTF8); + var query = new Query(); + + // Read NDJSON lines and update query + string? line; + while ((line = reader.ReadLine()) != null) + { + if (string.IsNullOrWhiteSpace(line)) continue; + var envelope = JsonSerializer.Deserialize(line); + query.Update(envelope); + } + + var queryResults = CreateQueryResults(query); + var options = new JsonSerializerOptions + { + WriteIndented = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + return JsonSerializer.Serialize(queryResults, options); + } + + private static Dictionary CreateQueryResults(Query query) + { + var results = new Dictionary + { + ["countMostSevereTestStepResultStatus"] = query.CountMostSevereTestStepResultStatus(), + ["countTestCasesStarted"] = query.TestCasesStartedCount, + ["findAllPickles"] = query.FindAllPickles().Count, + ["findAllPickleSteps"] = query.FindAllPickleSteps().Count, + ["findAllTestCaseStarted"] = query.FindAllTestCaseStarted().Count, + ["findAllTestSteps"] = query.FindAllTestSteps().Count, + ["findAllTestCaseStartedGroupedByFeature"] = query.FindAllTestCaseStartedGroupedByFeature() + .Select(entry => new object[] + { + entry.Key?.Name, + entry.Value.Select(tcs => tcs.Id).ToList() + }).ToList(), + ["findAttachmentsBy"] = query.FindAllTestCaseStarted() + .SelectMany(tcs => query.FindTestStepFinishedAndTestStepBy(tcs)) + .Select(pair => pair.Item1) + .SelectMany(tsf => query.FindAttachmentsBy(tsf)) + .Select(att => new object?[] + { + att.TestStepId, + att.TestCaseStartedId, + att.MediaType, + att.ContentEncoding + }).ToList(), + ["findFeatureBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindFeatureBy(tcs)?.Name) + .ToList(), + ["findHookBy"] = query.FindAllTestSteps() + .Select(ts => query.FindHookBy(ts)?.Id) + .Where(id => id != null) + .ToList(), + ["findLocationOf"] = query.FindAllPickles() + .Select(pickle => query.FindLocationOf(pickle)) + .Where(loc => loc != null) + .ToList(), + ["findMeta"] = query.FindMeta()?.Implementation?.Name, + ["findMostSevereTestStepResultBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindMostSevereTestStepResultBy(tcs)?.Status) + .ToList(), + ["findNameOf"] = new Dictionary + { + ["long"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).Build())).ToList(), + ["excludeFeatureName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).FeatureName(FeatureName.EXCLUDE).Build())).ToList(), + ["longPickleName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).ExampleName(ExampleName.PICKLE).Build())).ToList(), + ["short"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.SHORT).Build())).ToList(), + ["shortPickleName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.SHORT).ExampleName(ExampleName.PICKLE).Build())).ToList(), + }, + ["findPickleBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindPickleBy(tcs)?.Name) + .ToList(), + ["findPickleStepBy"] = query.FindAllTestSteps() + .Select(ts => query.FindPickleStepBy(ts)?.Text) + .Where(text => text != null) + .ToList(), + ["findStepBy"] = query.FindAllPickleSteps() + .Select(ps => query.FindStepBy(ps)?.Text) + .ToList(), + ["findTestCaseBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindTestCaseBy(tcs)?.Id) + .ToList(), + ["findTestCaseDurationBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindTestCaseDurationBy(tcs)?.ToString()) + .ToList(), + ["findTestCaseFinishedBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindTestCaseFinishedBy(tcs)?.TestCaseStartedId) + .ToList(), + ["findTestRunDuration"] = query.FindTestRunDuration()?.ToString(), + ["findTestRunFinished"] = query.FindTestRunFinished(), + ["findTestRunStarted"] = query.FindTestRunStarted(), + ["findTestStepByTestStepStarted"] = query.FindAllTestCaseStarted() + .SelectMany(tcs => query.FindTestStepsStartedBy(tcs)) + .Select(tss => query.FindTestStepBy(tss)?.Id) + .ToList(), + ["findTestStepByTestStepFinished"] = query.FindAllTestCaseStarted() + .SelectMany(tcs => query.FindTestStepsFinishedBy(tcs)) + .Select(tsf => query.FindTestStepBy(tsf)?.Id) + .ToList(), + ["findTestStepsFinishedBy"] = query.FindAllTestCaseStarted() + .Select(tcs => query.FindTestStepsFinishedBy(tcs).Select(tsf => tsf.TestStepId).ToList()) + .ToList(), + ["findTestStepFinishedAndTestStepBy"] = query.FindAllTestCaseStarted() + .SelectMany(tcs => query.FindTestStepFinishedAndTestStepBy(tcs)) + .Select(pair => new object?[] { pair.Item1.TestStepId, pair.Item2.Id }) + .ToList(), + }; + return results; + } + + private static Stream ReadResourceAsStream(string resourceName) + { + var assembly = Assembly.GetExecutingAssembly(); + var fullName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith(resourceName)); + if (fullName == null) + throw new FileNotFoundException($"Resource {resourceName} not found."); + return assembly.GetManifestResourceStream(fullName)!; + } + + private static string ReadResourceAsString(string resourceName) + { + using var stream = ReadResourceAsStream(resourceName); + using var reader = new StreamReader(stream, Encoding.UTF8); + return reader.ReadToEnd(); + } + + public class TestCase + { + public string SourceResourceName { get; } + public string ExpectedResourceName { get; } + public string Name { get; } + + public TestCase(string ndjsonFile) + { + Name = ndjsonFile.Substring(0, ndjsonFile.LastIndexOf(".ndjson", StringComparison.Ordinal)); + SourceResourceName = $"QueryTest.Resources.{ndjsonFile}"; + ExpectedResourceName = $"QueryTest.Resources.{Name}.query-results.json"; + } + + public override string ToString() => Name; + } + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryTest.cs b/dotnet/Query/QueryTest/QueryTest.cs new file mode 100644 index 00000000..f5016c1a --- /dev/null +++ b/dotnet/Query/QueryTest/QueryTest.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Io.Cucumber.Query; +using Io.Cucumber.Messages.Types; +using System.Collections.Generic; + +namespace QueryTest +{ + [TestClass] + public class QueryTest + { + private readonly Query query = new Query(); + + [TestMethod] + public void RetainsTimestampOrderForTestCaseStarted() + { + var a = new TestCaseStarted(0L, RandomId(), RandomId(), "main", new Timestamp(1L, 0L)); + var b = new TestCaseStarted(0L, RandomId(), RandomId(), "main", new Timestamp(2L, 0L)); + var c = new TestCaseStarted(0L, RandomId(), RandomId(), "main", new Timestamp(3L, 0L)); + + foreach (var tcs in new[] { a, b, c }) + query.UpdateTestCaseStarted(tcs); + + var result = query.FindAllTestCaseStarted(); + CollectionAssert.AreEqual(new[] { a, b, c }, result.ToArray()); + } + + [TestMethod] + public void IdIsTieOrderTieBreaker() + { + var a = new TestCaseStarted(0L, "2", RandomId(), "main", new Timestamp(1L, 0L)); + var b = new TestCaseStarted(0L, "1", RandomId(), "main", new Timestamp(1L, 0L)); + var c = new TestCaseStarted(0L, "0", RandomId(), "main", new Timestamp(1L, 0L)); + + foreach (var tcs in new[] { a, b, c }) + query.UpdateTestCaseStarted(tcs); + + var result = query.FindAllTestCaseStarted(); + CollectionAssert.AreEqual(new[] { c, b, a }, result.ToArray()); + } + + [TestMethod] + public void OmitsTestCaseStartedIfFinishedAndWillBeRetried() + { + var a = new TestCaseStarted(0L, RandomId(), RandomId(), "main", new Timestamp(0L, 0L)); + var b = new TestCaseFinished(a.Id, new Timestamp(0L, 0L), true); + var c = new TestCaseStarted(0L, RandomId(), RandomId(), "main", new Timestamp(0L, 0L)); + var d = new TestCaseFinished(c.Id, new Timestamp(0L, 0L), false); + + query.UpdateTestCaseStarted(a); + query.UpdateTestCaseStarted(c); + query.UpdateTestCaseFinished(b); + query.UpdateTestCaseFinished(d); + + var result = query.FindAllTestCaseStarted(); + Assert.AreEqual(1, result.Count); + Assert.AreEqual(c, result[0]); + Assert.AreEqual(1, query.TestCasesStartedCount); + } + + private static string RandomId() => Guid.NewGuid().ToString(); + } +} diff --git a/dotnet/Query/QueryTest/QueryTest.csproj b/dotnet/Query/QueryTest/QueryTest.csproj index 0138d060..a3940118 100644 --- a/dotnet/Query/QueryTest/QueryTest.csproj +++ b/dotnet/Query/QueryTest/QueryTest.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -15,7 +15,15 @@ true + + + + + + + + diff --git a/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson b/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson new file mode 100644 index 00000000..a2b0583f --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson @@ -0,0 +1,77 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type\n\n Scenario: Strings can be attached with a media type\n Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.\n\n When the string \"hello\" is attached as \"application/octet-stream\"\n\n Scenario: Log text\n When the string \"hello\" is logged\n\n Scenario: Log ANSI coloured text\n When text with ANSI escapes is logged\n\n Scenario: Log JSON\n When the following string is attached as \"application/json\":\n ```\n {\"message\": \"The big question\", \"foo\": \"bar\"}\n ```\n\n Scenario: Byte arrays are base64-encoded regardless of media type\n When an array with 10 bytes is attached as \"text/plain\"\n\n Scenario: Attaching JPEG images\n When a JPEG image is attached\n\n Scenario: Attaching PNG images\n When a PNG image is attached\n\n Scenario: Attaching PDFs with a different filename\n When a PDF document is attached and renamed\n\n Scenario: Attaching URIs\n When a link to \"https://cucumber.io\" is attached\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/attachments/attachments.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":" Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":12},"name":"Strings can be attached with a media type","steps":[{"id":"9","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"the string \"hello\" is attached as \"application/octet-stream\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":18},"name":"Log text","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":19},"text":"the string \"hello\" is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"14","keyword":"Scenario","location":{"column":3,"line":21},"name":"Log ANSI coloured text","steps":[{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":5,"line":22},"text":"text with ANSI escapes is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"16","keyword":"Scenario","location":{"column":3,"line":24},"name":"Log JSON","steps":[{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}","delimiter":"```","location":{"column":8,"line":26}},"id":"15","keyword":"When ","keywordType":"Action","location":{"column":6,"line":25},"text":"the following string is attached as \"application/json\":"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"18","keyword":"Scenario","location":{"column":3,"line":30},"name":"Byte arrays are base64-encoded regardless of media type","steps":[{"id":"17","keyword":"When ","keywordType":"Action","location":{"column":5,"line":31},"text":"an array with 10 bytes is attached as \"text/plain\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"20","keyword":"Scenario","location":{"column":3,"line":33},"name":"Attaching JPEG images","steps":[{"id":"19","keyword":"When ","keywordType":"Action","location":{"column":5,"line":34},"text":"a JPEG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"22","keyword":"Scenario","location":{"column":3,"line":36},"name":"Attaching PNG images","steps":[{"id":"21","keyword":"When ","keywordType":"Action","location":{"column":5,"line":37},"text":"a PNG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"24","keyword":"Scenario","location":{"column":3,"line":39},"name":"Attaching PDFs with a different filename","steps":[{"id":"23","keyword":"When ","keywordType":"Action","location":{"column":5,"line":40},"text":"a PDF document is attached and renamed"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"26","keyword":"Scenario","location":{"column":3,"line":42},"name":"Attaching URIs","steps":[{"id":"25","keyword":"When ","keywordType":"Action","location":{"column":5,"line":43},"text":"a link to \"https://cucumber.io\" is attached"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Attachments","tags":[]},"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"28","language":"en","name":"Strings can be attached with a media type","steps":[{"astNodeIds":["9"],"id":"27","text":"the string \"hello\" is attached as \"application/octet-stream\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["12"],"id":"30","language":"en","name":"Log text","steps":[{"astNodeIds":["11"],"id":"29","text":"the string \"hello\" is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["14"],"id":"32","language":"en","name":"Log ANSI coloured text","steps":[{"astNodeIds":["13"],"id":"31","text":"text with ANSI escapes is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["16"],"id":"34","language":"en","name":"Log JSON","steps":[{"argument":{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}"}},"astNodeIds":["15"],"id":"33","text":"the following string is attached as \"application/json\":","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["18"],"id":"36","language":"en","name":"Byte arrays are base64-encoded regardless of media type","steps":[{"astNodeIds":["17"],"id":"35","text":"an array with 10 bytes is attached as \"text/plain\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["20"],"id":"38","language":"en","name":"Attaching JPEG images","steps":[{"astNodeIds":["19"],"id":"37","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["22"],"id":"40","language":"en","name":"Attaching PNG images","steps":[{"astNodeIds":["21"],"id":"39","text":"a PNG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["24"],"id":"42","language":"en","name":"Attaching PDFs with a different filename","steps":[{"astNodeIds":["23"],"id":"41","text":"a PDF document is attached and renamed","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["26"],"id":"44","language":"en","name":"Attaching URIs","steps":[{"astNodeIds":["25"],"id":"43","text":"a link to \"https://cucumber.io\" is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"the string {string} is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"the string {string} is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"text with ANSI escapes is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"the following string is attached as {string}:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":18},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"4","pattern":{"source":"an array with {int} bytes is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"5","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":31},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"6","pattern":{"source":"a PNG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":35},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"7","pattern":{"source":"a PDF document is attached and renamed","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":39},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"8","pattern":{"source":"a link to {string} is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":43},"uri":"samples/attachments/attachments.feature.ts"}}} +{"testRunStarted":{"id":"45","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"47","pickleId":"28","testRunStartedId":"45","testSteps":[{"id":"46","pickleStepId":"27","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"},{"group":{"children":[{"children":[{"children":[]}],"start":35,"value":"application/octet-stream"},{"children":[{"children":[]}]}],"start":34,"value":"\"application/octet-stream\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"49","pickleId":"30","testRunStartedId":"45","testSteps":[{"id":"48","pickleStepId":"29","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"51","pickleId":"32","testRunStartedId":"45","testSteps":[{"id":"50","pickleStepId":"31","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"53","pickleId":"34","testRunStartedId":"45","testSteps":[{"id":"52","pickleStepId":"33","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":37,"value":"application/json"},{"children":[{"children":[]}]}],"start":36,"value":"\"application/json\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"55","pickleId":"36","testRunStartedId":"45","testSteps":[{"id":"54","pickleStepId":"35","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[{"children":[{"children":[]}],"start":39,"value":"text/plain"},{"children":[{"children":[]}]}],"start":38,"value":"\"text/plain\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"57","pickleId":"38","testRunStartedId":"45","testSteps":[{"id":"56","pickleStepId":"37","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"59","pickleId":"40","testRunStartedId":"45","testSteps":[{"id":"58","pickleStepId":"39","stepDefinitionIds":["6"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"61","pickleId":"42","testRunStartedId":"45","testSteps":[{"id":"60","pickleStepId":"41","stepDefinitionIds":["7"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"63","pickleId":"44","testRunStartedId":"45","testSteps":[{"id":"62","pickleStepId":"43","stepDefinitionIds":["8"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":11,"value":"https://cucumber.io"},{"children":[{"children":[]}]}],"start":10,"value":"\"https://cucumber.io\""},"parameterTypeName":"string"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"64","testCaseId":"47","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"64","testStepId":"46","timestamp":{"nanos":2000000,"seconds":0}}} +{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"application/octet-stream","testCaseStartedId":"64","testStepId":"46"}} +{"testStepFinished":{"testCaseStartedId":"64","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"64","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"65","testCaseId":"49","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"65","testStepId":"48","timestamp":{"nanos":6000000,"seconds":0}}} +{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"65","testStepId":"48"}} +{"testStepFinished":{"testCaseStartedId":"65","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"65","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"66","testCaseId":"51","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"66","testStepId":"50","timestamp":{"nanos":10000000,"seconds":0}}} +{"attachment":{"body":"This displays a \u001b[31mr\u001b[0m\u001b[91ma\u001b[0m\u001b[33mi\u001b[0m\u001b[32mn\u001b[0m\u001b[34mb\u001b[0m\u001b[95mo\u001b[0m\u001b[35mw\u001b[0m","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"66","testStepId":"50"}} +{"testStepFinished":{"testCaseStartedId":"66","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"66","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"67","testCaseId":"53","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"67","testStepId":"52","timestamp":{"nanos":14000000,"seconds":0}}} +{"attachment":{"body":"{\"message\": \"The big question\", \"foo\": \"bar\"}","contentEncoding":"IDENTITY","mediaType":"application/json","testCaseStartedId":"67","testStepId":"52"}} +{"testStepFinished":{"testCaseStartedId":"67","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"67","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"68","testCaseId":"55","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"68","testStepId":"54","timestamp":{"nanos":18000000,"seconds":0}}} +{"attachment":{"body":"AAECAwQFBgcICQ==","contentEncoding":"BASE64","mediaType":"text/plain","testCaseStartedId":"68","testStepId":"54"}} +{"testStepFinished":{"testCaseStartedId":"68","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"68","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"69","testCaseId":"57","timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"69","testStepId":"56","timestamp":{"nanos":22000000,"seconds":0}}} +{"attachment":{"body":"/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAC4AKQMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAIBAUGBwABAwL/2gAIAQEAAAAAOESYe+lPPw0bK2mvU5gRhNkM/tNMGeuJM5msiEjujvC+s0ApSWvn/8QAFgEBAQEAAAAAAAAAAAAAAAAABQME/9oACAECEAAAADs6pclK4E//xAAWAQEBAQAAAAAAAAAAAAAAAAAHBgT/2gAIAQMQAAAAMJZbKcF1XHit/8QANhAAAQQBAgQDBAcJAAAAAAAAAgEDBAUGABEHEiExEyJREEFCUhRTYXFzgZIVFiMyMzRVY3L/2gAIAQEAAT8AzLMqPBKOReXb6gy3sDbYdXXnS/labH3mWrrMOIWdGb063fxyoPq1XVp8klQ/3v8Aff7E0eCY86fjPtynn99/GclOq5v6782quZnOGmEnEcrmPNN96y1cWTFcH5BUurf5a4bcTKzP6x9QjlBuIKo1YVzq7mwfuJF+IC9y+zPLc8z4kWiuHz1GLuLAht/AU3u+6qfMK+XUuV4TbrTBtFNVoyYZM0RTJE6dO+2+oGcWZY1fzp0URsq5wGuXkUU3dLlHmH1FdYvMs59HCmW7SBKdQiVEHl3Hfyqqe7dNFbOYRlNDnkQlBth9uHaoPZ2C+SCSl9oL1HX0qN9c3+pNY6pkeSG9/XO/sie9fEV5d9Z5FxdbKNKsbeREsUbHZGAVxeQV6Lt8K6gtMPQYzhD43istETjzaC45sm6EaeulzOgC1Kmdkm1KF3wvO2Qjz+m+syECxe7Q+30ZV/NF3TX7dyv5nv06zGpPDOJd/WvAoV+QvHb1znwk8f8AcN/9c3XUuhp5s1qyl17L0poUQDNN+3VN07LqDTZdNg5fLsFdanyxAI4c/wBUSnsGy9B9w6x+kWwrq2blFW2VtHVUF11P4qiC+RT27r9+r6E9kUyiwmDusq8nNMny924zZc7rv3Cia/dSg/xTH6dcQMDpc/oSqbLmZeaNHoUxro9GfHs4C6uoGZYC4cXM6Z+TCb6BdV7avRjH1dEerRagWEO0iNToDyOx3N+Q0RU32XZehbLq4u4VMyByFI33VQI8ZpOZ5416IICnVdcHuHNjUOSs3y5lByGwaRpiL3Svid0b/EL4vavbXDDBM5ymjjRKi3qK2vZ5lOSYOvykRw1Lyhsgawbg9jGGSUtzJ63v1TzWU/zuB+CPZtPb/8QAJREAAgEDBAEEAwAAAAAAAAAAAQIDAAQRBRITIVEUMTJhI0Fx/9oACAECAQE/ALy8eNxb2/z63N4zTy6hbbpJJ9wV9uCdwPWaglFxEkqDGeiPBFSv6bUZJXLhXGQVx3kfdPBbpyvLNyDOAEbsEjOfsVpJ4rUlx83JH8FSwxTqElTI/R9iKGkBJm5X/GGO1R7kV0AABgAYA8Cv/8QAJREAAgIBBAEDBQAAAAAAAAAAAQIDBAUABhESMSFRcRMVIjJB/9oACAEDAQE/AN1bpuJcbFYt+hXgSSDzydG9uLFF7T3yekwjKl+wY8dvHtrAZlMzjo7RAWQHrIvsw1k+2I3LdksmZVcsymPjlg/z/NTU6MIsy2bf1x26hYnHKsy9ufXyB41sWnN9rmlPKrJNyvwBxrL4LH5mMLbj/Nf1dfRhqjsKaa27WZgtRZD1APLsuq1aGpBHXgQLGihVA1//2Q==","contentEncoding":"BASE64","mediaType":"image/jpeg","testCaseStartedId":"69","testStepId":"56"}} +{"testStepFinished":{"testCaseStartedId":"69","testStepId":"56","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"69","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"59","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"58","timestamp":{"nanos":26000000,"seconds":0}}} +{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"70","testStepId":"58"}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"61","timestamp":{"nanos":29000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"60","timestamp":{"nanos":30000000,"seconds":0}}} +{"attachment":{"body":"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RmlsZTIgOCAwIFI+PgplbmRvYmoKMTAgMCBvYmoKPDwvVHlwZSAvRm9udAovRm9udERlc2NyaXB0b3IgOSAwIFIKL0Jhc2VGb250IC9BQUFBQUErQXJpYWxNVAovU3VidHlwZSAvQ0lERm9udFR5cGUyCi9DSURUb0dJRE1hcCAvSWRlbnRpdHkKL0NJRFN5c3RlbUluZm8gPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKElkZW50aXR5KQovU3VwcGxlbWVudCAwPj4KL1cgWzAgWzc1MF0gNTUgWzYxMC44Mzk4NF0gNzIgWzU1Ni4xNTIzNF0gODcgWzI3Ny44MzIwM11dCi9EVyA1MDA+PgplbmRvYmoKMTEgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDI1MD4+IHN0cmVhbQp4nF2Qy2rEIBSG9z7FWU4Xg0lmMtNFEMqUQha90LQPYPQkFRoVYxZ5+3pJU6ig8PP/n+dCb+1jq5UH+uaM6NDDoLR0OJvFCYQeR6VJWYFUwm8qvWLiltAAd+vscWr1YEjTAND34M7erXB4kKbHO0JfnUSn9AiHz1sXdLdY+40Tag8FYQwkDuGnZ25f+IRAE3ZsZfCVX4+B+Ut8rBahSrrM3QgjcbZcoON6RNIU4TBonsJhBLX851eZ6gfxxV1Mn64hXRT1mUV1vk/qUid2S5W/zF6ivmQos9fTls5+LBqXs08kFufCMGmDaYrYv9K4L9kaG6l4fwAdQH9hCmVuZHN0cmVhbQplbmRvYmoKNCAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMAovQmFzZUZvbnQgL0FBQUFBQStBcmlhbE1UCi9FbmNvZGluZyAvSWRlbnRpdHktSAovRGVzY2VuZGFudEZvbnRzIFsxMCAwIFJdCi9Ub1VuaWNvZGUgMTEgMCBSPj4KZW5kb2JqCnhyZWYKMCAxMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDM4MiAwMDAwMCBuIAowMDAwMDAwMTA4IDAwMDAwIG4gCjAwMDAwMDk2MDYgMDAwMDAgbiAKMDAwMDAwMDE0NSAwMDAwMCBuIAowMDAwMDAwNTkwIDAwMDAwIG4gCjAwMDAwMDA2NDUgMDAwMDAgbiAKMDAwMDAwMDY5MiAwMDAwMCBuIAowMDAwMDA4Nzg3IDAwMDAwIG4gCjAwMDAwMDkwMjEgMDAwMDAgbiAKMDAwMDAwOTI4NSAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgMTIKL1Jvb3QgNyAwIFIKL0luZm8gMSAwIFI+PgpzdGFydHhyZWYKOTc0NQolJUVPRgo=","contentEncoding":"BASE64","fileName":"renamed.pdf","mediaType":"application/pdf","testCaseStartedId":"71","testStepId":"60"}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":31000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"63","timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"62","timestamp":{"nanos":34000000,"seconds":0}}} +{"attachment":{"body":"https://cucumber.io","contentEncoding":"IDENTITY","mediaType":"text/uri-list","testCaseStartedId":"72","testStepId":"62"}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"62","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"45","timestamp":{"nanos":37000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json b/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json new file mode 100644 index 00000000..988c1074 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json @@ -0,0 +1,407 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 9, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 0, + "AMBIGUOUS" : 0, + "FAILED" : 0 + }, + "countTestCasesStarted" : 9, + "findAllPickles" : 9, + "findAllPickleSteps" : 9, + "findAllTestCaseStarted" : 9, + "findAllTestSteps" : 9, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "Attachments", + [ + "64", + "65", + "66", + "67", + "68", + "69", + "70", + "71", + "72" + ] + ] + ], + "findAttachmentsBy" : [ + [ + "46", + "64", + "application/octet-stream", + "IDENTITY" + ], + [ + "48", + "65", + "text/x.cucumber.log+plain", + "IDENTITY" + ], + [ + "50", + "66", + "text/x.cucumber.log+plain", + "IDENTITY" + ], + [ + "52", + "67", + "application/json", + "IDENTITY" + ], + [ + "54", + "68", + "text/plain", + "BASE64" + ], + [ + "56", + "69", + "image/jpeg", + "BASE64" + ], + [ + "58", + "70", + "image/png", + "BASE64" + ], + [ + "60", + "71", + "application/pdf", + "BASE64" + ], + [ + "62", + "72", + "text/uri-list", + "IDENTITY" + ] + ], + "findFeatureBy" : [ + "Attachments", + "Attachments", + "Attachments", + "Attachments", + "Attachments", + "Attachments", + "Attachments", + "Attachments", + "Attachments" + ], + "findLocationOf" : [ + { + "line" : 12, + "column" : 3 + }, + { + "line" : 18, + "column" : 3 + }, + { + "line" : 21, + "column" : 3 + }, + { + "line" : 24, + "column" : 3 + }, + { + "line" : 30, + "column" : 3 + }, + { + "line" : 33, + "column" : 3 + }, + { + "line" : 36, + "column" : 3 + }, + { + "line" : 39, + "column" : 3 + }, + { + "line" : 42, + "column" : 3 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + "PASSED", + "PASSED", + "PASSED", + "PASSED", + "PASSED", + "PASSED", + "PASSED", + "PASSED", + "PASSED" + ], + "findNameOf" : { + "long" : [ + "Attachments - Strings can be attached with a media type", + "Attachments - Log text", + "Attachments - Log ANSI coloured text", + "Attachments - Log JSON", + "Attachments - Byte arrays are base64-encoded regardless of media type", + "Attachments - Attaching JPEG images", + "Attachments - Attaching PNG images", + "Attachments - Attaching PDFs with a different filename", + "Attachments - Attaching URIs" + ], + "excludeFeatureName" : [ + "Strings can be attached with a media type", + "Log text", + "Log ANSI coloured text", + "Log JSON", + "Byte arrays are base64-encoded regardless of media type", + "Attaching JPEG images", + "Attaching PNG images", + "Attaching PDFs with a different filename", + "Attaching URIs" + ], + "longPickleName" : [ + "Attachments - Strings can be attached with a media type", + "Attachments - Log text", + "Attachments - Log ANSI coloured text", + "Attachments - Log JSON", + "Attachments - Byte arrays are base64-encoded regardless of media type", + "Attachments - Attaching JPEG images", + "Attachments - Attaching PNG images", + "Attachments - Attaching PDFs with a different filename", + "Attachments - Attaching URIs" + ], + "short" : [ + "Strings can be attached with a media type", + "Log text", + "Log ANSI coloured text", + "Log JSON", + "Byte arrays are base64-encoded regardless of media type", + "Attaching JPEG images", + "Attaching PNG images", + "Attaching PDFs with a different filename", + "Attaching URIs" + ], + "shortPickleName" : [ + "Strings can be attached with a media type", + "Log text", + "Log ANSI coloured text", + "Log JSON", + "Byte arrays are base64-encoded regardless of media type", + "Attaching JPEG images", + "Attaching PNG images", + "Attaching PDFs with a different filename", + "Attaching URIs" + ] + }, + "findPickleBy" : [ + "Strings can be attached with a media type", + "Log text", + "Log ANSI coloured text", + "Log JSON", + "Byte arrays are base64-encoded regardless of media type", + "Attaching JPEG images", + "Attaching PNG images", + "Attaching PDFs with a different filename", + "Attaching URIs" + ], + "findPickleStepBy" : [ + "the string \"hello\" is attached as \"application/octet-stream\"", + "the string \"hello\" is logged", + "text with ANSI escapes is logged", + "the following string is attached as \"application/json\":", + "an array with 10 bytes is attached as \"text/plain\"", + "a JPEG image is attached", + "a PNG image is attached", + "a PDF document is attached and renamed", + "a link to \"https://cucumber.io\" is attached" + ], + "findStepBy" : [ + "the string \"hello\" is attached as \"application/octet-stream\"", + "the string \"hello\" is logged", + "text with ANSI escapes is logged", + "the following string is attached as \"application/json\":", + "an array with 10 bytes is attached as \"text/plain\"", + "a JPEG image is attached", + "a PNG image is attached", + "a PDF document is attached and renamed", + "a link to \"https://cucumber.io\" is attached" + ], + "findTestCaseBy" : [ + "47", + "49", + "51", + "53", + "55", + "57", + "59", + "61", + "63" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + }, + { + "seconds" : 0, + "nanos" : 3000000 + } + ], + "findTestCaseFinishedBy" : [ + "64", + "65", + "66", + "67", + "68", + "69", + "70", + "71", + "72" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 37000000 + }, + "findTestRunFinished" : { + "success" : true, + "timestamp" : { + "seconds" : 0, + "nanos" : 37000000 + }, + "testRunStartedId" : "45" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "45" + }, + "findTestStepByTestStepStarted" : [ + "46", + "48", + "50", + "52", + "54", + "56", + "58", + "60", + "62" + ], + "findTestStepByTestStepFinished" : [ + "46", + "48", + "50", + "52", + "54", + "56", + "58", + "60", + "62" + ], + "findTestStepsFinishedBy" : [ + [ + "46" + ], + [ + "48" + ], + [ + "50" + ], + [ + "52" + ], + [ + "54" + ], + [ + "56" + ], + [ + "58" + ], + [ + "60" + ], + [ + "62" + ] + ], + "findTestStepFinishedAndTestStepBy" : [ + [ + "46", + "46" + ], + [ + "48", + "48" + ], + [ + "50", + "50" + ], + [ + "52", + "52" + ], + [ + "54", + "54" + ], + [ + "56", + "56" + ], + [ + "58", + "58" + ], + [ + "60", + "60" + ], + [ + "62", + "62" + ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson b/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson new file mode 100644 index 00000000..f0cb0b6d --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: cdata\n Cucumber xml formatters should be able to handle xml cdata elements\n\n Scenario: cdata\n Given I have 42 in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/cdata/cdata.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":4},"name":"cdata","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":5},"text":"I have 42 in my belly"}],"tags":[]}}],"description":" Cucumber xml formatters should be able to handle xml cdata elements","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"cdata","tags":[]},"uri":"samples/cdata/cdata.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cdata","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 in my belly","type":"Context"}],"tags":[],"uri":"samples/cdata/cdata.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/cdata/cdata.feature.ts"}}} +{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson b/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson new file mode 100644 index 00000000..d530c1c7 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson @@ -0,0 +1,15 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Data Tables\n Data Tables can be placed underneath a step and will be passed as the last\n argument to the step definition.\n\n They can be used to represent richer data structures, and can be transformed to other data-types.\n\n Scenario: transposed table\n When the following table is transposed:\n | a | b |\n | 1 | 2 |\n Then it should be:\n | a | 1 |\n | b | 2 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/data-tables/data-tables.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":7},"name":"transposed table","steps":[{"dataTable":{"location":{"column":7,"line":9},"rows":[{"cells":[{"location":{"column":9,"line":9},"value":"a"},{"location":{"column":13,"line":9},"value":"b"}],"id":"2","location":{"column":7,"line":9}},{"cells":[{"location":{"column":9,"line":10},"value":"1"},{"location":{"column":13,"line":10},"value":"2"}],"id":"3","location":{"column":7,"line":10}}]},"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"the following table is transposed:"},{"dataTable":{"location":{"column":7,"line":12},"rows":[{"cells":[{"location":{"column":9,"line":12},"value":"a"},{"location":{"column":13,"line":12},"value":"1"}],"id":"5","location":{"column":7,"line":12}},{"cells":[{"location":{"column":9,"line":13},"value":"b"},{"location":{"column":13,"line":13},"value":"2"}],"id":"6","location":{"column":7,"line":13}}]},"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":11},"text":"it should be:"}],"tags":[]}}],"description":" Data Tables can be placed underneath a step and will be passed as the last\n argument to the step definition.\n\n They can be used to represent richer data structures, and can be transformed to other data-types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Data Tables","tags":[]},"uri":"samples/data-tables/data-tables.feature"}} +{"pickle":{"astNodeIds":["8"],"id":"11","language":"en","name":"transposed table","steps":[{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"b"}]},{"cells":[{"value":"1"},{"value":"2"}]}]}},"astNodeIds":["4"],"id":"9","text":"the following table is transposed:","type":"Action"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"1"}]},{"cells":[{"value":"b"},{"value":"2"}]}]}},"astNodeIds":["7"],"id":"10","text":"it should be:","type":"Outcome"}],"tags":[],"uri":"samples/data-tables/data-tables.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"the following table is transposed:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":5},"uri":"samples/data-tables/data-tables.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"it should be:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/data-tables/data-tables.feature.ts"}}} +{"testRunStarted":{"id":"12","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"15","pickleId":"11","testRunStartedId":"12","testSteps":[{"id":"13","pickleStepId":"9","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"14","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"16","testCaseId":"15","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"16","testStepId":"13","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"16","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"16","testStepId":"14","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"16","testStepId":"14","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"16","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"12","timestamp":{"nanos":7000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/empty.feature.ndjson b/dotnet/Query/QueryTest/Resources/empty.feature.ndjson new file mode 100644 index 00000000..2e429bb5 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/empty.feature.ndjson @@ -0,0 +1,9 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Empty Scenarios\n Sometimes we want to quickly jot down a new scenario without specifying any actual steps\n for what should be executed.\n\n In this instance we want to stipulate what should / shouldn't run and what the output is\n\n Scenario: Blank Scenario\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/empty/empty.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"0","keyword":"Scenario","location":{"column":3,"line":7},"name":"Blank Scenario","steps":[],"tags":[]}}],"description":" Sometimes we want to quickly jot down a new scenario without specifying any actual steps\n for what should be executed.\n\n In this instance we want to stipulate what should / shouldn't run and what the output is","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Empty Scenarios","tags":[]},"uri":"samples/empty/empty.feature"}} +{"pickle":{"astNodeIds":["0"],"id":"1","language":"en","name":"Blank Scenario","steps":[],"tags":[],"uri":"samples/empty/empty.feature"}} +{"testRunStarted":{"id":"2","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"3","pickleId":"1","testRunStartedId":"2","testSteps":[]}} +{"testCaseStarted":{"attempt":0,"id":"4","testCaseId":"3","timestamp":{"nanos":1000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"4","timestamp":{"nanos":2000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"2","timestamp":{"nanos":3000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json b/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json new file mode 100644 index 00000000..645774a5 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json @@ -0,0 +1,91 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 0, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 0, + "AMBIGUOUS" : 0, + "FAILED" : 0 + }, + "countTestCasesStarted" : 1, + "findAllPickles" : 1, + "findAllPickleSteps" : 0, + "findAllTestCaseStarted" : 1, + "findAllTestSteps" : 0, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "Empty Scenarios", + [ + "4" + ] + ] + ], + "findFeatureBy" : [ + "Empty Scenarios" + ], + "findLocationOf" : [ + { + "line" : 7, + "column" : 3 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + null + ], + "findNameOf" : { + "long" : [ + "Empty Scenarios - Blank Scenario" + ], + "excludeFeatureName" : [ + "Blank Scenario" + ], + "longPickleName" : [ + "Empty Scenarios - Blank Scenario" + ], + "short" : [ + "Blank Scenario" + ], + "shortPickleName" : [ + "Blank Scenario" + ] + }, + "findPickleBy" : [ + "Blank Scenario" + ], + "findTestCaseBy" : [ + "3" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 1000000 + } + ], + "findTestCaseFinishedBy" : [ + "4" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 3000000 + }, + "findTestRunFinished" : { + "success" : true, + "timestamp" : { + "seconds" : 0, + "nanos" : 3000000 + }, + "testRunStartedId" : "2" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "2" + }, + "findTestStepsFinishedBy" : [ + [ ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson b/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson new file mode 100644 index 00000000..5c277447 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson @@ -0,0 +1,21 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Examples Tables - With attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.\n\n Scenario Outline: Attaching images in an examples table\n When a image is attached\n\n Examples:\n | type |\n | JPEG |\n | PNG |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"6","keyword":"Examples","location":{"column":5,"line":10},"name":"","tableBody":[{"cells":[{"location":{"column":9,"line":12},"value":"JPEG"}],"id":"4","location":{"column":7,"line":12}},{"cells":[{"location":{"column":9,"line":13},"value":"PNG"}],"id":"5","location":{"column":7,"line":13}}],"tableHeader":{"cells":[{"location":{"column":9,"line":11},"value":"type"}],"id":"3","location":{"column":7,"line":11}},"tags":[]}],"id":"7","keyword":"Scenario Outline","location":{"column":3,"line":7},"name":"Attaching images in an examples table","steps":[{"id":"2","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a image is attached"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables - With attachments","tags":[]},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} +{"pickle":{"astNodeIds":["7","4"],"id":"9","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","4"],"id":"8","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} +{"pickle":{"astNodeIds":["7","5"],"id":"11","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","5"],"id":"10","text":"a PNG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a PNG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}} +{"testRunStarted":{"id":"12","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"14","pickleId":"9","testRunStartedId":"12","testSteps":[{"id":"13","pickleStepId":"8","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"16","pickleId":"11","testRunStartedId":"12","testSteps":[{"id":"15","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"17","testCaseId":"14","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"17","testStepId":"13","timestamp":{"nanos":2000000,"seconds":0}}} +{"attachment":{"body":"/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAC4AKQMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAIBAUGBwABAwL/2gAIAQEAAAAAOESYe+lPPw0bK2mvU5gRhNkM/tNMGeuJM5msiEjujvC+s0ApSWvn/8QAFgEBAQEAAAAAAAAAAAAAAAAABQME/9oACAECEAAAADs6pclK4E//xAAWAQEBAQAAAAAAAAAAAAAAAAAHBgT/2gAIAQMQAAAAMJZbKcF1XHit/8QANhAAAQQBAgQDBAcJAAAAAAAAAgEDBAUGABEHEiExEyJREEFCUhRTYXFzgZIVFiMyMzRVY3L/2gAIAQEAAT8AzLMqPBKOReXb6gy3sDbYdXXnS/labH3mWrrMOIWdGb063fxyoPq1XVp8klQ/3v8Aff7E0eCY86fjPtynn99/GclOq5v6782quZnOGmEnEcrmPNN96y1cWTFcH5BUurf5a4bcTKzP6x9QjlBuIKo1YVzq7mwfuJF+IC9y+zPLc8z4kWiuHz1GLuLAht/AU3u+6qfMK+XUuV4TbrTBtFNVoyYZM0RTJE6dO+2+oGcWZY1fzp0URsq5wGuXkUU3dLlHmH1FdYvMs59HCmW7SBKdQiVEHl3Hfyqqe7dNFbOYRlNDnkQlBth9uHaoPZ2C+SCSl9oL1HX0qN9c3+pNY6pkeSG9/XO/sie9fEV5d9Z5FxdbKNKsbeREsUbHZGAVxeQV6Lt8K6gtMPQYzhD43istETjzaC45sm6EaeulzOgC1Kmdkm1KF3wvO2Qjz+m+syECxe7Q+30ZV/NF3TX7dyv5nv06zGpPDOJd/WvAoV+QvHb1znwk8f8AcN/9c3XUuhp5s1qyl17L0poUQDNN+3VN07LqDTZdNg5fLsFdanyxAI4c/wBUSnsGy9B9w6x+kWwrq2blFW2VtHVUF11P4qiC+RT27r9+r6E9kUyiwmDusq8nNMny924zZc7rv3Cia/dSg/xTH6dcQMDpc/oSqbLmZeaNHoUxro9GfHs4C6uoGZYC4cXM6Z+TCb6BdV7avRjH1dEerRagWEO0iNToDyOx3N+Q0RU32XZehbLq4u4VMyByFI33VQI8ZpOZ5416IICnVdcHuHNjUOSs3y5lByGwaRpiL3Svid0b/EL4vavbXDDBM5ymjjRKi3qK2vZ5lOSYOvykRw1Lyhsgawbg9jGGSUtzJ63v1TzWU/zuB+CPZtPb/8QAJREAAgEDBAEEAwAAAAAAAAAAAQIDAAQRBRITIVEUMTJhI0Fx/9oACAECAQE/ALy8eNxb2/z63N4zTy6hbbpJJ9wV9uCdwPWaglFxEkqDGeiPBFSv6bUZJXLhXGQVx3kfdPBbpyvLNyDOAEbsEjOfsVpJ4rUlx83JH8FSwxTqElTI/R9iKGkBJm5X/GGO1R7kV0AABgAYA8Cv/8QAJREAAgIBBAEDBQAAAAAAAAAAAQIDBAUABhESMSFRcRMVIjJB/9oACAEDAQE/AN1bpuJcbFYt+hXgSSDzydG9uLFF7T3yekwjKl+wY8dvHtrAZlMzjo7RAWQHrIvsw1k+2I3LdksmZVcsymPjlg/z/NTU6MIsy2bf1x26hYnHKsy9ufXyB41sWnN9rmlPKrJNyvwBxrL4LH5mMLbj/Nf1dfRhqjsKaa27WZgtRZD1APLsuq1aGpBHXgQLGihVA1//2Q==","contentEncoding":"BASE64","mediaType":"image/jpeg","testCaseStartedId":"17","testStepId":"13"}} +{"testStepFinished":{"testCaseStartedId":"17","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"17","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"18","testCaseId":"16","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"18","testStepId":"15","timestamp":{"nanos":6000000,"seconds":0}}} +{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"18","testStepId":"15"}} +{"testStepFinished":{"testCaseStartedId":"18","testStepId":"15","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"18","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"12","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson b/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson new file mode 100644 index 00000000..c60e75c2 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson @@ -0,0 +1,100 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Examples Tables\n Sometimes it can be desirable to run the same scenario multiple times with\n different data each time - this can be done by placing an Examples table\n underneath a Scenario, and use in the Scenario which match the\n table headers.\n\n The Scenario Outline name can also be parameterized. The name of the resulting\n pickle will have the replaced with the value from the examples\n table.\n\n Scenario Outline: Eating cucumbers\n Given there are cucumbers\n When I eat cucumbers\n Then I should have cucumbers\n\n @passing\n Examples: These are passing\n | start | eat | left |\n | 12 | 5 | 7 |\n | 20 | 5 | 15 |\n\n @failing\n Examples: These are failing\n | start | eat | left |\n | 12 | 20 | 0 |\n | 0 | 1 | 0 |\n\n @undefined\n Examples: These are undefined because the value is not an {int}\n | start | eat | left |\n | 12 | banana | 12 |\n | 0 | 1 | apple |\n\n Scenario Outline: Eating cucumbers with friends\n Given there are friends\n And there are cucumbers\n Then each person can eat cucumbers\n\n Examples:\n | friends | start | share |\n | 11 | 12 | 1 |\n | 1 | 4 | 2 |\n | 0 | 4 | 4 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables/examples-tables.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"12","keyword":"Examples","location":{"column":5,"line":17},"name":"These are passing","tableBody":[{"cells":[{"location":{"column":12,"line":19},"value":"12"},{"location":{"column":19,"line":19},"value":"5"},{"location":{"column":26,"line":19},"value":"7"}],"id":"9","location":{"column":7,"line":19}},{"cells":[{"location":{"column":12,"line":20},"value":"20"},{"location":{"column":19,"line":20},"value":"5"},{"location":{"column":25,"line":20},"value":"15"}],"id":"10","location":{"column":7,"line":20}}],"tableHeader":{"cells":[{"location":{"column":9,"line":18},"value":"start"},{"location":{"column":17,"line":18},"value":"eat"},{"location":{"column":23,"line":18},"value":"left"}],"id":"8","location":{"column":7,"line":18}},"tags":[{"id":"11","location":{"column":5,"line":16},"name":"@passing"}]},{"description":"","id":"17","keyword":"Examples","location":{"column":5,"line":23},"name":"These are failing","tableBody":[{"cells":[{"location":{"column":12,"line":25},"value":"12"},{"location":{"column":18,"line":25},"value":"20"},{"location":{"column":26,"line":25},"value":"0"}],"id":"14","location":{"column":7,"line":25}},{"cells":[{"location":{"column":13,"line":26},"value":"0"},{"location":{"column":19,"line":26},"value":"1"},{"location":{"column":26,"line":26},"value":"0"}],"id":"15","location":{"column":7,"line":26}}],"tableHeader":{"cells":[{"location":{"column":9,"line":24},"value":"start"},{"location":{"column":17,"line":24},"value":"eat"},{"location":{"column":23,"line":24},"value":"left"}],"id":"13","location":{"column":7,"line":24}},"tags":[{"id":"16","location":{"column":5,"line":22},"name":"@failing"}]},{"description":"","id":"22","keyword":"Examples","location":{"column":5,"line":29},"name":"These are undefined because the value is not an {int}","tableBody":[{"cells":[{"location":{"column":12,"line":31},"value":"12"},{"location":{"column":17,"line":31},"value":"banana"},{"location":{"column":29,"line":31},"value":"12"}],"id":"19","location":{"column":7,"line":31}},{"cells":[{"location":{"column":13,"line":32},"value":"0"},{"location":{"column":22,"line":32},"value":"1"},{"location":{"column":26,"line":32},"value":"apple"}],"id":"20","location":{"column":7,"line":32}}],"tableHeader":{"cells":[{"location":{"column":9,"line":30},"value":"start"},{"location":{"column":17,"line":30},"value":"eat"},{"location":{"column":26,"line":30},"value":"left"}],"id":"18","location":{"column":7,"line":30}},"tags":[{"id":"21","location":{"column":5,"line":28},"name":"@undefined"}]}],"id":"23","keyword":"Scenario Outline","location":{"column":3,"line":11},"name":"Eating cucumbers","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"there are cucumbers"},{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":13},"text":"I eat cucumbers"},{"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":14},"text":"I should have cucumbers"}],"tags":[]}},{"scenario":{"description":"","examples":[{"description":"","id":"31","keyword":"Examples","location":{"column":5,"line":39},"name":"","tableBody":[{"cells":[{"location":{"column":14,"line":41},"value":"11"},{"location":{"column":22,"line":41},"value":"12"},{"location":{"column":31,"line":41},"value":"1"}],"id":"28","location":{"column":7,"line":41}},{"cells":[{"location":{"column":15,"line":42},"value":"1"},{"location":{"column":23,"line":42},"value":"4"},{"location":{"column":31,"line":42},"value":"2"}],"id":"29","location":{"column":7,"line":42}},{"cells":[{"location":{"column":15,"line":43},"value":"0"},{"location":{"column":23,"line":43},"value":"4"},{"location":{"column":31,"line":43},"value":"4"}],"id":"30","location":{"column":7,"line":43}}],"tableHeader":{"cells":[{"location":{"column":9,"line":40},"value":"friends"},{"location":{"column":19,"line":40},"value":"start"},{"location":{"column":27,"line":40},"value":"share"}],"id":"27","location":{"column":7,"line":40}},"tags":[]}],"id":"32","keyword":"Scenario Outline","location":{"column":3,"line":34},"name":"Eating cucumbers with friends","steps":[{"id":"24","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":35},"text":"there are friends"},{"id":"25","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":36},"text":"there are cucumbers"},{"id":"26","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":37},"text":"each person can eat cucumbers"}],"tags":[]}}],"description":" Sometimes it can be desirable to run the same scenario multiple times with\n different data each time - this can be done by placing an Examples table\n underneath a Scenario, and use in the Scenario which match the\n table headers.\n\n The Scenario Outline name can also be parameterized. The name of the resulting\n pickle will have the replaced with the value from the examples\n table.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables","tags":[]},"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","9"],"id":"36","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","9"],"id":"33","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","9"],"id":"34","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["7","9"],"id":"35","text":"I should have 7 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"11","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","10"],"id":"40","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","10"],"id":"37","text":"there are 20 cucumbers","type":"Context"},{"astNodeIds":["6","10"],"id":"38","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["7","10"],"id":"39","text":"I should have 15 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"11","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","14"],"id":"44","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","14"],"id":"41","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","14"],"id":"42","text":"I eat 20 cucumbers","type":"Action"},{"astNodeIds":["7","14"],"id":"43","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"16","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","15"],"id":"48","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","15"],"id":"45","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["6","15"],"id":"46","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["7","15"],"id":"47","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"16","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","19"],"id":"52","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","19"],"id":"49","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","19"],"id":"50","text":"I eat banana cucumbers","type":"Action"},{"astNodeIds":["7","19"],"id":"51","text":"I should have 12 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["23","20"],"id":"56","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","20"],"id":"53","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["6","20"],"id":"54","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["7","20"],"id":"55","text":"I should have apple cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["32","28"],"id":"60","language":"en","name":"Eating cucumbers with 11 friends","steps":[{"astNodeIds":["24","28"],"id":"57","text":"there are 11 friends","type":"Context"},{"astNodeIds":["25","28"],"id":"58","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["26","28"],"id":"59","text":"each person can eat 1 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["32","29"],"id":"64","language":"en","name":"Eating cucumbers with 1 friends","steps":[{"astNodeIds":["24","29"],"id":"61","text":"there are 1 friends","type":"Context"},{"astNodeIds":["25","29"],"id":"62","text":"there are 4 cucumbers","type":"Context"},{"astNodeIds":["26","29"],"id":"63","text":"each person can eat 2 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["32","30"],"id":"68","language":"en","name":"Eating cucumbers with 0 friends","steps":[{"astNodeIds":["24","30"],"id":"65","text":"there are 0 friends","type":"Context"},{"astNodeIds":["25","30"],"id":"66","text":"there are 4 cucumbers","type":"Context"},{"astNodeIds":["26","30"],"id":"67","text":"each person can eat 4 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"there are {int} friends","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"I eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"I should have {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"4","pattern":{"source":"each person can eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":20},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"testRunStarted":{"id":"69","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"73","pickleId":"36","testRunStartedId":"69","testSteps":[{"id":"70","pickleStepId":"33","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"71","pickleStepId":"34","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"72","pickleStepId":"35","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"7"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"77","pickleId":"40","testRunStartedId":"69","testSteps":[{"id":"74","pickleStepId":"37","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"75","pickleStepId":"38","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"76","pickleStepId":"39","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"15"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"81","pickleId":"44","testRunStartedId":"69","testSteps":[{"id":"78","pickleStepId":"41","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"79","pickleStepId":"42","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"80","pickleStepId":"43","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"85","pickleId":"48","testRunStartedId":"69","testSteps":[{"id":"82","pickleStepId":"45","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"83","pickleStepId":"46","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"84","pickleStepId":"47","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"89","pickleId":"52","testRunStartedId":"69","testSteps":[{"id":"86","pickleStepId":"49","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"87","pickleStepId":"50","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"88","pickleStepId":"51","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"12"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"93","pickleId":"56","testRunStartedId":"69","testSteps":[{"id":"90","pickleStepId":"53","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"91","pickleStepId":"54","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"92","pickleStepId":"55","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCase":{"id":"97","pickleId":"60","testRunStartedId":"69","testSteps":[{"id":"94","pickleStepId":"57","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"11"},"parameterTypeName":"int"}]}]},{"id":"95","pickleStepId":"58","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"96","pickleStepId":"59","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"1"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"101","pickleId":"64","testRunStartedId":"69","testSteps":[{"id":"98","pickleStepId":"61","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"99","pickleStepId":"62","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"4"},"parameterTypeName":"int"}]}]},{"id":"100","pickleStepId":"63","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"2"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"105","pickleId":"68","testRunStartedId":"69","testSteps":[{"id":"102","pickleStepId":"65","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"103","pickleStepId":"66","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"4"},"parameterTypeName":"int"}]}]},{"id":"104","pickleStepId":"67","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"4"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"106","testCaseId":"73","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"106","testStepId":"70","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"106","testStepId":"70","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"106","testStepId":"71","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"106","testStepId":"71","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"106","testStepId":"72","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"106","testStepId":"72","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"106","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"107","testCaseId":"77","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"107","testStepId":"74","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"107","testStepId":"74","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"107","testStepId":"75","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"107","testStepId":"75","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"107","testStepId":"76","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"107","testStepId":"76","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"107","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"108","testCaseId":"81","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"108","testStepId":"78","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"108","testStepId":"78","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"108","testStepId":"79","timestamp":{"nanos":20000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"108","testStepId":"79","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"108","testStepId":"80","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"108","testStepId":"80","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-8 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-8 !== 0\n\nsamples/examples-tables/examples-tables.feature:14\nsamples/examples-tables/examples-tables.feature:25","status":"FAILED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"108","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"109","testCaseId":"85","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"109","testStepId":"82","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"109","testStepId":"82","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"109","testStepId":"83","timestamp":{"nanos":28000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"109","testStepId":"83","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"109","testStepId":"84","timestamp":{"nanos":30000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"109","testStepId":"84","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-1 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-1 !== 0\n\nsamples/examples-tables/examples-tables.feature:14\nsamples/examples-tables/examples-tables.feature:26","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"109","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"110","testCaseId":"89","timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"110","testStepId":"86","timestamp":{"nanos":34000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"110","testStepId":"86","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"110","testStepId":"87","timestamp":{"nanos":36000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"110","testStepId":"87","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"110","testStepId":"88","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"110","testStepId":"88","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"110","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"111","testCaseId":"93","timestamp":{"nanos":41000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"111","testStepId":"90","timestamp":{"nanos":42000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"111","testStepId":"90","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":43000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"111","testStepId":"91","timestamp":{"nanos":44000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"111","testStepId":"91","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"111","testStepId":"92","timestamp":{"nanos":46000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"111","testStepId":"92","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":47000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"111","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"112","testCaseId":"97","timestamp":{"nanos":49000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"112","testStepId":"94","timestamp":{"nanos":50000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"112","testStepId":"94","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":51000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"112","testStepId":"95","timestamp":{"nanos":52000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"112","testStepId":"95","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":53000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"112","testStepId":"96","timestamp":{"nanos":54000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"112","testStepId":"96","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":55000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"112","timestamp":{"nanos":56000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"113","testCaseId":"101","timestamp":{"nanos":57000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"113","testStepId":"98","timestamp":{"nanos":58000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"113","testStepId":"98","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":59000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"113","testStepId":"99","timestamp":{"nanos":60000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"113","testStepId":"99","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":61000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"113","testStepId":"100","timestamp":{"nanos":62000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"113","testStepId":"100","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":63000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"113","timestamp":{"nanos":64000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"114","testCaseId":"105","timestamp":{"nanos":65000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"114","testStepId":"102","timestamp":{"nanos":66000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"114","testStepId":"102","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":67000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"114","testStepId":"103","timestamp":{"nanos":68000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"114","testStepId":"103","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":69000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"114","testStepId":"104","timestamp":{"nanos":70000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"114","testStepId":"104","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":71000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"114","timestamp":{"nanos":72000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"69","timestamp":{"nanos":73000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json b/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json new file mode 100644 index 00000000..8380693f --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json @@ -0,0 +1,513 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 5, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 2, + "AMBIGUOUS" : 0, + "FAILED" : 2 + }, + "countTestCasesStarted" : 9, + "findAllPickles" : 9, + "findAllPickleSteps" : 27, + "findAllTestCaseStarted" : 9, + "findAllTestSteps" : 27, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "Examples Tables", + [ + "106", + "107", + "108", + "109", + "110", + "111", + "112", + "113", + "114" + ] + ] + ], + "findFeatureBy" : [ + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables", + "Examples Tables" + ], + "findLocationOf" : [ + { + "line" : 19, + "column" : 7 + }, + { + "line" : 20, + "column" : 7 + }, + { + "line" : 25, + "column" : 7 + }, + { + "line" : 26, + "column" : 7 + }, + { + "line" : 31, + "column" : 7 + }, + { + "line" : 32, + "column" : 7 + }, + { + "line" : 41, + "column" : 7 + }, + { + "line" : 42, + "column" : 7 + }, + { + "line" : 43, + "column" : 7 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + "PASSED", + "PASSED", + "FAILED", + "FAILED", + "UNDEFINED", + "UNDEFINED", + "PASSED", + "PASSED", + "PASSED" + ], + "findNameOf" : { + "long" : [ + "Examples Tables - Eating cucumbers - These are passing - #1.1", + "Examples Tables - Eating cucumbers - These are passing - #1.2", + "Examples Tables - Eating cucumbers - These are failing - #2.1", + "Examples Tables - Eating cucumbers - These are failing - #2.2", + "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - #3.1", + "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - #3.2", + "Examples Tables - Eating cucumbers with friends - #1.1: Eating cucumbers with 11 friends", + "Examples Tables - Eating cucumbers with friends - #1.2: Eating cucumbers with 1 friends", + "Examples Tables - Eating cucumbers with friends - #1.3: Eating cucumbers with 0 friends" + ], + "excludeFeatureName" : [ + "Eating cucumbers - These are passing - #1.1", + "Eating cucumbers - These are passing - #1.2", + "Eating cucumbers - These are failing - #2.1", + "Eating cucumbers - These are failing - #2.2", + "Eating cucumbers - These are undefined because the value is not an {int} - #3.1", + "Eating cucumbers - These are undefined because the value is not an {int} - #3.2", + "Eating cucumbers with friends - #1.1: Eating cucumbers with 11 friends", + "Eating cucumbers with friends - #1.2: Eating cucumbers with 1 friends", + "Eating cucumbers with friends - #1.3: Eating cucumbers with 0 friends" + ], + "longPickleName" : [ + "Examples Tables - Eating cucumbers - These are passing - Eating cucumbers", + "Examples Tables - Eating cucumbers - These are passing - Eating cucumbers", + "Examples Tables - Eating cucumbers - These are failing - Eating cucumbers", + "Examples Tables - Eating cucumbers - These are failing - Eating cucumbers", + "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - Eating cucumbers", + "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - Eating cucumbers", + "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 11 friends", + "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 1 friends", + "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 0 friends" + ], + "short" : [ + "#1.1", + "#1.2", + "#2.1", + "#2.2", + "#3.1", + "#3.2", + "#1.1: Eating cucumbers with 11 friends", + "#1.2: Eating cucumbers with 1 friends", + "#1.3: Eating cucumbers with 0 friends" + ], + "shortPickleName" : [ + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers with 11 friends", + "Eating cucumbers with 1 friends", + "Eating cucumbers with 0 friends" + ] + }, + "findPickleBy" : [ + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers", + "Eating cucumbers with 11 friends", + "Eating cucumbers with 1 friends", + "Eating cucumbers with 0 friends" + ], + "findPickleStepBy" : [ + "each person can eat 2 cucumbers", + "there are 0 friends", + "there are 4 cucumbers", + "each person can eat 4 cucumbers", + "there are 12 cucumbers", + "I eat 5 cucumbers", + "I should have 7 cucumbers", + "there are 20 cucumbers", + "I eat 5 cucumbers", + "I should have 15 cucumbers", + "there are 12 cucumbers", + "I eat 20 cucumbers", + "I should have 0 cucumbers", + "there are 0 cucumbers", + "I eat 1 cucumbers", + "I should have 0 cucumbers", + "there are 12 cucumbers", + "I eat banana cucumbers", + "I should have 12 cucumbers", + "there are 0 cucumbers", + "I eat 1 cucumbers", + "I should have apple cucumbers", + "there are 11 friends", + "there are 12 cucumbers", + "each person can eat 1 cucumbers", + "there are 1 friends", + "there are 4 cucumbers" + ], + "findStepBy" : [ + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are cucumbers", + "I eat cucumbers", + "I should have cucumbers", + "there are friends", + "there are cucumbers", + "each person can eat cucumbers", + "there are friends", + "there are cucumbers", + "each person can eat cucumbers", + "there are friends", + "there are cucumbers", + "each person can eat cucumbers" + ], + "findTestCaseBy" : [ + "73", + "77", + "81", + "85", + "89", + "93", + "97", + "101", + "105" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + } + ], + "findTestCaseFinishedBy" : [ + "106", + "107", + "108", + "109", + "110", + "111", + "112", + "113", + "114" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 73000000 + }, + "findTestRunFinished" : { + "success" : false, + "timestamp" : { + "seconds" : 0, + "nanos" : 73000000 + }, + "testRunStartedId" : "69" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "69" + }, + "findTestStepByTestStepStarted" : [ + "70", + "71", + "72", + "74", + "75", + "76", + "78", + "79", + "80", + "82", + "83", + "84", + "86", + "87", + "88", + "90", + "91", + "92", + "94", + "95", + "96", + "98", + "99", + "100", + "102", + "103", + "104" + ], + "findTestStepByTestStepFinished" : [ + "70", + "71", + "72", + "74", + "75", + "76", + "78", + "79", + "80", + "82", + "83", + "84", + "86", + "87", + "88", + "90", + "91", + "92", + "94", + "95", + "96", + "98", + "99", + "100", + "102", + "103", + "104" + ], + "findTestStepsFinishedBy" : [ + [ + "70", + "71", + "72" + ], + [ + "74", + "75", + "76" + ], + [ + "78", + "79", + "80" + ], + [ + "82", + "83", + "84" + ], + [ + "86", + "87", + "88" + ], + [ + "90", + "91", + "92" + ], + [ + "94", + "95", + "96" + ], + [ + "98", + "99", + "100" + ], + [ + "102", + "103", + "104" + ] + ], + "findTestStepFinishedAndTestStepBy" : [ + [ + "70", + "70" + ], + [ + "71", + "71" + ], + [ + "72", + "72" + ], + [ + "74", + "74" + ], + [ + "75", + "75" + ], + [ + "76", + "76" + ], + [ + "78", + "78" + ], + [ + "79", + "79" + ], + [ + "80", + "80" + ], + [ + "82", + "82" + ], + [ + "83", + "83" + ], + [ + "84", + "84" + ], + [ + "86", + "86" + ], + [ + "87", + "87" + ], + [ + "88", + "88" + ], + [ + "90", + "90" + ], + [ + "91", + "91" + ], + [ + "92", + "92" + ], + [ + "94", + "94" + ], + [ + "95", + "95" + ], + [ + "96", + "96" + ], + [ + "98", + "98" + ], + [ + "99", + "99" + ], + [ + "100", + "100" + ], + [ + "102", + "102" + ], + [ + "103", + "103" + ], + [ + "104", + "104" + ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson new file mode 100644 index 00000000..5e911d8f --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson @@ -0,0 +1,20 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Hooks - Attachments\n Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.\n\n Scenario: With an valid attachment in the hook and a passed step\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-attachment/hooks-attachment.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":6},"name":"With an valid attachment in the hook and a passed step","steps":[{"id":"3","keyword":"When ","keywordType":"Action","location":{"column":5,"line":7},"text":"a step passes"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Attachments","tags":[]},"uri":"samples/hooks-attachment/hooks-attachment.feature"}} +{"pickle":{"astNodeIds":["4"],"id":"6","language":"en","name":"With an valid attachment in the hook and a passed step","steps":[{"astNodeIds":["3"],"id":"5","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks-attachment/hooks-attachment.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":4},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"BEFORE_TEST_CASE"}} +{"hook":{"id":"2","sourceReference":{"location":{"line":13},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"AFTER_TEST_CASE"}} +{"testRunStarted":{"id":"7","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"11","pickleId":"6","testRunStartedId":"7","testSteps":[{"hookId":"0","id":"8"},{"id":"9","pickleStepId":"5","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"2","id":"10"}]}} +{"testCaseStarted":{"attempt":0,"id":"12","testCaseId":"11","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"8","timestamp":{"nanos":2000000,"seconds":0}}} +{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"12","testStepId":"8"}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"8","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"9","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"9","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"10","timestamp":{"nanos":6000000,"seconds":0}}} +{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"12","testStepId":"10"}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"10","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"12","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"7","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson new file mode 100644 index 00000000..c2473224 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson @@ -0,0 +1,36 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Hooks - Conditional execution\n Hooks are special steps that run before or after each scenario's steps.\n\n They can also conditionally target specific scenarios, using tag expressions\n\n @fail-before\n Scenario: A failure in the before hook and a skipped step\n When a step passes\n\n @fail-after\n Scenario: A failure in the after hook and a passed step\n When a step passes\n\n @passing-hook\n Scenario: With an tag, a passed step and hook\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-conditional/hooks-conditional.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":7},"name":"A failure in the before hook and a skipped step","steps":[{"id":"5","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step passes"}],"tags":[{"id":"6","location":{"column":3,"line":6},"name":"@fail-before"}]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":11},"name":"A failure in the after hook and a passed step","steps":[{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":12},"text":"a step passes"}],"tags":[{"id":"9","location":{"column":3,"line":10},"name":"@fail-after"}]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":15},"name":"With an tag, a passed step and hook","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"a step passes"}],"tags":[{"id":"12","location":{"column":3,"line":14},"name":"@passing-hook"}]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n They can also conditionally target specific scenarios, using tag expressions","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Conditional execution","tags":[]},"uri":"samples/hooks-conditional/hooks-conditional.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"A failure in the before hook and a skipped step","steps":[{"astNodeIds":["5"],"id":"14","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"6","name":"@fail-before"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"17","language":"en","name":"A failure in the after hook and a passed step","steps":[{"astNodeIds":["8"],"id":"16","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"9","name":"@fail-after"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} +{"pickle":{"astNodeIds":["13"],"id":"19","language":"en","name":"With an tag, a passed step and hook","steps":[{"astNodeIds":["11"],"id":"18","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"12","name":"@passing-hook"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@passing-hook","type":"BEFORE_TEST_CASE"}} +{"hook":{"id":"1","sourceReference":{"location":{"line":7},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@fail-before","type":"BEFORE_TEST_CASE"}} +{"hook":{"id":"3","sourceReference":{"location":{"line":15},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@fail-after","type":"AFTER_TEST_CASE"}} +{"hook":{"id":"4","sourceReference":{"location":{"line":19},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@passing-hook","type":"AFTER_TEST_CASE"}} +{"testRunStarted":{"id":"20","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"23","pickleId":"15","testRunStartedId":"20","testSteps":[{"hookId":"1","id":"21"},{"id":"22","pickleStepId":"14","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"26","pickleId":"17","testRunStartedId":"20","testSteps":[{"id":"24","pickleStepId":"16","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"25"}]}} +{"testCase":{"id":"30","pickleId":"19","testRunStartedId":"20","testSteps":[{"hookId":"0","id":"27"},{"id":"28","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"29"}]}} +{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"23","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"21","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks-conditional/hooks-conditional.feature:7","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"22","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"26","timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"24","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"25","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks-conditional/hooks-conditional.feature:11","status":"FAILED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"33","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"33","testStepId":"27","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"33","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"33","testStepId":"28","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"33","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"33","testStepId":"29","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"33","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"33","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"20","timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson new file mode 100644 index 00000000..6d415aad --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson @@ -0,0 +1,18 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Hooks - Named\n Hooks are special steps that run before or after each scenario's steps.\n\n Hooks can be given a name. Which is nice for reporting. Otherwise they work\n exactly the same as regular hooks.\n\n Scenario: With a named before and after hook\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-named/hooks-named.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":7},"name":"With a named before and after hook","steps":[{"id":"3","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step passes"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n Hooks can be given a name. Which is nice for reporting. Otherwise they work\n exactly the same as regular hooks.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Named","tags":[]},"uri":"samples/hooks-named/hooks-named.feature"}} +{"pickle":{"astNodeIds":["4"],"id":"6","language":"en","name":"With a named before and after hook","steps":[{"astNodeIds":["3"],"id":"5","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks-named/hooks-named.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/hooks-named/hooks-named.feature.ts"}}} +{"hook":{"id":"0","name":"A named before hook","sourceReference":{"location":{"line":3},"uri":"samples/hooks-named/hooks-named.feature.ts"},"type":"BEFORE_TEST_CASE"}} +{"hook":{"id":"2","name":"A named after hook","sourceReference":{"location":{"line":11},"uri":"samples/hooks-named/hooks-named.feature.ts"},"type":"AFTER_TEST_CASE"}} +{"testRunStarted":{"id":"7","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"11","pickleId":"6","testRunStartedId":"7","testSteps":[{"hookId":"0","id":"8"},{"id":"9","pickleStepId":"5","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"2","id":"10"}]}} +{"testCaseStarted":{"attempt":0,"id":"12","testCaseId":"11","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"8","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"8","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"9","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"9","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"12","testStepId":"10","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"12","testStepId":"10","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"12","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"7","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson new file mode 100644 index 00000000..238718e9 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson @@ -0,0 +1,39 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} +{"source":{"data":"Feature: Hooks\n Hooks are special steps that run before or after each scenario's steps.\n\n Scenario: No tags and a passed step\n When a step passes\n\n Scenario: No tags and a failed step\n When a step fails\n\n Scenario: No tags and a undefined step\n When a step does not exist\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks/hooks.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":4},"name":"No tags and a passed step","steps":[{"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":5},"text":"a step passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":7},"name":"No tags and a failed step","steps":[{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":10},"name":"No tags and a undefined step","steps":[{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":11},"text":"a step does not exist"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks","tags":[]},"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["5"],"id":"11","language":"en","name":"No tags and a passed step","steps":[{"astNodeIds":["4"],"id":"10","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"13","language":"en","name":"No tags and a failed step","steps":[{"astNodeIds":["6"],"id":"12","text":"a step fails","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"15","language":"en","name":"No tags and a undefined step","steps":[{"astNodeIds":["8"],"id":"14","text":"a step does not exist","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/hooks/hooks.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/hooks/hooks.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/hooks/hooks.feature.ts"},"type":"BEFORE_TEST_CASE"}} +{"hook":{"id":"3","sourceReference":{"location":{"line":15},"uri":"samples/hooks/hooks.feature.ts"},"type":"AFTER_TEST_CASE"}} +{"testRunStarted":{"id":"16","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"20","pickleId":"11","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"17"},{"id":"18","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"19"}]}} +{"testCase":{"id":"24","pickleId":"13","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"21"},{"id":"22","pickleStepId":"12","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"23"}]}} +{"testCase":{"id":"28","pickleId":"15","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"25"},{"id":"26","pickleStepId":"14","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"hookId":"3","id":"27"}]}} +{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"17","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"17","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"18","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"18","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"19","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"19","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"24","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"21","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"22","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:8","status":"FAILED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"23","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"23","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"28","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"25","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"26","timestamp":{"nanos":20000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"26","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"27","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"16","timestamp":{"nanos":25000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json b/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json new file mode 100644 index 00000000..8c4fb304 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json @@ -0,0 +1,221 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 1, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 1, + "AMBIGUOUS" : 0, + "FAILED" : 1 + }, + "countTestCasesStarted" : 3, + "findAllPickles" : 3, + "findAllPickleSteps" : 3, + "findAllTestCaseStarted" : 3, + "findAllTestSteps" : 9, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "Hooks", + [ + "29", + "30", + "31" + ] + ] + ], + "findFeatureBy" : [ + "Hooks", + "Hooks", + "Hooks" + ], + "findHookBy" : [ + "0", + "3", + "0", + "3", + "0", + "3" + ], + "findLocationOf" : [ + { + "line" : 4, + "column" : 3 + }, + { + "line" : 7, + "column" : 3 + }, + { + "line" : 10, + "column" : 3 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + "PASSED", + "FAILED", + "UNDEFINED" + ], + "findNameOf" : { + "long" : [ + "Hooks - No tags and a passed step", + "Hooks - No tags and a failed step", + "Hooks - No tags and a undefined step" + ], + "excludeFeatureName" : [ + "No tags and a passed step", + "No tags and a failed step", + "No tags and a undefined step" + ], + "longPickleName" : [ + "Hooks - No tags and a passed step", + "Hooks - No tags and a failed step", + "Hooks - No tags and a undefined step" + ], + "short" : [ + "No tags and a passed step", + "No tags and a failed step", + "No tags and a undefined step" + ], + "shortPickleName" : [ + "No tags and a passed step", + "No tags and a failed step", + "No tags and a undefined step" + ] + }, + "findPickleBy" : [ + "No tags and a passed step", + "No tags and a failed step", + "No tags and a undefined step" + ], + "findPickleStepBy" : [ + "a step passes", + "a step fails", + "a step does not exist" + ], + "findStepBy" : [ + "a step passes", + "a step fails", + "a step does not exist" + ], + "findTestCaseBy" : [ + "20", + "24", + "28" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + }, + { + "seconds" : 0, + "nanos" : 7000000 + } + ], + "findTestCaseFinishedBy" : [ + "29", + "30", + "31" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 25000000 + }, + "findTestRunFinished" : { + "success" : false, + "timestamp" : { + "seconds" : 0, + "nanos" : 25000000 + }, + "testRunStartedId" : "16" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "16" + }, + "findTestStepByTestStepStarted" : [ + "17", + "18", + "19", + "21", + "22", + "23", + "25", + "26", + "27" + ], + "findTestStepByTestStepFinished" : [ + "17", + "18", + "19", + "21", + "22", + "23", + "25", + "26", + "27" + ], + "findTestStepsFinishedBy" : [ + [ + "17", + "18", + "19" + ], + [ + "21", + "22", + "23" + ], + [ + "25", + "26", + "27" + ] + ], + "findTestStepFinishedAndTestStepBy" : [ + [ + "17", + "17" + ], + [ + "18", + "18" + ], + [ + "19", + "19" + ], + [ + "21", + "21" + ], + [ + "22", + "22" + ], + [ + "23", + "23" + ], + [ + "25", + "25" + ], + [ + "26", + "26" + ], + [ + "27", + "27" + ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson b/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson new file mode 100644 index 00000000..d7d088f9 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson @@ -0,0 +1,35 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"# Feature: Cheese\n\nThis table is not picked up by Gherkin (not indented 2+ spaces)\n\n| foo | bar |\n| --- | --- |\n| boz | boo |\n\n\n## Rule: Nom nom nom\n\nI love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese.\n\n### Scenario Outline: Ylajali!\n\n* Given some TypeScript code:\n ```typescript\n type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'\n ```\n* And some classic Gherkin:\n ```gherkin\n Given there are 24 apples in Mary's basket\n ```\n* When we use a data table and attach something and then \n | name | age |\n | ---- | --: |\n | Bill | 3 |\n | Jane | 6 |\n | Isla | 5 |\n* Then this might or might not run\n\n#### Examples: because we need more tables\n\nThis table is indented 2 spaces, so Gherkin will pick it up\n\n | what |\n | ---- |\n | fail |\n | pass |\n\nAnd oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent:\n\n| cheese |\n| -------- |\n| gouda |\n| gamalost |\n","mediaType":"text/x.cucumber.gherkin+markdown","uri":"samples/markdown/markdown.feature.md"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"15","keyword":"Examples","location":{"column":6,"line":32},"name":"because we need more tables","tableBody":[{"cells":[{"location":{"column":5,"line":38},"value":"fail"}],"id":"13","location":{"column":3,"line":38}},{"cells":[{"location":{"column":5,"line":39},"value":"pass"}],"id":"14","location":{"column":3,"line":39}}],"tableHeader":{"cells":[{"location":{"column":5,"line":36},"value":"what"}],"id":"12","location":{"column":3,"line":36}},"tags":[]}],"id":"16","keyword":"Scenario Outline","location":{"column":5,"line":14},"name":"Ylajali!","steps":[{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","delimiter":"```","location":{"column":3,"line":17},"mediaType":"typescript"},"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":3,"line":16},"text":"some TypeScript code:"},{"docString":{"content":"Given there are 24 apples in Mary's basket","delimiter":"```","location":{"column":3,"line":21},"mediaType":"gherkin"},"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":3,"line":20},"text":"some classic Gherkin:"},{"dataTable":{"location":{"column":3,"line":25},"rows":[{"cells":[{"location":{"column":5,"line":25},"value":"name"},{"location":{"column":12,"line":25},"value":"age"}],"id":"6","location":{"column":3,"line":25}},{"cells":[{"location":{"column":5,"line":27},"value":"Bill"},{"location":{"column":14,"line":27},"value":"3"}],"id":"7","location":{"column":3,"line":27}},{"cells":[{"location":{"column":5,"line":28},"value":"Jane"},{"location":{"column":14,"line":28},"value":"6"}],"id":"8","location":{"column":3,"line":28}},{"cells":[{"location":{"column":5,"line":29},"value":"Isla"},{"location":{"column":14,"line":29},"value":"5"}],"id":"9","location":{"column":3,"line":29}}]},"id":"10","keyword":"When ","keywordType":"Action","location":{"column":3,"line":24},"text":"we use a data table and attach something and then "},{"id":"11","keyword":"Then ","keywordType":"Outcome","location":{"column":3,"line":30},"text":"this might or might not run"}],"tags":[]}}],"description":"","id":"17","keyword":"Rule","location":{"column":4,"line":10},"name":"Nom nom nom","tags":[]}}],"description":"","keyword":"Feature","language":"en","location":{"column":3,"line":1},"name":"Cheese","tags":[]},"uri":"samples/markdown/markdown.feature.md"}} +{"pickle":{"astNodeIds":["16","13"],"id":"22","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","13"],"id":"18","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","13"],"id":"19","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","13"],"id":"20","text":"we use a data table and attach something and then fail","type":"Action"},{"astNodeIds":["11","13"],"id":"21","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} +{"pickle":{"astNodeIds":["16","14"],"id":"27","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","14"],"id":"23","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","14"],"id":"24","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","14"],"id":"25","text":"we use a data table and attach something and then pass","type":"Action"},{"astNodeIds":["11","14"],"id":"26","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} +{"stepDefinition":{"id":"0","pattern":{"source":"some TypeScript code:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"some classic Gherkin:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"we use a data table and attach something and then {word}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"this might or might not run","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"testRunStarted":{"id":"28","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"33","pickleId":"22","testRunStartedId":"28","testSteps":[{"id":"29","pickleStepId":"18","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"30","pickleStepId":"19","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"31","pickleStepId":"20","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"fail"},"parameterTypeName":"word"}]}]},{"id":"32","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"38","pickleId":"27","testRunStartedId":"28","testSteps":[{"id":"34","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"35","pickleStepId":"24","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"36","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"pass"},"parameterTypeName":"word"}]}]},{"id":"37","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"39","testCaseId":"33","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"29","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"30","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"31","timestamp":{"nanos":6000000,"seconds":0}}} +{"attachment":{"body":"We are logging some plain text (fail)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"39","testStepId":"31"}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"You asked me to fail","type":"Error"},"message":"You asked me to fail\nsamples/markdown/markdown.feature.md:24\nsamples/markdown/markdown.feature.md:38","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"32","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"32","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"40","testCaseId":"38","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"34","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"35","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"36","timestamp":{"nanos":16000000,"seconds":0}}} +{"attachment":{"body":"We are logging some plain text (pass)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"40","testStepId":"36"}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"37","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"28","timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson b/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson new file mode 100644 index 00000000..6d974e09 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: minimal\n \n Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list\n \n Scenario: cukes\n Given I have 42 cukes in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/minimal/minimal.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":9},"name":"cukes","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"I have 42 cukes in my belly"}],"tags":[]}}],"description":" Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"minimal","tags":[]},"uri":"samples/minimal/minimal.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cukes","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 cukes in my belly","type":"Context"}],"tags":[],"uri":"samples/minimal/minimal.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} cukes in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/minimal/minimal.feature.ts"}}} +{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json b/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json new file mode 100644 index 00000000..c4892efa --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json @@ -0,0 +1,111 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 1, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 0, + "AMBIGUOUS" : 0, + "FAILED" : 0 + }, + "countTestCasesStarted" : 1, + "findAllPickles" : 1, + "findAllPickleSteps" : 1, + "findAllTestCaseStarted" : 1, + "findAllTestSteps" : 1, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "minimal", + [ + "8" + ] + ] + ], + "findFeatureBy" : [ + "minimal" + ], + "findLocationOf" : [ + { + "line" : 9, + "column" : 3 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + "PASSED" + ], + "findNameOf" : { + "long" : [ + "minimal - cukes" + ], + "excludeFeatureName" : [ + "cukes" + ], + "longPickleName" : [ + "minimal - cukes" + ], + "short" : [ + "cukes" + ], + "shortPickleName" : [ + "cukes" + ] + }, + "findPickleBy" : [ + "cukes" + ], + "findPickleStepBy" : [ + "I have 42 cukes in my belly" + ], + "findStepBy" : [ + "I have 42 cukes in my belly" + ], + "findTestCaseBy" : [ + "7" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 3000000 + } + ], + "findTestCaseFinishedBy" : [ + "8" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 5000000 + }, + "findTestRunFinished" : { + "success" : true, + "timestamp" : { + "seconds" : 0, + "nanos" : 5000000 + }, + "testRunStartedId" : "5" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "5" + }, + "findTestStepByTestStepStarted" : [ + "6" + ], + "findTestStepByTestStepFinished" : [ + "6" + ], + "findTestStepsFinishedBy" : [ + [ + "6" + ] + ], + "findTestStepFinishedAndTestStepBy" : [ + [ + "6", + "6" + ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson b/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson new file mode 100644 index 00000000..f538d6f4 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson @@ -0,0 +1,13 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Parameter Types\n Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions.\n\n This lets you define a precise domain-specific vocabulary which can be used to\n generate a glossary with examples taken from your scenarios.\n\n Parameter types also enable you to transform strings and tables into different types.\n\n Scenario: Flight transformer\n Given LHR-CDG has been delayed\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/parameter-types/parameter-types.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":10},"name":"Flight transformer","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"LHR-CDG has been delayed"}],"tags":[]}}],"description":" Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions.\n\n This lets you define a precise domain-specific vocabulary which can be used to\n generate a glossary with examples taken from your scenarios.\n\n Parameter types also enable you to transform strings and tables into different types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/parameter-types/parameter-types.feature"}} +{"pickle":{"astNodeIds":["3"],"id":"5","language":"en","name":"Flight transformer","steps":[{"astNodeIds":["2"],"id":"4","text":"LHR-CDG has been delayed","type":"Context"}],"tags":[],"uri":"samples/parameter-types/parameter-types.feature"}} +{"parameterType":{"id":"0","name":"flight","preferForRegularExpressionMatch":false,"regularExpressions":["([A-Z]{3})-([A-Z]{3})"],"sourceReference":{"location":{"line":8},"uri":"samples/parameter-types/parameter-types.feature.ts"},"useForSnippets":true}} +{"stepDefinition":{"id":"1","pattern":{"source":"{flight} has been delayed","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/parameter-types/parameter-types.feature.ts"}}} +{"testRunStarted":{"id":"6","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"8","pickleId":"5","testRunStartedId":"6","testSteps":[{"id":"7","pickleStepId":"4","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[],"start":0,"value":"LHR"},{"children":[],"start":4,"value":"CDG"}],"start":0,"value":"LHR-CDG"},"parameterTypeName":"flight"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"9","testCaseId":"8","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"9","testStepId":"7","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"9","testStepId":"7","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"9","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"6","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/pending.feature.ndjson b/dotnet/Query/QueryTest/Resources/pending.feature.ndjson new file mode 100644 index 00000000..5ece61bc --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/pending.feature.ndjson @@ -0,0 +1,30 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Pending steps\n During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.\n\n Scenario: Unimplemented step signals pending status\n Given an unimplemented pending step\n\n Scenario: Steps before unimplemented steps are executed\n Given an implemented non-pending step\n And an unimplemented pending step\n\n Scenario: Steps after unimplemented steps are skipped\n Given an unimplemented pending step\n And an implemented step that is skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/pending/pending.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":9},"name":"Unimplemented step signals pending status","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"an unimplemented pending step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":12},"name":"Steps before unimplemented steps are executed","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":13},"text":"an implemented non-pending step"},{"id":"6","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":14},"text":"an unimplemented pending step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":16},"name":"Steps after unimplemented steps are skipped","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":17},"text":"an unimplemented pending step"},{"id":"9","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":18},"text":"an implemented step that is skipped"}],"tags":[]}}],"description":" During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Pending steps","tags":[]},"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["4"],"id":"12","language":"en","name":"Unimplemented step signals pending status","steps":[{"astNodeIds":["3"],"id":"11","text":"an unimplemented pending step","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"Steps before unimplemented steps are executed","steps":[{"astNodeIds":["5"],"id":"13","text":"an implemented non-pending step","type":"Context"},{"astNodeIds":["6"],"id":"14","text":"an unimplemented pending step","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"18","language":"en","name":"Steps after unimplemented steps are skipped","steps":[{"astNodeIds":["8"],"id":"16","text":"an unimplemented pending step","type":"Context"},{"astNodeIds":["9"],"id":"17","text":"an implemented step that is skipped","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"an implemented non-pending step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/pending/pending.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"an implemented step that is skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/pending/pending.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"an unimplemented pending step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/pending/pending.feature.ts"}}} +{"testRunStarted":{"id":"19","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"21","pickleId":"12","testRunStartedId":"19","testSteps":[{"id":"20","pickleStepId":"11","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"24","pickleId":"15","testRunStartedId":"19","testSteps":[{"id":"22","pickleStepId":"13","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"23","pickleStepId":"14","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"27","pickleId":"18","testRunStartedId":"19","testSteps":[{"id":"25","pickleStepId":"16","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"26","pickleStepId":"17","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"21","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"20","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"20","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"24","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"22","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"23","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"23","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"27","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"25","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"26","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"26","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"19","timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/retry.feature.ndjson b/dotnet/Query/QueryTest/Resources/retry.feature.ndjson new file mode 100644 index 00000000..4143f1d2 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/retry.feature.ndjson @@ -0,0 +1,59 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Retry\n Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED won't trigger a retry, as they are not\n going to pass however many times we attempt them.\n\n Scenario: Test cases that pass aren't retried\n Given a step that always passes\n\n Scenario: Test cases that fail are retried if within the --retry limit\n Given a step that passes the second time\n\n Scenario: Test cases that fail will continue to retry up to the --retry limit\n Given a step that passes the third time\n\n Scenario: Test cases won't retry after failing more than the --retry limit\n Given a step that always fails\n\n Scenario: Test cases won't retry when the status is UNDEFINED\n Given a non-existent step\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/retry/retry.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":8},"name":"Test cases that pass aren't retried","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"a step that always passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":11},"name":"Test cases that fail are retried if within the --retry limit","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"a step that passes the second time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":14},"name":"Test cases that fail will continue to retry up to the --retry limit","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":15},"text":"a step that passes the third time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":17},"name":"Test cases won't retry after failing more than the --retry limit","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that always fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":20},"name":"Test cases won't retry when the status is UNDEFINED","steps":[{"id":"12","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":21},"text":"a non-existent step"}],"tags":[]}}],"description":" Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED won't trigger a retry, as they are not\n going to pass however many times we attempt them.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Retry","tags":[]},"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["5"],"id":"15","language":"en","name":"Test cases that pass aren't retried","steps":[{"astNodeIds":["4"],"id":"14","text":"a step that always passes","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"17","language":"en","name":"Test cases that fail are retried if within the --retry limit","steps":[{"astNodeIds":["6"],"id":"16","text":"a step that passes the second time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"19","language":"en","name":"Test cases that fail will continue to retry up to the --retry limit","steps":[{"astNodeIds":["8"],"id":"18","text":"a step that passes the third time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["11"],"id":"21","language":"en","name":"Test cases won't retry after failing more than the --retry limit","steps":[{"astNodeIds":["10"],"id":"20","text":"a step that always fails","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["13"],"id":"23","language":"en","name":"Test cases won't retry when the status is UNDEFINED","steps":[{"astNodeIds":["12"],"id":"22","text":"a non-existent step","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"a step that always passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that passes the second time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step that passes the third time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"a step that always fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/retry/retry.feature.ts"}}} +{"testRunStarted":{"id":"24","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"26","pickleId":"15","testRunStartedId":"24","testSteps":[{"id":"25","pickleStepId":"14","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"28","pickleId":"17","testRunStartedId":"24","testSteps":[{"id":"27","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"30","pickleId":"19","testRunStartedId":"24","testSteps":[{"id":"29","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"32","pickleId":"21","testRunStartedId":"24","testSteps":[{"id":"31","pickleStepId":"20","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"34","pickleId":"23","testRunStartedId":"24","testSteps":[{"id":"33","pickleStepId":"22","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCaseStarted":{"attempt":0,"id":"35","testCaseId":"26","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"35","testStepId":"25","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"35","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"35","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"36","testCaseId":"28","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"36","testStepId":"27","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"36","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:12","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"36","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"37","testCaseId":"28","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"37","testStepId":"27","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"37","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"37","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"38","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"29","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:15","status":"FAILED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"39","testCaseId":"30","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"29","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:15","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":2,"id":"40","testCaseId":"30","timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"29","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"41","testCaseId":"32","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"41","testStepId":"31","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"41","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"41","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"42","testCaseId":"32","timestamp":{"nanos":29000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"42","testStepId":"31","timestamp":{"nanos":30000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"42","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"42","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":2,"id":"43","testCaseId":"32","timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"43","testStepId":"31","timestamp":{"nanos":34000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"43","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"43","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"44","testCaseId":"34","timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"44","testStepId":"33","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"44","testStepId":"33","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"44","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"24","timestamp":{"nanos":41000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/rules.feature.ndjson b/dotnet/Query/QueryTest/Resources/rules.feature.ndjson new file mode 100644 index 00000000..81ac0e1c --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/rules.feature.ndjson @@ -0,0 +1,47 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Usage of a `Rule`\n You can place scenarios inside rules. This makes it possible to structure Gherkin documents\n in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n\n You can also use the Examples synonym for Scenario to make them even similar.\n\n Rule: A sale cannot happen if the customer does not have enough money\n # Unhappy path\n Example: Not enough money\n Given the customer has 100 cents\n And there are chocolate bars in stock\n When the customer tries to buy a 125 cent chocolate bar\n Then the sale should not happen\n\n # Happy path\n Example: Enough money\n Given the customer has 100 cents\n And there are chocolate bars in stock\n When the customer tries to buy a 75 cent chocolate bar\n Then the sale should happen\n\n @some-tag\n Rule: a sale cannot happen if there is no stock\n # Unhappy path\n Example: No chocolates left\n Given the customer has 100 cents\n And there are no chocolate bars in stock\n When the customer tries to buy a 1 cent chocolate bar\n Then the sale should not happen\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/rules/rules.feature"}} +{"gherkinDocument":{"comments":[{"location":{"column":1,"line":8},"text":" # Unhappy path"},{"location":{"column":1,"line":15},"text":" # Happy path"},{"location":{"column":1,"line":24},"text":" # Unhappy path"}],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"10","keyword":"Example","location":{"column":5,"line":9},"name":"Not enough money","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":10},"text":"the customer has 100 cents"},{"id":"7","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":11},"text":"there are chocolate bars in stock"},{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":7,"line":12},"text":"the customer tries to buy a 125 cent chocolate bar"},{"id":"9","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":13},"text":"the sale should not happen"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Example","location":{"column":5,"line":16},"name":"Enough money","steps":[{"id":"11","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":17},"text":"the customer has 100 cents"},{"id":"12","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":18},"text":"there are chocolate bars in stock"},{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":7,"line":19},"text":"the customer tries to buy a 75 cent chocolate bar"},{"id":"14","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":20},"text":"the sale should happen"}],"tags":[]}}],"description":"","id":"16","keyword":"Rule","location":{"column":3,"line":7},"name":"A sale cannot happen if the customer does not have enough money","tags":[]}},{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"21","keyword":"Example","location":{"column":5,"line":25},"name":"No chocolates left","steps":[{"id":"17","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":26},"text":"the customer has 100 cents"},{"id":"18","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":27},"text":"there are no chocolate bars in stock"},{"id":"19","keyword":"When ","keywordType":"Action","location":{"column":7,"line":28},"text":"the customer tries to buy a 1 cent chocolate bar"},{"id":"20","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":29},"text":"the sale should not happen"}],"tags":[]}}],"description":"","id":"23","keyword":"Rule","location":{"column":3,"line":23},"name":"a sale cannot happen if there is no stock","tags":[{"id":"22","location":{"column":3,"line":22},"name":"@some-tag"}]}}],"description":" You can place scenarios inside rules. This makes it possible to structure Gherkin documents\n in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n\n You can also use the Examples synonym for Scenario to make them even similar.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Usage of a `Rule`","tags":[]},"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"28","language":"en","name":"Not enough money","steps":[{"astNodeIds":["6"],"id":"24","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["7"],"id":"25","text":"there are chocolate bars in stock","type":"Context"},{"astNodeIds":["8"],"id":"26","text":"the customer tries to buy a 125 cent chocolate bar","type":"Action"},{"astNodeIds":["9"],"id":"27","text":"the sale should not happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["15"],"id":"33","language":"en","name":"Enough money","steps":[{"astNodeIds":["11"],"id":"29","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["12"],"id":"30","text":"there are chocolate bars in stock","type":"Context"},{"astNodeIds":["13"],"id":"31","text":"the customer tries to buy a 75 cent chocolate bar","type":"Action"},{"astNodeIds":["14"],"id":"32","text":"the sale should happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["21"],"id":"38","language":"en","name":"No chocolates left","steps":[{"astNodeIds":["17"],"id":"34","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["18"],"id":"35","text":"there are no chocolate bars in stock","type":"Context"},{"astNodeIds":["19"],"id":"36","text":"the customer tries to buy a 1 cent chocolate bar","type":"Action"},{"astNodeIds":["20"],"id":"37","text":"the sale should not happen","type":"Outcome"}],"tags":[{"astNodeId":"22","name":"@some-tag"}],"uri":"samples/rules/rules.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"the customer has {int} cents","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"there are chocolate bars in stock","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"there are no chocolate bars in stock","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"the customer tries to buy a {int} cent chocolate bar","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"4","pattern":{"source":"the sale should not happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"5","pattern":{"source":"the sale should happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":26},"uri":"samples/rules/rules.feature.ts"}}} +{"testRunStarted":{"id":"39","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"44","pickleId":"28","testRunStartedId":"39","testSteps":[{"id":"40","pickleStepId":"24","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"41","pickleStepId":"25","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"42","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"125"},"parameterTypeName":"int"}]}]},{"id":"43","pickleStepId":"27","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"49","pickleId":"33","testRunStartedId":"39","testSteps":[{"id":"45","pickleStepId":"29","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"46","pickleStepId":"30","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"47","pickleStepId":"31","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"75"},"parameterTypeName":"int"}]}]},{"id":"48","pickleStepId":"32","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"54","pickleId":"38","testRunStartedId":"39","testSteps":[{"id":"50","pickleStepId":"34","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"51","pickleStepId":"35","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"52","pickleStepId":"36","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"53","pickleStepId":"37","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"55","testCaseId":"44","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"55","testStepId":"40","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"55","testStepId":"40","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"55","testStepId":"41","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"55","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"55","testStepId":"42","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"55","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"55","testStepId":"43","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"55","testStepId":"43","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"55","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"56","testCaseId":"49","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"45","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"46","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"47","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"48","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"56","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"57","testCaseId":"54","timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"50","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"51","timestamp":{"nanos":24000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"52","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"53","timestamp":{"nanos":28000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"53","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"57","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"39","timestamp":{"nanos":31000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json b/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json new file mode 100644 index 00000000..a49b48ed --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json @@ -0,0 +1,252 @@ +{ + "countMostSevereTestStepResultStatus" : { + "UNKNOWN" : 0, + "PASSED" : 3, + "SKIPPED" : 0, + "PENDING" : 0, + "UNDEFINED" : 0, + "AMBIGUOUS" : 0, + "FAILED" : 0 + }, + "countTestCasesStarted" : 3, + "findAllPickles" : 3, + "findAllPickleSteps" : 12, + "findAllTestCaseStarted" : 3, + "findAllTestSteps" : 12, + "findAllTestCaseStartedGroupedByFeature" : [ + [ + "Usage of a `Rule`", + [ + "55", + "56", + "57" + ] + ] + ], + "findFeatureBy" : [ + "Usage of a `Rule`", + "Usage of a `Rule`", + "Usage of a `Rule`" + ], + "findLocationOf" : [ + { + "line" : 9, + "column" : 5 + }, + { + "line" : 16, + "column" : 5 + }, + { + "line" : 25, + "column" : 5 + } + ], + "findMeta" : "fake-cucumber", + "findMostSevereTestStepResultBy" : [ + "PASSED", + "PASSED", + "PASSED" + ], + "findNameOf" : { + "long" : [ + "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Not enough money", + "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Enough money", + "Usage of a `Rule` - a sale cannot happen if there is no stock - No chocolates left" + ], + "excludeFeatureName" : [ + "A sale cannot happen if the customer does not have enough money - Not enough money", + "A sale cannot happen if the customer does not have enough money - Enough money", + "a sale cannot happen if there is no stock - No chocolates left" + ], + "longPickleName" : [ + "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Not enough money", + "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Enough money", + "Usage of a `Rule` - a sale cannot happen if there is no stock - No chocolates left" + ], + "short" : [ + "Not enough money", + "Enough money", + "No chocolates left" + ], + "shortPickleName" : [ + "Not enough money", + "Enough money", + "No chocolates left" + ] + }, + "findPickleBy" : [ + "Not enough money", + "Enough money", + "No chocolates left" + ], + "findPickleStepBy" : [ + "the customer has 100 cents", + "there are chocolate bars in stock", + "the customer tries to buy a 125 cent chocolate bar", + "the sale should not happen", + "the customer has 100 cents", + "there are chocolate bars in stock", + "the customer tries to buy a 75 cent chocolate bar", + "the sale should happen", + "the customer has 100 cents", + "there are no chocolate bars in stock", + "the customer tries to buy a 1 cent chocolate bar", + "the sale should not happen" + ], + "findStepBy" : [ + "the customer has 100 cents", + "there are chocolate bars in stock", + "the customer tries to buy a 125 cent chocolate bar", + "the sale should not happen", + "the customer has 100 cents", + "there are chocolate bars in stock", + "the customer tries to buy a 75 cent chocolate bar", + "the sale should happen", + "the customer has 100 cents", + "there are no chocolate bars in stock", + "the customer tries to buy a 1 cent chocolate bar", + "the sale should not happen" + ], + "findTestCaseBy" : [ + "44", + "49", + "54" + ], + "findTestCaseDurationBy" : [ + { + "seconds" : 0, + "nanos" : 9000000 + }, + { + "seconds" : 0, + "nanos" : 9000000 + }, + { + "seconds" : 0, + "nanos" : 9000000 + } + ], + "findTestCaseFinishedBy" : [ + "55", + "56", + "57" + ], + "findTestRunDuration" : { + "seconds" : 0, + "nanos" : 31000000 + }, + "findTestRunFinished" : { + "success" : true, + "timestamp" : { + "seconds" : 0, + "nanos" : 31000000 + }, + "testRunStartedId" : "39" + }, + "findTestRunStarted" : { + "timestamp" : { + "seconds" : 0, + "nanos" : 0 + }, + "id" : "39" + }, + "findTestStepByTestStepStarted" : [ + "40", + "41", + "42", + "43", + "45", + "46", + "47", + "48", + "50", + "51", + "52", + "53" + ], + "findTestStepByTestStepFinished" : [ + "40", + "41", + "42", + "43", + "45", + "46", + "47", + "48", + "50", + "51", + "52", + "53" + ], + "findTestStepsFinishedBy" : [ + [ + "40", + "41", + "42", + "43" + ], + [ + "45", + "46", + "47", + "48" + ], + [ + "50", + "51", + "52", + "53" + ] + ], + "findTestStepFinishedAndTestStepBy" : [ + [ + "40", + "40" + ], + [ + "41", + "41" + ], + [ + "42", + "42" + ], + [ + "43", + "43" + ], + [ + "45", + "45" + ], + [ + "46", + "46" + ], + [ + "47", + "47" + ], + [ + "48", + "48" + ], + [ + "50", + "50" + ], + [ + "51", + "51" + ], + [ + "52", + "52" + ], + [ + "53", + "53" + ] + ] +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson b/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson new file mode 100644 index 00000000..3b1808ba --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson @@ -0,0 +1,33 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Skipping scenarios\n\n Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by raising a particular kind of exception status (For example PENDING or SKIPPED).\n\n This can be useful in certain situations e.g. the current environment doesn't have\n the right conditions for running a particular scenario.\n\n @skip\n Scenario: Skipping from a Before hook\n Given a step that is skipped\n\n Scenario: Skipping from a step doesn't affect the previous steps\n Given a step that does not skip\n And I skip a step\n\n Scenario: Skipping from a step causes the rest of the scenario to be skipped\n Given I skip a step\n And a step that is skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/skipped/skipped.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Skipping from a Before hook","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that is skipped"}],"tags":[{"id":"5","location":{"column":3,"line":9},"name":"@skip"}]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":13},"name":"Skipping from a step doesn't affect the previous steps","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"a step that does not skip"},{"id":"8","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":15},"text":"I skip a step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":17},"name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"I skip a step"},{"id":"11","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":19},"text":"a step that is skipped"}],"tags":[]}}],"description":" Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by raising a particular kind of exception status (For example PENDING or SKIPPED).\n\n This can be useful in certain situations e.g. the current environment doesn't have\n the right conditions for running a particular scenario.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Skipping scenarios","tags":[]},"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Skipping from a Before hook","steps":[{"astNodeIds":["4"],"id":"13","text":"a step that is skipped","type":"Context"}],"tags":[{"astNodeId":"5","name":"@skip"}],"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Skipping from a step doesn't affect the previous steps","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that does not skip","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"I skip a step","type":"Context"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["12"],"id":"20","language":"en","name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"astNodeIds":["10"],"id":"18","text":"I skip a step","type":"Context"},{"astNodeIds":["11"],"id":"19","text":"a step that is skipped","type":"Context"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that does not skip","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/skipped/skipped.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step that is skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/skipped/skipped.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"I skip a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":15},"uri":"samples/skipped/skipped.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/skipped/skipped.feature.ts"},"tagExpression":"@skip","type":"BEFORE_TEST_CASE"}} +{"testRunStarted":{"id":"21","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"24","pickleId":"14","testRunStartedId":"21","testSteps":[{"hookId":"0","id":"22"},{"id":"23","pickleStepId":"13","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"27","pickleId":"17","testRunStartedId":"21","testSteps":[{"id":"25","pickleStepId":"15","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"26","pickleStepId":"16","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"30","pickleId":"20","testRunStartedId":"21","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"29","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"24","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"22","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"23","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"23","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"27","timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"25","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"26","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"33","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"33","testStepId":"28","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"33","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"33","testStepId":"29","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"33","testStepId":"29","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"33","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"testRunStartedId":"21","timestamp":{"nanos":19000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson b/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson new file mode 100644 index 00000000..49d10f54 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Stack traces\n Stack traces can help you diagnose the source of a bug.\n Cucumber provides helpful stack traces that includes the stack frames from the\n Gherkin document and remove uninteresting frames by default\n\n The first line of the stack trace will contain a reference to the feature file.\n\n Scenario: A failing step\n When a step throws an exception\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/stack-traces/stack-traces.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":8},"name":"A failing step","steps":[{"id":"1","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"a step throws an exception"}],"tags":[]}}],"description":" Stack traces can help you diagnose the source of a bug.\n Cucumber provides helpful stack traces that includes the stack frames from the\n Gherkin document and remove uninteresting frames by default\n\n The first line of the stack trace will contain a reference to the feature file.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Stack traces","tags":[]},"uri":"samples/stack-traces/stack-traces.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"A failing step","steps":[{"astNodeIds":["1"],"id":"3","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/stack-traces/stack-traces.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/stack-traces/stack-traces.feature.ts"}}} +{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"BOOM","type":"Error"},"message":"BOOM\nsamples/stack-traces/stack-traces.feature:9","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson b/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson new file mode 100644 index 00000000..aafa4d47 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson @@ -0,0 +1,29 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Undefined steps\n\n At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario is not able to run and so the step status\n will be UNDEFINED, with subsequent steps being SKIPPED and the overall result will be FAILURE\n\n Scenario: An undefined step causes a failure\n Given a step that is yet to be defined\n\n Scenario: Steps before undefined steps are executed\n Given an implemented step\n And a step that is yet to be defined\n\n Scenario: Steps after undefined steps are skipped\n Given a step that is yet to be defined\n And a step that will be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/undefined/undefined.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":7},"name":"An undefined step causes a failure","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":8},"text":"a step that is yet to be defined"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Steps before undefined steps are executed","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"an implemented step"},{"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":12},"text":"a step that is yet to be defined"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":14},"name":"Steps after undefined steps are skipped","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":15},"text":"a step that is yet to be defined"},{"id":"8","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":16},"text":"a step that will be skipped"}],"tags":[]}}],"description":" At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario is not able to run and so the step status\n will be UNDEFINED, with subsequent steps being SKIPPED and the overall result will be FAILURE","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Undefined steps","tags":[]},"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["3"],"id":"11","language":"en","name":"An undefined step causes a failure","steps":[{"astNodeIds":["2"],"id":"10","text":"a step that is yet to be defined","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Steps before undefined steps are executed","steps":[{"astNodeIds":["4"],"id":"12","text":"an implemented step","type":"Context"},{"astNodeIds":["5"],"id":"13","text":"a step that is yet to be defined","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Steps after undefined steps are skipped","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that is yet to be defined","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that will be skipped","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/undefined/undefined.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that will be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/undefined/undefined.feature.ts"}}} +{"testRunStarted":{"id":"18","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"20","pickleId":"11","testRunStartedId":"18","testSteps":[{"id":"19","pickleStepId":"10","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCase":{"id":"23","pickleId":"14","testRunStartedId":"18","testSteps":[{"id":"21","pickleStepId":"12","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"22","pickleStepId":"13","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCase":{"id":"26","pickleId":"17","testRunStartedId":"18","testSteps":[{"id":"24","pickleStepId":"15","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"25","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"27","testStepId":"19","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"27","testStepId":"19","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"23","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"21","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"22","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"26","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"24","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"24","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"25","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"25","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"18","timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson b/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson new file mode 100644 index 00000000..40f7ebd4 --- /dev/null +++ b/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} +{"source":{"data":"Feature: Parameter Types\n Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.\n\n Scenario: undefined parameter type\n Given CDG is closed because of a strike\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"1","keyword":"Scenario","location":{"column":3,"line":5},"name":"undefined parameter type","steps":[{"id":"0","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"CDG is closed because of a strike"}],"tags":[]}}],"description":" Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"pickle":{"astNodeIds":["1"],"id":"3","language":"en","name":"undefined parameter type","steps":[{"astNodeIds":["0"],"id":"2","text":"CDG is closed because of a strike","type":"Context"}],"tags":[],"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"undefinedParameterType":{"expression":"{airport} is closed because of a strike","name":"airport"}} +{"testRunStarted":{"id":"4","timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"6","pickleId":"3","testRunStartedId":"4","testSteps":[{"id":"5","pickleStepId":"2","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"testRunStartedId":"4","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/TimestampComparerTest.cs b/dotnet/Query/QueryTest/TimestampComparerTest.cs new file mode 100644 index 00000000..ce45b7f3 --- /dev/null +++ b/dotnet/Query/QueryTest/TimestampComparerTest.cs @@ -0,0 +1,46 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Io.Cucumber.Query; +using Io.Cucumber.Messages.Types; + +namespace QueryTest +{ + [TestClass] + public class TimestampComparerTest + { + private readonly TimestampComparer comparer = new TimestampComparer(); + + [TestMethod] + public void Identity() + { + var a = new Timestamp(1L, 1L); + var b = new Timestamp(1L, 1L); + + Assert.AreEqual(0, comparer.Compare(a, b)); + Assert.AreEqual(0, comparer.Compare(b, a)); + } + + [TestMethod] + public void OnSeconds() + { + var a = new Timestamp(1L, 1L); + var b = new Timestamp(2L, 2L); + Assert.AreEqual(-1, comparer.Compare(a, b)); + Assert.AreEqual(1, comparer.Compare(b, a)); + } + + [TestMethod] + public void OnNanoSeconds() + { + var a = new Timestamp(1L, 1L); + var b1 = new Timestamp(1L, 0L); + var b2 = new Timestamp(1L, 2L); + + Assert.AreEqual(1, comparer.Compare(a, b1)); + Assert.AreEqual(-1, comparer.Compare(b1, a)); + + Assert.AreEqual(-1, comparer.Compare(a, b2)); + Assert.AreEqual(1, comparer.Compare(b2, a)); + } + } +} From 8360374dd0eff0c2e82000d1d429255eac482dbc Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 8 Jul 2025 17:41:08 -0500 Subject: [PATCH 4/8] First cut at fully passing tests. --- dotnet/Query/Query/PortingTemplate.cs | 11 ---- dotnet/Query/Query/Query.cs | 63 +++++++++---------- .../QueryTest/CucumberMessageEnumConverter.cs | 42 +++++++++++++ dotnet/Query/QueryTest/NdjsonSerializer.cs | 60 ++++++++++++++++++ dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 56 ++++++++++++++--- dotnet/Query/QueryTest/QueryTest.csproj | 2 +- .../TestRunFinishedOrderedConverter.cs | 35 +++++++++++ .../TestRunStartedOrderedConverter.cs | 24 +++++++ .../QueryTest/TimestampOrderedConverter.cs | 20 ++++++ 9 files changed, 257 insertions(+), 56 deletions(-) delete mode 100644 dotnet/Query/Query/PortingTemplate.cs create mode 100644 dotnet/Query/QueryTest/CucumberMessageEnumConverter.cs create mode 100644 dotnet/Query/QueryTest/NdjsonSerializer.cs create mode 100644 dotnet/Query/QueryTest/TestRunFinishedOrderedConverter.cs create mode 100644 dotnet/Query/QueryTest/TestRunStartedOrderedConverter.cs create mode 100644 dotnet/Query/QueryTest/TimestampOrderedConverter.cs diff --git a/dotnet/Query/Query/PortingTemplate.cs b/dotnet/Query/Query/PortingTemplate.cs deleted file mode 100644 index 8d9aa534..00000000 --- a/dotnet/Query/Query/PortingTemplate.cs +++ /dev/null @@ -1,11 +0,0 @@ -// File-scoped namespace for all ported classes -namespace Io.Cucumber.Query; - -using System; -using System.Collections.Generic; -using Io.Cucumber.Messages.Types; - -// This file will be used as a template for porting Java classes to C# -// Each Java class will be ported as a public C# class in this namespace -// Nullable types and [Required] attributes will be used as specified -// Implementation will follow idiomatic C# and .NET Standard 2.0 compatibility diff --git a/dotnet/Query/Query/Query.cs b/dotnet/Query/Query/Query.cs index 7210cfaa..699d1911 100644 --- a/dotnet/Query/Query/Query.cs +++ b/dotnet/Query/Query/Query.cs @@ -11,15 +11,7 @@ namespace Io.Cucumber.Query; // Ported from io.cucumber.query.Query (Java) public class Query { - // Internal state for queries - private readonly List _gherkinDocuments = new(); - private readonly List _pickles = new(); - private readonly List _testCases = new(); - private readonly List _testStepFinished = new(); - private readonly List _testCaseFinished = new(); - private readonly List _testCaseStarted = new(); - - // Additional internal state for queries (to be expanded as needed) + private readonly ConcurrentDictionary _testCaseStartedById = new(); private readonly ConcurrentDictionary _testCaseFinishedByTestCaseStartedId = new(); private readonly ConcurrentDictionary> _testStepsFinishedByTestCaseStartedId = new(); @@ -38,23 +30,26 @@ public class Query public Query() { } - // Property getters for counts public int MostSevereTestStepResultStatusCount => CountMostSevereTestStepResultStatus().Count; public int TestCasesStartedCount => FindAllTestCaseStarted().Count; - // Ported methods (incrementally implemented) public IDictionary CountMostSevereTestStepResultStatus() { var statusCounts = new Dictionary(); + // Initialize with zero for each possible TestStepResultStatus + foreach (TestStepResultStatus status in Enum.GetValues(typeof(TestStepResultStatus))) + { + statusCounts[status] = 0; + } foreach (var testCaseStarted in FindAllTestCaseStarted()) { var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); if (finishedSteps.Count == 0) continue; - // Find the most severe status (lowest enum value) + // Find the most severe status (largest enum value) var mostSevere = finishedSteps .Select(f => f.TestStepResult.Status) - .Min(); + .Max(); if (statusCounts.ContainsKey(mostSevere)) statusCounts[mostSevere]++; else @@ -94,18 +89,7 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public Feature? FindFeatureBy(TestCaseStarted testCaseStarted) { - // Find the TestCase for this TestCaseStarted - if (_testCaseById.TryGetValue(testCaseStarted.TestCaseId, out var testCase)) - { - // Find the Pickle for this TestCase - if (_pickleById.TryGetValue(testCase.PickleId, out var pickle)) - { - // Find the GherkinDocument for this Pickle - var doc = _gherkinDocuments.FirstOrDefault(d => d.Uri == pickle.Uri); - return doc?.Feature; - } - } - return null; + return FindLineageBy(testCaseStarted)?.Feature; } public Hook? FindHookBy(TestStep testStep) @@ -278,10 +262,10 @@ public IList FindTestStepsFinishedBy(TestCaseStarted testCaseS var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); if (finishedSteps.Count == 0) return null; - // Find the TestStepFinished with the most severe status (lowest enum value) + // Find the TestStepFinished with the most severe status (highest enum value) var mostSevere = finishedSteps .OrderBy(f => f.TestStepResult.Status) - .FirstOrDefault(); + .LastOrDefault(); return mostSevere?.TestStepResult; } @@ -313,13 +297,11 @@ internal void UpdateHook(Hook hook) internal void UpdateTestCaseStarted(TestCaseStarted testCaseStarted) { _testCaseStartedById[testCaseStarted.Id] = testCaseStarted; - _testCaseStarted.Add(testCaseStarted); } internal void UpdateTestCase(TestCase testCase) { _testCaseById[testCase.Id] = testCase; - _testCases.Add(testCase); foreach (var testStep in testCase.TestSteps) { _testStepById[testStep.Id] = testStep; @@ -329,7 +311,6 @@ internal void UpdateTestCase(TestCase testCase) internal void UpdatePickle(Pickle pickle) { _pickleById[pickle.Id] = pickle; - _pickles.Add(pickle); foreach (var step in pickle.Steps) { _pickleStepById[step.Id] = step; @@ -338,12 +319,14 @@ internal void UpdatePickle(Pickle pickle) internal void UpdateGherkinDocument(GherkinDocument document) { - _gherkinDocuments.Add(document); + foreach (var lineage in Lineages.Of(document)) + { + _lineageById.TryAdd(lineage.Key, lineage.Value); + } if (document.Feature != null) { UpdateFeature(document.Feature); } - // Lineage population would go here if implemented } internal void UpdateFeature(Feature feature) @@ -389,13 +372,11 @@ internal void UpdateTestStepFinished(TestStepFinished testStepFinished) testStepFinished.TestCaseStartedId, _ => new List { testStepFinished }, (_, list) => { list.Add(testStepFinished); return list; }); - _testStepFinished.Add(testStepFinished); } internal void UpdateTestCaseFinished(TestCaseFinished testCaseFinished) { _testCaseFinishedByTestCaseStartedId[testCaseFinished.TestCaseStartedId] = testCaseFinished; - _testCaseFinished.Add(testCaseFinished); } internal void UpdateTestRunFinished(TestRunFinished testRunFinished) @@ -481,10 +462,22 @@ public void Update(Envelope envelope) public Lineage? FindLineageBy(Pickle pickle) { - _lineageById.TryGetValue(pickle, out var lineage); + var astNodeIds = pickle.AstNodeIds; + var lastAstNodeId = astNodeIds.LastOrDefault(); + _lineageById.TryGetValue(lastAstNodeId, out var lineage); return lineage; } + public Lineage? FindLineageBy(TestCaseStarted testCaseStarted) + { + var pickle = FindPickleBy(testCaseStarted); + if (pickle == null) + { + return null; + } + return FindLineageBy(pickle); + } + public string FindNameOf(GherkinDocument element, NamingStrategy namingStrategy) { if (element == null) return string.Empty; diff --git a/dotnet/Query/QueryTest/CucumberMessageEnumConverter.cs b/dotnet/Query/QueryTest/CucumberMessageEnumConverter.cs new file mode 100644 index 00000000..566b3764 --- /dev/null +++ b/dotnet/Query/QueryTest/CucumberMessageEnumConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace QueryTest +{ + internal class CucumberMessageEnumConverter : JsonConverter where T : struct, Enum + { + private readonly Dictionary _enumToString = new(); + private readonly Dictionary _stringToEnum = new(); + + protected internal CucumberMessageEnumConverter() + { + var type = typeof(T); + foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static)) + { +#pragma warning disable CS8605 // Unboxing a possibly null value. + var value = (T)field.GetValue(null); +#pragma warning restore CS8605 // Unboxing a possibly null value. + var attribute = field.GetCustomAttribute(); + var name = attribute?.Description ?? field.Name; + _enumToString[value] = name; + _stringToEnum[name] = value; + } + } + + public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var stringValue = reader.GetString(); + return _stringToEnum.TryGetValue(stringValue!, out var enumValue) ? enumValue : default; + } + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + writer.WriteStringValue(_enumToString.TryGetValue(value, out var stringValue) ? stringValue : value.ToString()); + } + } + +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/NdjsonSerializer.cs b/dotnet/Query/QueryTest/NdjsonSerializer.cs new file mode 100644 index 00000000..4d49a561 --- /dev/null +++ b/dotnet/Query/QueryTest/NdjsonSerializer.cs @@ -0,0 +1,60 @@ +using Io.Cucumber.Messages.Types; +using System; +using System.IO; +using System.Text.Json; + +namespace QueryTest +{ + /// + /// When using System.Text.Json to serialize a Cucumber Message Envelope, the following serialization options are used. + /// Consumers of Cucumber.Messages should use these options, or their serialization library's equivalent options. + /// These options should work with System.Text.Json v6 or above. + /// + public class NdjsonSerializer + { + private static readonly Lazy _jsonOptions = new(() => + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull; + options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping; + + return options; + }); + + private static JsonSerializerOptions JsonOptions + { + get + { + return _jsonOptions.Value; + } + } + + public static string Serialize(Envelope message) + { + return Serialize(message); + } + + internal static string Serialize(T message) + { + return JsonSerializer.Serialize(message, JsonOptions); + } + + public static Envelope Deserialize(string json) + { + return Deserialize(json); + } + + internal static T Deserialize(string json) + { + return JsonSerializer.Deserialize(json, JsonOptions)!; + } + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs index 7a09ac07..ec3add3b 100644 --- a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -11,6 +11,8 @@ using Io.Cucumber.Messages.Types; using Io.Cucumber.Query; using Microsoft.VisualStudio.TestTools.UnitTesting; +using FluentAssertions; +using System.Security.Cryptography; namespace QueryTest { @@ -46,7 +48,8 @@ public void Test(TestCase testCase) var actualJson = JsonNode.Parse(actual); var expectedJson = JsonNode.Parse(expected); - Assert.AreEqual(expectedJson.ToJsonString(), actualJson.ToJsonString()); + actualJson!.ToJsonString().Should().Be(expectedJson!.ToJsonString(), + $"Query results for {testCase.Name} do not match expected results."); } private static string WriteQueryResults(TestCase testCase) @@ -60,7 +63,7 @@ private static string WriteQueryResults(TestCase testCase) while ((line = reader.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) continue; - var envelope = JsonSerializer.Deserialize(line); + var envelope = NdjsonSerializer.Deserialize(line); query.Update(envelope); } @@ -68,8 +71,20 @@ private static string WriteQueryResults(TestCase testCase) var options = new JsonSerializerOptions { WriteIndented = true, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new CucumberMessageEnumConverter()); + options.Converters.Add(new TimestampOrderedConverter()); + options.Converters.Add(new TestRunStartedOrderedConverter()); + options.Converters.Add(new TestRunFinishedOrderedConverter()); + return JsonSerializer.Serialize(queryResults, options); } @@ -77,7 +92,11 @@ private static string WriteQueryResults(TestCase testCase) { var results = new Dictionary { - ["countMostSevereTestStepResultStatus"] = query.CountMostSevereTestStepResultStatus(), + ["countMostSevereTestStepResultStatus"] = query.CountMostSevereTestStepResultStatus() + .ToDictionary( + kvp => kvp.Key.ToString(), + kvp => (object)kvp.Value + ), ["countTestCasesStarted"] = query.TestCasesStartedCount, ["findAllPickles"] = query.FindAllPickles().Count, ["findAllPickleSteps"] = query.FindAllPickleSteps().Count, @@ -113,7 +132,7 @@ private static string WriteQueryResults(TestCase testCase) .ToList(), ["findMeta"] = query.FindMeta()?.Implementation?.Name, ["findMostSevereTestStepResultBy"] = query.FindAllTestCaseStarted() - .Select(tcs => query.FindMostSevereTestStepResultBy(tcs)?.Status) + .Select(tcs => query.FindMostSevereTestStepResultBy(tcs)?.Status.ToString()) .ToList(), ["findNameOf"] = new Dictionary { @@ -137,12 +156,17 @@ private static string WriteQueryResults(TestCase testCase) .Select(tcs => query.FindTestCaseBy(tcs)?.Id) .ToList(), ["findTestCaseDurationBy"] = query.FindAllTestCaseStarted() - .Select(tcs => query.FindTestCaseDurationBy(tcs)?.ToString()) + .Select(tcs => + { + var duration = query.FindTestCaseDurationBy(tcs); + var ts = ConvertTimeSpanToTimestamp(duration); + return ts; + }) .ToList(), ["findTestCaseFinishedBy"] = query.FindAllTestCaseStarted() .Select(tcs => query.FindTestCaseFinishedBy(tcs)?.TestCaseStartedId) .ToList(), - ["findTestRunDuration"] = query.FindTestRunDuration()?.ToString(), + ["findTestRunDuration"] = ConvertTimeSpanToTimestamp(query.FindTestRunDuration()), ["findTestRunFinished"] = query.FindTestRunFinished(), ["findTestRunStarted"] = query.FindTestRunStarted(), ["findTestStepByTestStepStarted"] = query.FindAllTestCaseStarted() @@ -161,7 +185,21 @@ private static string WriteQueryResults(TestCase testCase) .Select(pair => new object?[] { pair.Item1.TestStepId, pair.Item2.Id }) .ToList(), }; - return results; + // Filter out null values and empty collections + return results + .Where(kvp => + kvp.Value != null && + (!(kvp.Value is IEnumerable enumerable) || enumerable.Cast().Any())) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } + + private static Timestamp? ConvertTimeSpanToTimestamp(TimeSpan? duration) + { + if (duration == null) return null; + return new Timestamp( + (long)duration.Value.TotalSeconds, + (int)((duration.Value.Ticks % TimeSpan.TicksPerSecond) * 100) + ); } private static Stream ReadResourceAsStream(string resourceName) @@ -196,4 +234,4 @@ public TestCase(string ndjsonFile) public override string ToString() => Name; } } -} \ No newline at end of file +} diff --git a/dotnet/Query/QueryTest/QueryTest.csproj b/dotnet/Query/QueryTest/QueryTest.csproj index a3940118..e31aae8b 100644 --- a/dotnet/Query/QueryTest/QueryTest.csproj +++ b/dotnet/Query/QueryTest/QueryTest.csproj @@ -22,7 +22,7 @@ - + diff --git a/dotnet/Query/QueryTest/TestRunFinishedOrderedConverter.cs b/dotnet/Query/QueryTest/TestRunFinishedOrderedConverter.cs new file mode 100644 index 00000000..2fda4f69 --- /dev/null +++ b/dotnet/Query/QueryTest/TestRunFinishedOrderedConverter.cs @@ -0,0 +1,35 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Io.Cucumber.Messages.Types; + +public class TestRunFinishedOrderedConverter : JsonConverter +{ + public override TestRunFinished? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return JsonSerializer.Deserialize(ref reader, options); + } + + public override void Write(Utf8JsonWriter writer, TestRunFinished value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + // Write properties in the expected order + if (!string.IsNullOrEmpty(value.Message)) + writer.WriteString("message", value.Message); + + writer.WriteBoolean("success", value.Success); + + writer.WritePropertyName("timestamp"); + JsonSerializer.Serialize(writer, value.Timestamp, options); + + if (value.Exception != null) + { + writer.WritePropertyName("exception"); + JsonSerializer.Serialize(writer, value.Exception, options); + } + + if (!string.IsNullOrEmpty(value.TestRunStartedId)) + writer.WriteString("testRunStartedId", value.TestRunStartedId); + + writer.WriteEndObject(); + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/TestRunStartedOrderedConverter.cs b/dotnet/Query/QueryTest/TestRunStartedOrderedConverter.cs new file mode 100644 index 00000000..6e1965fc --- /dev/null +++ b/dotnet/Query/QueryTest/TestRunStartedOrderedConverter.cs @@ -0,0 +1,24 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Io.Cucumber.Messages.Types; + +public class TestRunStartedOrderedConverter : JsonConverter +{ + public override TestRunStarted? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return JsonSerializer.Deserialize(ref reader, options); + } + + public override void Write(Utf8JsonWriter writer, TestRunStarted value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + // Write properties in the expected order + writer.WritePropertyName("timestamp"); + JsonSerializer.Serialize(writer, value.Timestamp, options); + + if (!string.IsNullOrEmpty(value.Id)) + writer.WriteString("id", value.Id); + + writer.WriteEndObject(); + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/TimestampOrderedConverter.cs b/dotnet/Query/QueryTest/TimestampOrderedConverter.cs new file mode 100644 index 00000000..80ddbdb2 --- /dev/null +++ b/dotnet/Query/QueryTest/TimestampOrderedConverter.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Io.Cucumber.Messages.Types; + +public class TimestampOrderedConverter : JsonConverter +{ + public override Timestamp? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Use default deserialization + return JsonSerializer.Deserialize(ref reader, options); + } + + public override void Write(Utf8JsonWriter writer, Timestamp value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteNumber("seconds", value.Seconds); + writer.WriteNumber("nanos", value.Nanos); + writer.WriteEndObject(); + } +} \ No newline at end of file From 5aa6c09f4bf84530c2257f9a71662a934d290a41 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Wed, 9 Jul 2025 08:44:18 -0500 Subject: [PATCH 5/8] Refactor such that testdata files are read from the file system (rather than embedded resources). --- dotnet/.gitignore | 4 + dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 17 +- dotnet/Query/QueryTest/QueryTest.csproj | 15 +- .../Resources/attachments.feature.ndjson | 77 --- .../attachments.feature.query-results.json | 407 -------------- .../QueryTest/Resources/cdata.feature.ndjson | 12 - .../Resources/data-tables.feature.ndjson | 15 - .../QueryTest/Resources/empty.feature.ndjson | 9 - .../empty.feature.query-results.json | 91 ---- .../examples-tables-attachment.feature.ndjson | 21 - .../Resources/examples-tables.feature.ndjson | 100 ---- ...examples-tables.feature.query-results.json | 513 ------------------ .../Resources/hooks-attachment.feature.ndjson | 20 - .../hooks-conditional.feature.ndjson | 36 -- .../Resources/hooks-named.feature.ndjson | 18 - .../QueryTest/Resources/hooks.feature.ndjson | 39 -- .../hooks.feature.query-results.json | 221 -------- .../Resources/markdown.feature.md.ndjson | 35 -- .../Resources/minimal.feature.ndjson | 12 - .../minimal.feature.query-results.json | 111 ---- .../Resources/parameter-types.feature.ndjson | 13 - .../Resources/pending.feature.ndjson | 30 - .../QueryTest/Resources/retry.feature.ndjson | 59 -- .../QueryTest/Resources/rules.feature.ndjson | 47 -- .../rules.feature.query-results.json | 252 --------- .../Resources/skipped.feature.ndjson | 33 -- .../Resources/stack-traces.feature.ndjson | 12 - .../Resources/undefined.feature.ndjson | 29 - .../unknown-parameter-type.feature.ndjson | 12 - 29 files changed, 23 insertions(+), 2237 deletions(-) delete mode 100644 dotnet/Query/QueryTest/Resources/attachments.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/cdata.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/empty.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/empty.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/hooks.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/minimal.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/pending.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/retry.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/rules.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/rules.feature.query-results.json delete mode 100644 dotnet/Query/QueryTest/Resources/skipped.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/undefined.feature.ndjson delete mode 100644 dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson diff --git a/dotnet/.gitignore b/dotnet/.gitignore index 91fa9507..571b6977 100644 --- a/dotnet/.gitignore +++ b/dotnet/.gitignore @@ -174,3 +174,7 @@ Gherkin.NuGetPackages/bin/ .tested .fixprotoc .vs/ + +# ======================== +# Query project specific ignore settings +Query/QueryTest/testdata/ \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs index ec3add3b..4649e0c8 100644 --- a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -204,11 +204,14 @@ private static string WriteQueryResults(TestCase testCase) private static Stream ReadResourceAsStream(string resourceName) { - var assembly = Assembly.GetExecutingAssembly(); - var fullName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith(resourceName)); - if (fullName == null) - throw new FileNotFoundException($"Resource {resourceName} not found."); - return assembly.GetManifestResourceStream(fullName)!; + var assemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (assemblyLocation == null) + throw new InvalidOperationException("Assembly location could not be determined."); + + var fullName = Path.Combine(assemblyLocation, "testdata", resourceName); + if (!File.Exists(fullName)) + throw new FileNotFoundException($"Resource {fullName} not found."); + return File.OpenRead(fullName); } private static string ReadResourceAsString(string resourceName) @@ -227,8 +230,8 @@ public class TestCase public TestCase(string ndjsonFile) { Name = ndjsonFile.Substring(0, ndjsonFile.LastIndexOf(".ndjson", StringComparison.Ordinal)); - SourceResourceName = $"QueryTest.Resources.{ndjsonFile}"; - ExpectedResourceName = $"QueryTest.Resources.{Name}.query-results.json"; + SourceResourceName = ndjsonFile; + ExpectedResourceName = $"{Name}.query-results.json"; } public override string ToString() => Name; diff --git a/dotnet/Query/QueryTest/QueryTest.csproj b/dotnet/Query/QueryTest/QueryTest.csproj index e31aae8b..1ded2e6c 100644 --- a/dotnet/Query/QueryTest/QueryTest.csproj +++ b/dotnet/Query/QueryTest/QueryTest.csproj @@ -15,12 +15,6 @@ true - - - - - - @@ -34,4 +28,13 @@ + + + Always + + + Always + + + diff --git a/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson b/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson deleted file mode 100644 index a2b0583f..00000000 --- a/dotnet/Query/QueryTest/Resources/attachments.feature.ndjson +++ /dev/null @@ -1,77 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type\n\n Scenario: Strings can be attached with a media type\n Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.\n\n When the string \"hello\" is attached as \"application/octet-stream\"\n\n Scenario: Log text\n When the string \"hello\" is logged\n\n Scenario: Log ANSI coloured text\n When text with ANSI escapes is logged\n\n Scenario: Log JSON\n When the following string is attached as \"application/json\":\n ```\n {\"message\": \"The big question\", \"foo\": \"bar\"}\n ```\n\n Scenario: Byte arrays are base64-encoded regardless of media type\n When an array with 10 bytes is attached as \"text/plain\"\n\n Scenario: Attaching JPEG images\n When a JPEG image is attached\n\n Scenario: Attaching PNG images\n When a PNG image is attached\n\n Scenario: Attaching PDFs with a different filename\n When a PDF document is attached and renamed\n\n Scenario: Attaching URIs\n When a link to \"https://cucumber.io\" is attached\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/attachments/attachments.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":" Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":12},"name":"Strings can be attached with a media type","steps":[{"id":"9","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"the string \"hello\" is attached as \"application/octet-stream\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":18},"name":"Log text","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":19},"text":"the string \"hello\" is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"14","keyword":"Scenario","location":{"column":3,"line":21},"name":"Log ANSI coloured text","steps":[{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":5,"line":22},"text":"text with ANSI escapes is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"16","keyword":"Scenario","location":{"column":3,"line":24},"name":"Log JSON","steps":[{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}","delimiter":"```","location":{"column":8,"line":26}},"id":"15","keyword":"When ","keywordType":"Action","location":{"column":6,"line":25},"text":"the following string is attached as \"application/json\":"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"18","keyword":"Scenario","location":{"column":3,"line":30},"name":"Byte arrays are base64-encoded regardless of media type","steps":[{"id":"17","keyword":"When ","keywordType":"Action","location":{"column":5,"line":31},"text":"an array with 10 bytes is attached as \"text/plain\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"20","keyword":"Scenario","location":{"column":3,"line":33},"name":"Attaching JPEG images","steps":[{"id":"19","keyword":"When ","keywordType":"Action","location":{"column":5,"line":34},"text":"a JPEG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"22","keyword":"Scenario","location":{"column":3,"line":36},"name":"Attaching PNG images","steps":[{"id":"21","keyword":"When ","keywordType":"Action","location":{"column":5,"line":37},"text":"a PNG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"24","keyword":"Scenario","location":{"column":3,"line":39},"name":"Attaching PDFs with a different filename","steps":[{"id":"23","keyword":"When ","keywordType":"Action","location":{"column":5,"line":40},"text":"a PDF document is attached and renamed"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"26","keyword":"Scenario","location":{"column":3,"line":42},"name":"Attaching URIs","steps":[{"id":"25","keyword":"When ","keywordType":"Action","location":{"column":5,"line":43},"text":"a link to \"https://cucumber.io\" is attached"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Attachments","tags":[]},"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"28","language":"en","name":"Strings can be attached with a media type","steps":[{"astNodeIds":["9"],"id":"27","text":"the string \"hello\" is attached as \"application/octet-stream\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["12"],"id":"30","language":"en","name":"Log text","steps":[{"astNodeIds":["11"],"id":"29","text":"the string \"hello\" is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["14"],"id":"32","language":"en","name":"Log ANSI coloured text","steps":[{"astNodeIds":["13"],"id":"31","text":"text with ANSI escapes is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["16"],"id":"34","language":"en","name":"Log JSON","steps":[{"argument":{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}"}},"astNodeIds":["15"],"id":"33","text":"the following string is attached as \"application/json\":","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["18"],"id":"36","language":"en","name":"Byte arrays are base64-encoded regardless of media type","steps":[{"astNodeIds":["17"],"id":"35","text":"an array with 10 bytes is attached as \"text/plain\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["20"],"id":"38","language":"en","name":"Attaching JPEG images","steps":[{"astNodeIds":["19"],"id":"37","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["22"],"id":"40","language":"en","name":"Attaching PNG images","steps":[{"astNodeIds":["21"],"id":"39","text":"a PNG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["24"],"id":"42","language":"en","name":"Attaching PDFs with a different filename","steps":[{"astNodeIds":["23"],"id":"41","text":"a PDF document is attached and renamed","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["26"],"id":"44","language":"en","name":"Attaching URIs","steps":[{"astNodeIds":["25"],"id":"43","text":"a link to \"https://cucumber.io\" is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"the string {string} is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"the string {string} is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"text with ANSI escapes is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"the following string is attached as {string}:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":18},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"4","pattern":{"source":"an array with {int} bytes is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"5","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":31},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"6","pattern":{"source":"a PNG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":35},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"7","pattern":{"source":"a PDF document is attached and renamed","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":39},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"8","pattern":{"source":"a link to {string} is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":43},"uri":"samples/attachments/attachments.feature.ts"}}} -{"testRunStarted":{"id":"45","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"47","pickleId":"28","testRunStartedId":"45","testSteps":[{"id":"46","pickleStepId":"27","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"},{"group":{"children":[{"children":[{"children":[]}],"start":35,"value":"application/octet-stream"},{"children":[{"children":[]}]}],"start":34,"value":"\"application/octet-stream\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"49","pickleId":"30","testRunStartedId":"45","testSteps":[{"id":"48","pickleStepId":"29","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"51","pickleId":"32","testRunStartedId":"45","testSteps":[{"id":"50","pickleStepId":"31","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"53","pickleId":"34","testRunStartedId":"45","testSteps":[{"id":"52","pickleStepId":"33","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":37,"value":"application/json"},{"children":[{"children":[]}]}],"start":36,"value":"\"application/json\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"55","pickleId":"36","testRunStartedId":"45","testSteps":[{"id":"54","pickleStepId":"35","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[{"children":[{"children":[]}],"start":39,"value":"text/plain"},{"children":[{"children":[]}]}],"start":38,"value":"\"text/plain\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"57","pickleId":"38","testRunStartedId":"45","testSteps":[{"id":"56","pickleStepId":"37","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"59","pickleId":"40","testRunStartedId":"45","testSteps":[{"id":"58","pickleStepId":"39","stepDefinitionIds":["6"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"61","pickleId":"42","testRunStartedId":"45","testSteps":[{"id":"60","pickleStepId":"41","stepDefinitionIds":["7"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"63","pickleId":"44","testRunStartedId":"45","testSteps":[{"id":"62","pickleStepId":"43","stepDefinitionIds":["8"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":11,"value":"https://cucumber.io"},{"children":[{"children":[]}]}],"start":10,"value":"\"https://cucumber.io\""},"parameterTypeName":"string"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"64","testCaseId":"47","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"64","testStepId":"46","timestamp":{"nanos":2000000,"seconds":0}}} -{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"application/octet-stream","testCaseStartedId":"64","testStepId":"46"}} -{"testStepFinished":{"testCaseStartedId":"64","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"64","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"65","testCaseId":"49","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"65","testStepId":"48","timestamp":{"nanos":6000000,"seconds":0}}} -{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"65","testStepId":"48"}} -{"testStepFinished":{"testCaseStartedId":"65","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"65","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"66","testCaseId":"51","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"66","testStepId":"50","timestamp":{"nanos":10000000,"seconds":0}}} -{"attachment":{"body":"This displays a \u001b[31mr\u001b[0m\u001b[91ma\u001b[0m\u001b[33mi\u001b[0m\u001b[32mn\u001b[0m\u001b[34mb\u001b[0m\u001b[95mo\u001b[0m\u001b[35mw\u001b[0m","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"66","testStepId":"50"}} -{"testStepFinished":{"testCaseStartedId":"66","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"66","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"67","testCaseId":"53","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"67","testStepId":"52","timestamp":{"nanos":14000000,"seconds":0}}} -{"attachment":{"body":"{\"message\": \"The big question\", \"foo\": \"bar\"}","contentEncoding":"IDENTITY","mediaType":"application/json","testCaseStartedId":"67","testStepId":"52"}} -{"testStepFinished":{"testCaseStartedId":"67","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"67","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"68","testCaseId":"55","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"68","testStepId":"54","timestamp":{"nanos":18000000,"seconds":0}}} -{"attachment":{"body":"AAECAwQFBgcICQ==","contentEncoding":"BASE64","mediaType":"text/plain","testCaseStartedId":"68","testStepId":"54"}} -{"testStepFinished":{"testCaseStartedId":"68","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"68","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"69","testCaseId":"57","timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"69","testStepId":"56","timestamp":{"nanos":22000000,"seconds":0}}} -{"attachment":{"body":"/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAC4AKQMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAIBAUGBwABAwL/2gAIAQEAAAAAOESYe+lPPw0bK2mvU5gRhNkM/tNMGeuJM5msiEjujvC+s0ApSWvn/8QAFgEBAQEAAAAAAAAAAAAAAAAABQME/9oACAECEAAAADs6pclK4E//xAAWAQEBAQAAAAAAAAAAAAAAAAAHBgT/2gAIAQMQAAAAMJZbKcF1XHit/8QANhAAAQQBAgQDBAcJAAAAAAAAAgEDBAUGABEHEiExEyJREEFCUhRTYXFzgZIVFiMyMzRVY3L/2gAIAQEAAT8AzLMqPBKOReXb6gy3sDbYdXXnS/labH3mWrrMOIWdGb063fxyoPq1XVp8klQ/3v8Aff7E0eCY86fjPtynn99/GclOq5v6782quZnOGmEnEcrmPNN96y1cWTFcH5BUurf5a4bcTKzP6x9QjlBuIKo1YVzq7mwfuJF+IC9y+zPLc8z4kWiuHz1GLuLAht/AU3u+6qfMK+XUuV4TbrTBtFNVoyYZM0RTJE6dO+2+oGcWZY1fzp0URsq5wGuXkUU3dLlHmH1FdYvMs59HCmW7SBKdQiVEHl3Hfyqqe7dNFbOYRlNDnkQlBth9uHaoPZ2C+SCSl9oL1HX0qN9c3+pNY6pkeSG9/XO/sie9fEV5d9Z5FxdbKNKsbeREsUbHZGAVxeQV6Lt8K6gtMPQYzhD43istETjzaC45sm6EaeulzOgC1Kmdkm1KF3wvO2Qjz+m+syECxe7Q+30ZV/NF3TX7dyv5nv06zGpPDOJd/WvAoV+QvHb1znwk8f8AcN/9c3XUuhp5s1qyl17L0poUQDNN+3VN07LqDTZdNg5fLsFdanyxAI4c/wBUSnsGy9B9w6x+kWwrq2blFW2VtHVUF11P4qiC+RT27r9+r6E9kUyiwmDusq8nNMny924zZc7rv3Cia/dSg/xTH6dcQMDpc/oSqbLmZeaNHoUxro9GfHs4C6uoGZYC4cXM6Z+TCb6BdV7avRjH1dEerRagWEO0iNToDyOx3N+Q0RU32XZehbLq4u4VMyByFI33VQI8ZpOZ5416IICnVdcHuHNjUOSs3y5lByGwaRpiL3Svid0b/EL4vavbXDDBM5ymjjRKi3qK2vZ5lOSYOvykRw1Lyhsgawbg9jGGSUtzJ63v1TzWU/zuB+CPZtPb/8QAJREAAgEDBAEEAwAAAAAAAAAAAQIDAAQRBRITIVEUMTJhI0Fx/9oACAECAQE/ALy8eNxb2/z63N4zTy6hbbpJJ9wV9uCdwPWaglFxEkqDGeiPBFSv6bUZJXLhXGQVx3kfdPBbpyvLNyDOAEbsEjOfsVpJ4rUlx83JH8FSwxTqElTI/R9iKGkBJm5X/GGO1R7kV0AABgAYA8Cv/8QAJREAAgIBBAEDBQAAAAAAAAAAAQIDBAUABhESMSFRcRMVIjJB/9oACAEDAQE/AN1bpuJcbFYt+hXgSSDzydG9uLFF7T3yekwjKl+wY8dvHtrAZlMzjo7RAWQHrIvsw1k+2I3LdksmZVcsymPjlg/z/NTU6MIsy2bf1x26hYnHKsy9ufXyB41sWnN9rmlPKrJNyvwBxrL4LH5mMLbj/Nf1dfRhqjsKaa27WZgtRZD1APLsuq1aGpBHXgQLGihVA1//2Q==","contentEncoding":"BASE64","mediaType":"image/jpeg","testCaseStartedId":"69","testStepId":"56"}} -{"testStepFinished":{"testCaseStartedId":"69","testStepId":"56","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"69","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"59","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"58","timestamp":{"nanos":26000000,"seconds":0}}} -{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"70","testStepId":"58"}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"61","timestamp":{"nanos":29000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"60","timestamp":{"nanos":30000000,"seconds":0}}} -{"attachment":{"body":"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RmlsZTIgOCAwIFI+PgplbmRvYmoKMTAgMCBvYmoKPDwvVHlwZSAvRm9udAovRm9udERlc2NyaXB0b3IgOSAwIFIKL0Jhc2VGb250IC9BQUFBQUErQXJpYWxNVAovU3VidHlwZSAvQ0lERm9udFR5cGUyCi9DSURUb0dJRE1hcCAvSWRlbnRpdHkKL0NJRFN5c3RlbUluZm8gPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKElkZW50aXR5KQovU3VwcGxlbWVudCAwPj4KL1cgWzAgWzc1MF0gNTUgWzYxMC44Mzk4NF0gNzIgWzU1Ni4xNTIzNF0gODcgWzI3Ny44MzIwM11dCi9EVyA1MDA+PgplbmRvYmoKMTEgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDI1MD4+IHN0cmVhbQp4nF2Qy2rEIBSG9z7FWU4Xg0lmMtNFEMqUQha90LQPYPQkFRoVYxZ5+3pJU6ig8PP/n+dCb+1jq5UH+uaM6NDDoLR0OJvFCYQeR6VJWYFUwm8qvWLiltAAd+vscWr1YEjTAND34M7erXB4kKbHO0JfnUSn9AiHz1sXdLdY+40Tag8FYQwkDuGnZ25f+IRAE3ZsZfCVX4+B+Ut8rBahSrrM3QgjcbZcoON6RNIU4TBonsJhBLX851eZ6gfxxV1Mn64hXRT1mUV1vk/qUid2S5W/zF6ivmQos9fTls5+LBqXs08kFufCMGmDaYrYv9K4L9kaG6l4fwAdQH9hCmVuZHN0cmVhbQplbmRvYmoKNCAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMAovQmFzZUZvbnQgL0FBQUFBQStBcmlhbE1UCi9FbmNvZGluZyAvSWRlbnRpdHktSAovRGVzY2VuZGFudEZvbnRzIFsxMCAwIFJdCi9Ub1VuaWNvZGUgMTEgMCBSPj4KZW5kb2JqCnhyZWYKMCAxMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDM4MiAwMDAwMCBuIAowMDAwMDAwMTA4IDAwMDAwIG4gCjAwMDAwMDk2MDYgMDAwMDAgbiAKMDAwMDAwMDE0NSAwMDAwMCBuIAowMDAwMDAwNTkwIDAwMDAwIG4gCjAwMDAwMDA2NDUgMDAwMDAgbiAKMDAwMDAwMDY5MiAwMDAwMCBuIAowMDAwMDA4Nzg3IDAwMDAwIG4gCjAwMDAwMDkwMjEgMDAwMDAgbiAKMDAwMDAwOTI4NSAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgMTIKL1Jvb3QgNyAwIFIKL0luZm8gMSAwIFI+PgpzdGFydHhyZWYKOTc0NQolJUVPRgo=","contentEncoding":"BASE64","fileName":"renamed.pdf","mediaType":"application/pdf","testCaseStartedId":"71","testStepId":"60"}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":31000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"63","timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"62","timestamp":{"nanos":34000000,"seconds":0}}} -{"attachment":{"body":"https://cucumber.io","contentEncoding":"IDENTITY","mediaType":"text/uri-list","testCaseStartedId":"72","testStepId":"62"}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"62","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"45","timestamp":{"nanos":37000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json b/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json deleted file mode 100644 index 988c1074..00000000 --- a/dotnet/Query/QueryTest/Resources/attachments.feature.query-results.json +++ /dev/null @@ -1,407 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 9, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 0, - "AMBIGUOUS" : 0, - "FAILED" : 0 - }, - "countTestCasesStarted" : 9, - "findAllPickles" : 9, - "findAllPickleSteps" : 9, - "findAllTestCaseStarted" : 9, - "findAllTestSteps" : 9, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "Attachments", - [ - "64", - "65", - "66", - "67", - "68", - "69", - "70", - "71", - "72" - ] - ] - ], - "findAttachmentsBy" : [ - [ - "46", - "64", - "application/octet-stream", - "IDENTITY" - ], - [ - "48", - "65", - "text/x.cucumber.log+plain", - "IDENTITY" - ], - [ - "50", - "66", - "text/x.cucumber.log+plain", - "IDENTITY" - ], - [ - "52", - "67", - "application/json", - "IDENTITY" - ], - [ - "54", - "68", - "text/plain", - "BASE64" - ], - [ - "56", - "69", - "image/jpeg", - "BASE64" - ], - [ - "58", - "70", - "image/png", - "BASE64" - ], - [ - "60", - "71", - "application/pdf", - "BASE64" - ], - [ - "62", - "72", - "text/uri-list", - "IDENTITY" - ] - ], - "findFeatureBy" : [ - "Attachments", - "Attachments", - "Attachments", - "Attachments", - "Attachments", - "Attachments", - "Attachments", - "Attachments", - "Attachments" - ], - "findLocationOf" : [ - { - "line" : 12, - "column" : 3 - }, - { - "line" : 18, - "column" : 3 - }, - { - "line" : 21, - "column" : 3 - }, - { - "line" : 24, - "column" : 3 - }, - { - "line" : 30, - "column" : 3 - }, - { - "line" : 33, - "column" : 3 - }, - { - "line" : 36, - "column" : 3 - }, - { - "line" : 39, - "column" : 3 - }, - { - "line" : 42, - "column" : 3 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - "PASSED", - "PASSED", - "PASSED", - "PASSED", - "PASSED", - "PASSED", - "PASSED", - "PASSED", - "PASSED" - ], - "findNameOf" : { - "long" : [ - "Attachments - Strings can be attached with a media type", - "Attachments - Log text", - "Attachments - Log ANSI coloured text", - "Attachments - Log JSON", - "Attachments - Byte arrays are base64-encoded regardless of media type", - "Attachments - Attaching JPEG images", - "Attachments - Attaching PNG images", - "Attachments - Attaching PDFs with a different filename", - "Attachments - Attaching URIs" - ], - "excludeFeatureName" : [ - "Strings can be attached with a media type", - "Log text", - "Log ANSI coloured text", - "Log JSON", - "Byte arrays are base64-encoded regardless of media type", - "Attaching JPEG images", - "Attaching PNG images", - "Attaching PDFs with a different filename", - "Attaching URIs" - ], - "longPickleName" : [ - "Attachments - Strings can be attached with a media type", - "Attachments - Log text", - "Attachments - Log ANSI coloured text", - "Attachments - Log JSON", - "Attachments - Byte arrays are base64-encoded regardless of media type", - "Attachments - Attaching JPEG images", - "Attachments - Attaching PNG images", - "Attachments - Attaching PDFs with a different filename", - "Attachments - Attaching URIs" - ], - "short" : [ - "Strings can be attached with a media type", - "Log text", - "Log ANSI coloured text", - "Log JSON", - "Byte arrays are base64-encoded regardless of media type", - "Attaching JPEG images", - "Attaching PNG images", - "Attaching PDFs with a different filename", - "Attaching URIs" - ], - "shortPickleName" : [ - "Strings can be attached with a media type", - "Log text", - "Log ANSI coloured text", - "Log JSON", - "Byte arrays are base64-encoded regardless of media type", - "Attaching JPEG images", - "Attaching PNG images", - "Attaching PDFs with a different filename", - "Attaching URIs" - ] - }, - "findPickleBy" : [ - "Strings can be attached with a media type", - "Log text", - "Log ANSI coloured text", - "Log JSON", - "Byte arrays are base64-encoded regardless of media type", - "Attaching JPEG images", - "Attaching PNG images", - "Attaching PDFs with a different filename", - "Attaching URIs" - ], - "findPickleStepBy" : [ - "the string \"hello\" is attached as \"application/octet-stream\"", - "the string \"hello\" is logged", - "text with ANSI escapes is logged", - "the following string is attached as \"application/json\":", - "an array with 10 bytes is attached as \"text/plain\"", - "a JPEG image is attached", - "a PNG image is attached", - "a PDF document is attached and renamed", - "a link to \"https://cucumber.io\" is attached" - ], - "findStepBy" : [ - "the string \"hello\" is attached as \"application/octet-stream\"", - "the string \"hello\" is logged", - "text with ANSI escapes is logged", - "the following string is attached as \"application/json\":", - "an array with 10 bytes is attached as \"text/plain\"", - "a JPEG image is attached", - "a PNG image is attached", - "a PDF document is attached and renamed", - "a link to \"https://cucumber.io\" is attached" - ], - "findTestCaseBy" : [ - "47", - "49", - "51", - "53", - "55", - "57", - "59", - "61", - "63" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - }, - { - "seconds" : 0, - "nanos" : 3000000 - } - ], - "findTestCaseFinishedBy" : [ - "64", - "65", - "66", - "67", - "68", - "69", - "70", - "71", - "72" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 37000000 - }, - "findTestRunFinished" : { - "success" : true, - "timestamp" : { - "seconds" : 0, - "nanos" : 37000000 - }, - "testRunStartedId" : "45" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "45" - }, - "findTestStepByTestStepStarted" : [ - "46", - "48", - "50", - "52", - "54", - "56", - "58", - "60", - "62" - ], - "findTestStepByTestStepFinished" : [ - "46", - "48", - "50", - "52", - "54", - "56", - "58", - "60", - "62" - ], - "findTestStepsFinishedBy" : [ - [ - "46" - ], - [ - "48" - ], - [ - "50" - ], - [ - "52" - ], - [ - "54" - ], - [ - "56" - ], - [ - "58" - ], - [ - "60" - ], - [ - "62" - ] - ], - "findTestStepFinishedAndTestStepBy" : [ - [ - "46", - "46" - ], - [ - "48", - "48" - ], - [ - "50", - "50" - ], - [ - "52", - "52" - ], - [ - "54", - "54" - ], - [ - "56", - "56" - ], - [ - "58", - "58" - ], - [ - "60", - "60" - ], - [ - "62", - "62" - ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson b/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson deleted file mode 100644 index f0cb0b6d..00000000 --- a/dotnet/Query/QueryTest/Resources/cdata.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: cdata\n Cucumber xml formatters should be able to handle xml cdata elements\n\n Scenario: cdata\n Given I have 42 in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/cdata/cdata.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":4},"name":"cdata","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":5},"text":"I have 42 in my belly"}],"tags":[]}}],"description":" Cucumber xml formatters should be able to handle xml cdata elements","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"cdata","tags":[]},"uri":"samples/cdata/cdata.feature"}} -{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cdata","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 in my belly","type":"Context"}],"tags":[],"uri":"samples/cdata/cdata.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/cdata/cdata.feature.ts"}}} -{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson b/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson deleted file mode 100644 index d530c1c7..00000000 --- a/dotnet/Query/QueryTest/Resources/data-tables.feature.ndjson +++ /dev/null @@ -1,15 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Data Tables\n Data Tables can be placed underneath a step and will be passed as the last\n argument to the step definition.\n\n They can be used to represent richer data structures, and can be transformed to other data-types.\n\n Scenario: transposed table\n When the following table is transposed:\n | a | b |\n | 1 | 2 |\n Then it should be:\n | a | 1 |\n | b | 2 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/data-tables/data-tables.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":7},"name":"transposed table","steps":[{"dataTable":{"location":{"column":7,"line":9},"rows":[{"cells":[{"location":{"column":9,"line":9},"value":"a"},{"location":{"column":13,"line":9},"value":"b"}],"id":"2","location":{"column":7,"line":9}},{"cells":[{"location":{"column":9,"line":10},"value":"1"},{"location":{"column":13,"line":10},"value":"2"}],"id":"3","location":{"column":7,"line":10}}]},"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"the following table is transposed:"},{"dataTable":{"location":{"column":7,"line":12},"rows":[{"cells":[{"location":{"column":9,"line":12},"value":"a"},{"location":{"column":13,"line":12},"value":"1"}],"id":"5","location":{"column":7,"line":12}},{"cells":[{"location":{"column":9,"line":13},"value":"b"},{"location":{"column":13,"line":13},"value":"2"}],"id":"6","location":{"column":7,"line":13}}]},"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":11},"text":"it should be:"}],"tags":[]}}],"description":" Data Tables can be placed underneath a step and will be passed as the last\n argument to the step definition.\n\n They can be used to represent richer data structures, and can be transformed to other data-types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Data Tables","tags":[]},"uri":"samples/data-tables/data-tables.feature"}} -{"pickle":{"astNodeIds":["8"],"id":"11","language":"en","name":"transposed table","steps":[{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"b"}]},{"cells":[{"value":"1"},{"value":"2"}]}]}},"astNodeIds":["4"],"id":"9","text":"the following table is transposed:","type":"Action"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"1"}]},{"cells":[{"value":"b"},{"value":"2"}]}]}},"astNodeIds":["7"],"id":"10","text":"it should be:","type":"Outcome"}],"tags":[],"uri":"samples/data-tables/data-tables.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"the following table is transposed:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":5},"uri":"samples/data-tables/data-tables.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"it should be:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/data-tables/data-tables.feature.ts"}}} -{"testRunStarted":{"id":"12","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"15","pickleId":"11","testRunStartedId":"12","testSteps":[{"id":"13","pickleStepId":"9","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"14","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"16","testCaseId":"15","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"16","testStepId":"13","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"16","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"16","testStepId":"14","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"16","testStepId":"14","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"16","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"12","timestamp":{"nanos":7000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/empty.feature.ndjson b/dotnet/Query/QueryTest/Resources/empty.feature.ndjson deleted file mode 100644 index 2e429bb5..00000000 --- a/dotnet/Query/QueryTest/Resources/empty.feature.ndjson +++ /dev/null @@ -1,9 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Empty Scenarios\n Sometimes we want to quickly jot down a new scenario without specifying any actual steps\n for what should be executed.\n\n In this instance we want to stipulate what should / shouldn't run and what the output is\n\n Scenario: Blank Scenario\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/empty/empty.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"0","keyword":"Scenario","location":{"column":3,"line":7},"name":"Blank Scenario","steps":[],"tags":[]}}],"description":" Sometimes we want to quickly jot down a new scenario without specifying any actual steps\n for what should be executed.\n\n In this instance we want to stipulate what should / shouldn't run and what the output is","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Empty Scenarios","tags":[]},"uri":"samples/empty/empty.feature"}} -{"pickle":{"astNodeIds":["0"],"id":"1","language":"en","name":"Blank Scenario","steps":[],"tags":[],"uri":"samples/empty/empty.feature"}} -{"testRunStarted":{"id":"2","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"3","pickleId":"1","testRunStartedId":"2","testSteps":[]}} -{"testCaseStarted":{"attempt":0,"id":"4","testCaseId":"3","timestamp":{"nanos":1000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"4","timestamp":{"nanos":2000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"2","timestamp":{"nanos":3000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json b/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json deleted file mode 100644 index 645774a5..00000000 --- a/dotnet/Query/QueryTest/Resources/empty.feature.query-results.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 0, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 0, - "AMBIGUOUS" : 0, - "FAILED" : 0 - }, - "countTestCasesStarted" : 1, - "findAllPickles" : 1, - "findAllPickleSteps" : 0, - "findAllTestCaseStarted" : 1, - "findAllTestSteps" : 0, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "Empty Scenarios", - [ - "4" - ] - ] - ], - "findFeatureBy" : [ - "Empty Scenarios" - ], - "findLocationOf" : [ - { - "line" : 7, - "column" : 3 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - null - ], - "findNameOf" : { - "long" : [ - "Empty Scenarios - Blank Scenario" - ], - "excludeFeatureName" : [ - "Blank Scenario" - ], - "longPickleName" : [ - "Empty Scenarios - Blank Scenario" - ], - "short" : [ - "Blank Scenario" - ], - "shortPickleName" : [ - "Blank Scenario" - ] - }, - "findPickleBy" : [ - "Blank Scenario" - ], - "findTestCaseBy" : [ - "3" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 1000000 - } - ], - "findTestCaseFinishedBy" : [ - "4" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 3000000 - }, - "findTestRunFinished" : { - "success" : true, - "timestamp" : { - "seconds" : 0, - "nanos" : 3000000 - }, - "testRunStartedId" : "2" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "2" - }, - "findTestStepsFinishedBy" : [ - [ ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson b/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson deleted file mode 100644 index 5c277447..00000000 --- a/dotnet/Query/QueryTest/Resources/examples-tables-attachment.feature.ndjson +++ /dev/null @@ -1,21 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Examples Tables - With attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.\n\n Scenario Outline: Attaching images in an examples table\n When a image is attached\n\n Examples:\n | type |\n | JPEG |\n | PNG |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"6","keyword":"Examples","location":{"column":5,"line":10},"name":"","tableBody":[{"cells":[{"location":{"column":9,"line":12},"value":"JPEG"}],"id":"4","location":{"column":7,"line":12}},{"cells":[{"location":{"column":9,"line":13},"value":"PNG"}],"id":"5","location":{"column":7,"line":13}}],"tableHeader":{"cells":[{"location":{"column":9,"line":11},"value":"type"}],"id":"3","location":{"column":7,"line":11}},"tags":[]}],"id":"7","keyword":"Scenario Outline","location":{"column":3,"line":7},"name":"Attaching images in an examples table","steps":[{"id":"2","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a image is attached"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables - With attachments","tags":[]},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} -{"pickle":{"astNodeIds":["7","4"],"id":"9","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","4"],"id":"8","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} -{"pickle":{"astNodeIds":["7","5"],"id":"11","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","5"],"id":"10","text":"a PNG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a PNG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}} -{"testRunStarted":{"id":"12","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"14","pickleId":"9","testRunStartedId":"12","testSteps":[{"id":"13","pickleStepId":"8","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"16","pickleId":"11","testRunStartedId":"12","testSteps":[{"id":"15","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"17","testCaseId":"14","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"17","testStepId":"13","timestamp":{"nanos":2000000,"seconds":0}}} -{"attachment":{"body":"/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAC4AKQMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAIBAUGBwABAwL/2gAIAQEAAAAAOESYe+lPPw0bK2mvU5gRhNkM/tNMGeuJM5msiEjujvC+s0ApSWvn/8QAFgEBAQEAAAAAAAAAAAAAAAAABQME/9oACAECEAAAADs6pclK4E//xAAWAQEBAQAAAAAAAAAAAAAAAAAHBgT/2gAIAQMQAAAAMJZbKcF1XHit/8QANhAAAQQBAgQDBAcJAAAAAAAAAgEDBAUGABEHEiExEyJREEFCUhRTYXFzgZIVFiMyMzRVY3L/2gAIAQEAAT8AzLMqPBKOReXb6gy3sDbYdXXnS/labH3mWrrMOIWdGb063fxyoPq1XVp8klQ/3v8Aff7E0eCY86fjPtynn99/GclOq5v6782quZnOGmEnEcrmPNN96y1cWTFcH5BUurf5a4bcTKzP6x9QjlBuIKo1YVzq7mwfuJF+IC9y+zPLc8z4kWiuHz1GLuLAht/AU3u+6qfMK+XUuV4TbrTBtFNVoyYZM0RTJE6dO+2+oGcWZY1fzp0URsq5wGuXkUU3dLlHmH1FdYvMs59HCmW7SBKdQiVEHl3Hfyqqe7dNFbOYRlNDnkQlBth9uHaoPZ2C+SCSl9oL1HX0qN9c3+pNY6pkeSG9/XO/sie9fEV5d9Z5FxdbKNKsbeREsUbHZGAVxeQV6Lt8K6gtMPQYzhD43istETjzaC45sm6EaeulzOgC1Kmdkm1KF3wvO2Qjz+m+syECxe7Q+30ZV/NF3TX7dyv5nv06zGpPDOJd/WvAoV+QvHb1znwk8f8AcN/9c3XUuhp5s1qyl17L0poUQDNN+3VN07LqDTZdNg5fLsFdanyxAI4c/wBUSnsGy9B9w6x+kWwrq2blFW2VtHVUF11P4qiC+RT27r9+r6E9kUyiwmDusq8nNMny924zZc7rv3Cia/dSg/xTH6dcQMDpc/oSqbLmZeaNHoUxro9GfHs4C6uoGZYC4cXM6Z+TCb6BdV7avRjH1dEerRagWEO0iNToDyOx3N+Q0RU32XZehbLq4u4VMyByFI33VQI8ZpOZ5416IICnVdcHuHNjUOSs3y5lByGwaRpiL3Svid0b/EL4vavbXDDBM5ymjjRKi3qK2vZ5lOSYOvykRw1Lyhsgawbg9jGGSUtzJ63v1TzWU/zuB+CPZtPb/8QAJREAAgEDBAEEAwAAAAAAAAAAAQIDAAQRBRITIVEUMTJhI0Fx/9oACAECAQE/ALy8eNxb2/z63N4zTy6hbbpJJ9wV9uCdwPWaglFxEkqDGeiPBFSv6bUZJXLhXGQVx3kfdPBbpyvLNyDOAEbsEjOfsVpJ4rUlx83JH8FSwxTqElTI/R9iKGkBJm5X/GGO1R7kV0AABgAYA8Cv/8QAJREAAgIBBAEDBQAAAAAAAAAAAQIDBAUABhESMSFRcRMVIjJB/9oACAEDAQE/AN1bpuJcbFYt+hXgSSDzydG9uLFF7T3yekwjKl+wY8dvHtrAZlMzjo7RAWQHrIvsw1k+2I3LdksmZVcsymPjlg/z/NTU6MIsy2bf1x26hYnHKsy9ufXyB41sWnN9rmlPKrJNyvwBxrL4LH5mMLbj/Nf1dfRhqjsKaa27WZgtRZD1APLsuq1aGpBHXgQLGihVA1//2Q==","contentEncoding":"BASE64","mediaType":"image/jpeg","testCaseStartedId":"17","testStepId":"13"}} -{"testStepFinished":{"testCaseStartedId":"17","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"17","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"18","testCaseId":"16","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"18","testStepId":"15","timestamp":{"nanos":6000000,"seconds":0}}} -{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"18","testStepId":"15"}} -{"testStepFinished":{"testCaseStartedId":"18","testStepId":"15","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"18","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"12","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson b/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson deleted file mode 100644 index c60e75c2..00000000 --- a/dotnet/Query/QueryTest/Resources/examples-tables.feature.ndjson +++ /dev/null @@ -1,100 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Examples Tables\n Sometimes it can be desirable to run the same scenario multiple times with\n different data each time - this can be done by placing an Examples table\n underneath a Scenario, and use in the Scenario which match the\n table headers.\n\n The Scenario Outline name can also be parameterized. The name of the resulting\n pickle will have the replaced with the value from the examples\n table.\n\n Scenario Outline: Eating cucumbers\n Given there are cucumbers\n When I eat cucumbers\n Then I should have cucumbers\n\n @passing\n Examples: These are passing\n | start | eat | left |\n | 12 | 5 | 7 |\n | 20 | 5 | 15 |\n\n @failing\n Examples: These are failing\n | start | eat | left |\n | 12 | 20 | 0 |\n | 0 | 1 | 0 |\n\n @undefined\n Examples: These are undefined because the value is not an {int}\n | start | eat | left |\n | 12 | banana | 12 |\n | 0 | 1 | apple |\n\n Scenario Outline: Eating cucumbers with friends\n Given there are friends\n And there are cucumbers\n Then each person can eat cucumbers\n\n Examples:\n | friends | start | share |\n | 11 | 12 | 1 |\n | 1 | 4 | 2 |\n | 0 | 4 | 4 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables/examples-tables.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"12","keyword":"Examples","location":{"column":5,"line":17},"name":"These are passing","tableBody":[{"cells":[{"location":{"column":12,"line":19},"value":"12"},{"location":{"column":19,"line":19},"value":"5"},{"location":{"column":26,"line":19},"value":"7"}],"id":"9","location":{"column":7,"line":19}},{"cells":[{"location":{"column":12,"line":20},"value":"20"},{"location":{"column":19,"line":20},"value":"5"},{"location":{"column":25,"line":20},"value":"15"}],"id":"10","location":{"column":7,"line":20}}],"tableHeader":{"cells":[{"location":{"column":9,"line":18},"value":"start"},{"location":{"column":17,"line":18},"value":"eat"},{"location":{"column":23,"line":18},"value":"left"}],"id":"8","location":{"column":7,"line":18}},"tags":[{"id":"11","location":{"column":5,"line":16},"name":"@passing"}]},{"description":"","id":"17","keyword":"Examples","location":{"column":5,"line":23},"name":"These are failing","tableBody":[{"cells":[{"location":{"column":12,"line":25},"value":"12"},{"location":{"column":18,"line":25},"value":"20"},{"location":{"column":26,"line":25},"value":"0"}],"id":"14","location":{"column":7,"line":25}},{"cells":[{"location":{"column":13,"line":26},"value":"0"},{"location":{"column":19,"line":26},"value":"1"},{"location":{"column":26,"line":26},"value":"0"}],"id":"15","location":{"column":7,"line":26}}],"tableHeader":{"cells":[{"location":{"column":9,"line":24},"value":"start"},{"location":{"column":17,"line":24},"value":"eat"},{"location":{"column":23,"line":24},"value":"left"}],"id":"13","location":{"column":7,"line":24}},"tags":[{"id":"16","location":{"column":5,"line":22},"name":"@failing"}]},{"description":"","id":"22","keyword":"Examples","location":{"column":5,"line":29},"name":"These are undefined because the value is not an {int}","tableBody":[{"cells":[{"location":{"column":12,"line":31},"value":"12"},{"location":{"column":17,"line":31},"value":"banana"},{"location":{"column":29,"line":31},"value":"12"}],"id":"19","location":{"column":7,"line":31}},{"cells":[{"location":{"column":13,"line":32},"value":"0"},{"location":{"column":22,"line":32},"value":"1"},{"location":{"column":26,"line":32},"value":"apple"}],"id":"20","location":{"column":7,"line":32}}],"tableHeader":{"cells":[{"location":{"column":9,"line":30},"value":"start"},{"location":{"column":17,"line":30},"value":"eat"},{"location":{"column":26,"line":30},"value":"left"}],"id":"18","location":{"column":7,"line":30}},"tags":[{"id":"21","location":{"column":5,"line":28},"name":"@undefined"}]}],"id":"23","keyword":"Scenario Outline","location":{"column":3,"line":11},"name":"Eating cucumbers","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"there are cucumbers"},{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":13},"text":"I eat cucumbers"},{"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":14},"text":"I should have cucumbers"}],"tags":[]}},{"scenario":{"description":"","examples":[{"description":"","id":"31","keyword":"Examples","location":{"column":5,"line":39},"name":"","tableBody":[{"cells":[{"location":{"column":14,"line":41},"value":"11"},{"location":{"column":22,"line":41},"value":"12"},{"location":{"column":31,"line":41},"value":"1"}],"id":"28","location":{"column":7,"line":41}},{"cells":[{"location":{"column":15,"line":42},"value":"1"},{"location":{"column":23,"line":42},"value":"4"},{"location":{"column":31,"line":42},"value":"2"}],"id":"29","location":{"column":7,"line":42}},{"cells":[{"location":{"column":15,"line":43},"value":"0"},{"location":{"column":23,"line":43},"value":"4"},{"location":{"column":31,"line":43},"value":"4"}],"id":"30","location":{"column":7,"line":43}}],"tableHeader":{"cells":[{"location":{"column":9,"line":40},"value":"friends"},{"location":{"column":19,"line":40},"value":"start"},{"location":{"column":27,"line":40},"value":"share"}],"id":"27","location":{"column":7,"line":40}},"tags":[]}],"id":"32","keyword":"Scenario Outline","location":{"column":3,"line":34},"name":"Eating cucumbers with friends","steps":[{"id":"24","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":35},"text":"there are friends"},{"id":"25","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":36},"text":"there are cucumbers"},{"id":"26","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":37},"text":"each person can eat cucumbers"}],"tags":[]}}],"description":" Sometimes it can be desirable to run the same scenario multiple times with\n different data each time - this can be done by placing an Examples table\n underneath a Scenario, and use in the Scenario which match the\n table headers.\n\n The Scenario Outline name can also be parameterized. The name of the resulting\n pickle will have the replaced with the value from the examples\n table.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables","tags":[]},"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","9"],"id":"36","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","9"],"id":"33","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","9"],"id":"34","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["7","9"],"id":"35","text":"I should have 7 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"11","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","10"],"id":"40","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","10"],"id":"37","text":"there are 20 cucumbers","type":"Context"},{"astNodeIds":["6","10"],"id":"38","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["7","10"],"id":"39","text":"I should have 15 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"11","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","14"],"id":"44","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","14"],"id":"41","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","14"],"id":"42","text":"I eat 20 cucumbers","type":"Action"},{"astNodeIds":["7","14"],"id":"43","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"16","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","15"],"id":"48","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","15"],"id":"45","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["6","15"],"id":"46","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["7","15"],"id":"47","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"16","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","19"],"id":"52","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","19"],"id":"49","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["6","19"],"id":"50","text":"I eat banana cucumbers","type":"Action"},{"astNodeIds":["7","19"],"id":"51","text":"I should have 12 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["23","20"],"id":"56","language":"en","name":"Eating cucumbers","steps":[{"astNodeIds":["5","20"],"id":"53","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["6","20"],"id":"54","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["7","20"],"id":"55","text":"I should have apple cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["32","28"],"id":"60","language":"en","name":"Eating cucumbers with 11 friends","steps":[{"astNodeIds":["24","28"],"id":"57","text":"there are 11 friends","type":"Context"},{"astNodeIds":["25","28"],"id":"58","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["26","28"],"id":"59","text":"each person can eat 1 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["32","29"],"id":"64","language":"en","name":"Eating cucumbers with 1 friends","steps":[{"astNodeIds":["24","29"],"id":"61","text":"there are 1 friends","type":"Context"},{"astNodeIds":["25","29"],"id":"62","text":"there are 4 cucumbers","type":"Context"},{"astNodeIds":["26","29"],"id":"63","text":"each person can eat 2 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["32","30"],"id":"68","language":"en","name":"Eating cucumbers with 0 friends","steps":[{"astNodeIds":["24","30"],"id":"65","text":"there are 0 friends","type":"Context"},{"astNodeIds":["25","30"],"id":"66","text":"there are 4 cucumbers","type":"Context"},{"astNodeIds":["26","30"],"id":"67","text":"each person can eat 4 cucumbers","type":"Outcome"}],"tags":[],"uri":"samples/examples-tables/examples-tables.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"there are {int} friends","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"I eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"I should have {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"4","pattern":{"source":"each person can eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":20},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"testRunStarted":{"id":"69","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"73","pickleId":"36","testRunStartedId":"69","testSteps":[{"id":"70","pickleStepId":"33","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"71","pickleStepId":"34","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"72","pickleStepId":"35","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"7"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"77","pickleId":"40","testRunStartedId":"69","testSteps":[{"id":"74","pickleStepId":"37","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"75","pickleStepId":"38","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"76","pickleStepId":"39","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"15"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"81","pickleId":"44","testRunStartedId":"69","testSteps":[{"id":"78","pickleStepId":"41","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"79","pickleStepId":"42","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"80","pickleStepId":"43","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"85","pickleId":"48","testRunStartedId":"69","testSteps":[{"id":"82","pickleStepId":"45","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"83","pickleStepId":"46","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"84","pickleStepId":"47","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"89","pickleId":"52","testRunStartedId":"69","testSteps":[{"id":"86","pickleStepId":"49","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"87","pickleStepId":"50","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"88","pickleStepId":"51","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"12"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"93","pickleId":"56","testRunStartedId":"69","testSteps":[{"id":"90","pickleStepId":"53","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"91","pickleStepId":"54","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"92","pickleStepId":"55","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCase":{"id":"97","pickleId":"60","testRunStartedId":"69","testSteps":[{"id":"94","pickleStepId":"57","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"11"},"parameterTypeName":"int"}]}]},{"id":"95","pickleStepId":"58","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"96","pickleStepId":"59","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"1"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"101","pickleId":"64","testRunStartedId":"69","testSteps":[{"id":"98","pickleStepId":"61","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"99","pickleStepId":"62","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"4"},"parameterTypeName":"int"}]}]},{"id":"100","pickleStepId":"63","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"2"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"105","pickleId":"68","testRunStartedId":"69","testSteps":[{"id":"102","pickleStepId":"65","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"103","pickleStepId":"66","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"4"},"parameterTypeName":"int"}]}]},{"id":"104","pickleStepId":"67","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":20,"value":"4"},"parameterTypeName":"int"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"106","testCaseId":"73","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"106","testStepId":"70","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"106","testStepId":"70","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"106","testStepId":"71","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"106","testStepId":"71","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"106","testStepId":"72","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"106","testStepId":"72","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"106","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"107","testCaseId":"77","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"107","testStepId":"74","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"107","testStepId":"74","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"107","testStepId":"75","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"107","testStepId":"75","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"107","testStepId":"76","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"107","testStepId":"76","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"107","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"108","testCaseId":"81","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"108","testStepId":"78","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"108","testStepId":"78","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"108","testStepId":"79","timestamp":{"nanos":20000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"108","testStepId":"79","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"108","testStepId":"80","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"108","testStepId":"80","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-8 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-8 !== 0\n\nsamples/examples-tables/examples-tables.feature:14\nsamples/examples-tables/examples-tables.feature:25","status":"FAILED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"108","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"109","testCaseId":"85","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"109","testStepId":"82","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"109","testStepId":"82","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"109","testStepId":"83","timestamp":{"nanos":28000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"109","testStepId":"83","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"109","testStepId":"84","timestamp":{"nanos":30000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"109","testStepId":"84","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-1 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-1 !== 0\n\nsamples/examples-tables/examples-tables.feature:14\nsamples/examples-tables/examples-tables.feature:26","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"109","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"110","testCaseId":"89","timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"110","testStepId":"86","timestamp":{"nanos":34000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"110","testStepId":"86","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"110","testStepId":"87","timestamp":{"nanos":36000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"110","testStepId":"87","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"110","testStepId":"88","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"110","testStepId":"88","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"110","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"111","testCaseId":"93","timestamp":{"nanos":41000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"111","testStepId":"90","timestamp":{"nanos":42000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"111","testStepId":"90","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":43000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"111","testStepId":"91","timestamp":{"nanos":44000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"111","testStepId":"91","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"111","testStepId":"92","timestamp":{"nanos":46000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"111","testStepId":"92","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":47000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"111","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"112","testCaseId":"97","timestamp":{"nanos":49000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"112","testStepId":"94","timestamp":{"nanos":50000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"112","testStepId":"94","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":51000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"112","testStepId":"95","timestamp":{"nanos":52000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"112","testStepId":"95","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":53000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"112","testStepId":"96","timestamp":{"nanos":54000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"112","testStepId":"96","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":55000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"112","timestamp":{"nanos":56000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"113","testCaseId":"101","timestamp":{"nanos":57000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"113","testStepId":"98","timestamp":{"nanos":58000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"113","testStepId":"98","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":59000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"113","testStepId":"99","timestamp":{"nanos":60000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"113","testStepId":"99","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":61000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"113","testStepId":"100","timestamp":{"nanos":62000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"113","testStepId":"100","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":63000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"113","timestamp":{"nanos":64000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"114","testCaseId":"105","timestamp":{"nanos":65000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"114","testStepId":"102","timestamp":{"nanos":66000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"114","testStepId":"102","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":67000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"114","testStepId":"103","timestamp":{"nanos":68000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"114","testStepId":"103","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":69000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"114","testStepId":"104","timestamp":{"nanos":70000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"114","testStepId":"104","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":71000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"114","timestamp":{"nanos":72000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"69","timestamp":{"nanos":73000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json b/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json deleted file mode 100644 index 8380693f..00000000 --- a/dotnet/Query/QueryTest/Resources/examples-tables.feature.query-results.json +++ /dev/null @@ -1,513 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 5, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 2, - "AMBIGUOUS" : 0, - "FAILED" : 2 - }, - "countTestCasesStarted" : 9, - "findAllPickles" : 9, - "findAllPickleSteps" : 27, - "findAllTestCaseStarted" : 9, - "findAllTestSteps" : 27, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "Examples Tables", - [ - "106", - "107", - "108", - "109", - "110", - "111", - "112", - "113", - "114" - ] - ] - ], - "findFeatureBy" : [ - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables", - "Examples Tables" - ], - "findLocationOf" : [ - { - "line" : 19, - "column" : 7 - }, - { - "line" : 20, - "column" : 7 - }, - { - "line" : 25, - "column" : 7 - }, - { - "line" : 26, - "column" : 7 - }, - { - "line" : 31, - "column" : 7 - }, - { - "line" : 32, - "column" : 7 - }, - { - "line" : 41, - "column" : 7 - }, - { - "line" : 42, - "column" : 7 - }, - { - "line" : 43, - "column" : 7 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - "PASSED", - "PASSED", - "FAILED", - "FAILED", - "UNDEFINED", - "UNDEFINED", - "PASSED", - "PASSED", - "PASSED" - ], - "findNameOf" : { - "long" : [ - "Examples Tables - Eating cucumbers - These are passing - #1.1", - "Examples Tables - Eating cucumbers - These are passing - #1.2", - "Examples Tables - Eating cucumbers - These are failing - #2.1", - "Examples Tables - Eating cucumbers - These are failing - #2.2", - "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - #3.1", - "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - #3.2", - "Examples Tables - Eating cucumbers with friends - #1.1: Eating cucumbers with 11 friends", - "Examples Tables - Eating cucumbers with friends - #1.2: Eating cucumbers with 1 friends", - "Examples Tables - Eating cucumbers with friends - #1.3: Eating cucumbers with 0 friends" - ], - "excludeFeatureName" : [ - "Eating cucumbers - These are passing - #1.1", - "Eating cucumbers - These are passing - #1.2", - "Eating cucumbers - These are failing - #2.1", - "Eating cucumbers - These are failing - #2.2", - "Eating cucumbers - These are undefined because the value is not an {int} - #3.1", - "Eating cucumbers - These are undefined because the value is not an {int} - #3.2", - "Eating cucumbers with friends - #1.1: Eating cucumbers with 11 friends", - "Eating cucumbers with friends - #1.2: Eating cucumbers with 1 friends", - "Eating cucumbers with friends - #1.3: Eating cucumbers with 0 friends" - ], - "longPickleName" : [ - "Examples Tables - Eating cucumbers - These are passing - Eating cucumbers", - "Examples Tables - Eating cucumbers - These are passing - Eating cucumbers", - "Examples Tables - Eating cucumbers - These are failing - Eating cucumbers", - "Examples Tables - Eating cucumbers - These are failing - Eating cucumbers", - "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - Eating cucumbers", - "Examples Tables - Eating cucumbers - These are undefined because the value is not an {int} - Eating cucumbers", - "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 11 friends", - "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 1 friends", - "Examples Tables - Eating cucumbers with friends - Eating cucumbers with 0 friends" - ], - "short" : [ - "#1.1", - "#1.2", - "#2.1", - "#2.2", - "#3.1", - "#3.2", - "#1.1: Eating cucumbers with 11 friends", - "#1.2: Eating cucumbers with 1 friends", - "#1.3: Eating cucumbers with 0 friends" - ], - "shortPickleName" : [ - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers with 11 friends", - "Eating cucumbers with 1 friends", - "Eating cucumbers with 0 friends" - ] - }, - "findPickleBy" : [ - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers", - "Eating cucumbers with 11 friends", - "Eating cucumbers with 1 friends", - "Eating cucumbers with 0 friends" - ], - "findPickleStepBy" : [ - "each person can eat 2 cucumbers", - "there are 0 friends", - "there are 4 cucumbers", - "each person can eat 4 cucumbers", - "there are 12 cucumbers", - "I eat 5 cucumbers", - "I should have 7 cucumbers", - "there are 20 cucumbers", - "I eat 5 cucumbers", - "I should have 15 cucumbers", - "there are 12 cucumbers", - "I eat 20 cucumbers", - "I should have 0 cucumbers", - "there are 0 cucumbers", - "I eat 1 cucumbers", - "I should have 0 cucumbers", - "there are 12 cucumbers", - "I eat banana cucumbers", - "I should have 12 cucumbers", - "there are 0 cucumbers", - "I eat 1 cucumbers", - "I should have apple cucumbers", - "there are 11 friends", - "there are 12 cucumbers", - "each person can eat 1 cucumbers", - "there are 1 friends", - "there are 4 cucumbers" - ], - "findStepBy" : [ - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are cucumbers", - "I eat cucumbers", - "I should have cucumbers", - "there are friends", - "there are cucumbers", - "each person can eat cucumbers", - "there are friends", - "there are cucumbers", - "each person can eat cucumbers", - "there are friends", - "there are cucumbers", - "each person can eat cucumbers" - ], - "findTestCaseBy" : [ - "73", - "77", - "81", - "85", - "89", - "93", - "97", - "101", - "105" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - } - ], - "findTestCaseFinishedBy" : [ - "106", - "107", - "108", - "109", - "110", - "111", - "112", - "113", - "114" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 73000000 - }, - "findTestRunFinished" : { - "success" : false, - "timestamp" : { - "seconds" : 0, - "nanos" : 73000000 - }, - "testRunStartedId" : "69" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "69" - }, - "findTestStepByTestStepStarted" : [ - "70", - "71", - "72", - "74", - "75", - "76", - "78", - "79", - "80", - "82", - "83", - "84", - "86", - "87", - "88", - "90", - "91", - "92", - "94", - "95", - "96", - "98", - "99", - "100", - "102", - "103", - "104" - ], - "findTestStepByTestStepFinished" : [ - "70", - "71", - "72", - "74", - "75", - "76", - "78", - "79", - "80", - "82", - "83", - "84", - "86", - "87", - "88", - "90", - "91", - "92", - "94", - "95", - "96", - "98", - "99", - "100", - "102", - "103", - "104" - ], - "findTestStepsFinishedBy" : [ - [ - "70", - "71", - "72" - ], - [ - "74", - "75", - "76" - ], - [ - "78", - "79", - "80" - ], - [ - "82", - "83", - "84" - ], - [ - "86", - "87", - "88" - ], - [ - "90", - "91", - "92" - ], - [ - "94", - "95", - "96" - ], - [ - "98", - "99", - "100" - ], - [ - "102", - "103", - "104" - ] - ], - "findTestStepFinishedAndTestStepBy" : [ - [ - "70", - "70" - ], - [ - "71", - "71" - ], - [ - "72", - "72" - ], - [ - "74", - "74" - ], - [ - "75", - "75" - ], - [ - "76", - "76" - ], - [ - "78", - "78" - ], - [ - "79", - "79" - ], - [ - "80", - "80" - ], - [ - "82", - "82" - ], - [ - "83", - "83" - ], - [ - "84", - "84" - ], - [ - "86", - "86" - ], - [ - "87", - "87" - ], - [ - "88", - "88" - ], - [ - "90", - "90" - ], - [ - "91", - "91" - ], - [ - "92", - "92" - ], - [ - "94", - "94" - ], - [ - "95", - "95" - ], - [ - "96", - "96" - ], - [ - "98", - "98" - ], - [ - "99", - "99" - ], - [ - "100", - "100" - ], - [ - "102", - "102" - ], - [ - "103", - "103" - ], - [ - "104", - "104" - ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson deleted file mode 100644 index 5e911d8f..00000000 --- a/dotnet/Query/QueryTest/Resources/hooks-attachment.feature.ndjson +++ /dev/null @@ -1,20 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Hooks - Attachments\n Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.\n\n Scenario: With an valid attachment in the hook and a passed step\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-attachment/hooks-attachment.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":6},"name":"With an valid attachment in the hook and a passed step","steps":[{"id":"3","keyword":"When ","keywordType":"Action","location":{"column":5,"line":7},"text":"a step passes"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Attachments","tags":[]},"uri":"samples/hooks-attachment/hooks-attachment.feature"}} -{"pickle":{"astNodeIds":["4"],"id":"6","language":"en","name":"With an valid attachment in the hook and a passed step","steps":[{"astNodeIds":["3"],"id":"5","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks-attachment/hooks-attachment.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":4},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"BEFORE_TEST_CASE"}} -{"hook":{"id":"2","sourceReference":{"location":{"line":13},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"AFTER_TEST_CASE"}} -{"testRunStarted":{"id":"7","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"11","pickleId":"6","testRunStartedId":"7","testSteps":[{"hookId":"0","id":"8"},{"id":"9","pickleStepId":"5","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"2","id":"10"}]}} -{"testCaseStarted":{"attempt":0,"id":"12","testCaseId":"11","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"8","timestamp":{"nanos":2000000,"seconds":0}}} -{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"12","testStepId":"8"}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"8","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"9","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"9","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"10","timestamp":{"nanos":6000000,"seconds":0}}} -{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"12","testStepId":"10"}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"10","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"12","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"7","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson deleted file mode 100644 index c2473224..00000000 --- a/dotnet/Query/QueryTest/Resources/hooks-conditional.feature.ndjson +++ /dev/null @@ -1,36 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Hooks - Conditional execution\n Hooks are special steps that run before or after each scenario's steps.\n\n They can also conditionally target specific scenarios, using tag expressions\n\n @fail-before\n Scenario: A failure in the before hook and a skipped step\n When a step passes\n\n @fail-after\n Scenario: A failure in the after hook and a passed step\n When a step passes\n\n @passing-hook\n Scenario: With an tag, a passed step and hook\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-conditional/hooks-conditional.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":7},"name":"A failure in the before hook and a skipped step","steps":[{"id":"5","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step passes"}],"tags":[{"id":"6","location":{"column":3,"line":6},"name":"@fail-before"}]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":11},"name":"A failure in the after hook and a passed step","steps":[{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":12},"text":"a step passes"}],"tags":[{"id":"9","location":{"column":3,"line":10},"name":"@fail-after"}]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":15},"name":"With an tag, a passed step and hook","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"a step passes"}],"tags":[{"id":"12","location":{"column":3,"line":14},"name":"@passing-hook"}]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n They can also conditionally target specific scenarios, using tag expressions","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Conditional execution","tags":[]},"uri":"samples/hooks-conditional/hooks-conditional.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"A failure in the before hook and a skipped step","steps":[{"astNodeIds":["5"],"id":"14","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"6","name":"@fail-before"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"17","language":"en","name":"A failure in the after hook and a passed step","steps":[{"astNodeIds":["8"],"id":"16","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"9","name":"@fail-after"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} -{"pickle":{"astNodeIds":["13"],"id":"19","language":"en","name":"With an tag, a passed step and hook","steps":[{"astNodeIds":["11"],"id":"18","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"12","name":"@passing-hook"}],"uri":"samples/hooks-conditional/hooks-conditional.feature"}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@passing-hook","type":"BEFORE_TEST_CASE"}} -{"hook":{"id":"1","sourceReference":{"location":{"line":7},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@fail-before","type":"BEFORE_TEST_CASE"}} -{"hook":{"id":"3","sourceReference":{"location":{"line":15},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@fail-after","type":"AFTER_TEST_CASE"}} -{"hook":{"id":"4","sourceReference":{"location":{"line":19},"uri":"samples/hooks-conditional/hooks-conditional.feature.ts"},"tagExpression":"@passing-hook","type":"AFTER_TEST_CASE"}} -{"testRunStarted":{"id":"20","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"23","pickleId":"15","testRunStartedId":"20","testSteps":[{"hookId":"1","id":"21"},{"id":"22","pickleStepId":"14","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"26","pickleId":"17","testRunStartedId":"20","testSteps":[{"id":"24","pickleStepId":"16","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"25"}]}} -{"testCase":{"id":"30","pickleId":"19","testRunStartedId":"20","testSteps":[{"hookId":"0","id":"27"},{"id":"28","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"29"}]}} -{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"23","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"21","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks-conditional/hooks-conditional.feature:7","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"22","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"26","timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"24","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"25","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks-conditional/hooks-conditional.feature:11","status":"FAILED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"33","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"33","testStepId":"27","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"33","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"33","testStepId":"28","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"33","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"33","testStepId":"29","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"33","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"33","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"20","timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson deleted file mode 100644 index 6d415aad..00000000 --- a/dotnet/Query/QueryTest/Resources/hooks-named.feature.ndjson +++ /dev/null @@ -1,18 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Hooks - Named\n Hooks are special steps that run before or after each scenario's steps.\n\n Hooks can be given a name. Which is nice for reporting. Otherwise they work\n exactly the same as regular hooks.\n\n Scenario: With a named before and after hook\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-named/hooks-named.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":7},"name":"With a named before and after hook","steps":[{"id":"3","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step passes"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n Hooks can be given a name. Which is nice for reporting. Otherwise they work\n exactly the same as regular hooks.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Named","tags":[]},"uri":"samples/hooks-named/hooks-named.feature"}} -{"pickle":{"astNodeIds":["4"],"id":"6","language":"en","name":"With a named before and after hook","steps":[{"astNodeIds":["3"],"id":"5","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks-named/hooks-named.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/hooks-named/hooks-named.feature.ts"}}} -{"hook":{"id":"0","name":"A named before hook","sourceReference":{"location":{"line":3},"uri":"samples/hooks-named/hooks-named.feature.ts"},"type":"BEFORE_TEST_CASE"}} -{"hook":{"id":"2","name":"A named after hook","sourceReference":{"location":{"line":11},"uri":"samples/hooks-named/hooks-named.feature.ts"},"type":"AFTER_TEST_CASE"}} -{"testRunStarted":{"id":"7","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"11","pickleId":"6","testRunStartedId":"7","testSteps":[{"hookId":"0","id":"8"},{"id":"9","pickleStepId":"5","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"2","id":"10"}]}} -{"testCaseStarted":{"attempt":0,"id":"12","testCaseId":"11","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"8","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"8","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"9","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"9","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"12","testStepId":"10","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"12","testStepId":"10","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"12","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"7","timestamp":{"nanos":9000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson b/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson deleted file mode 100644 index 238718e9..00000000 --- a/dotnet/Query/QueryTest/Resources/hooks.feature.ndjson +++ /dev/null @@ -1,39 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}} -{"source":{"data":"Feature: Hooks\n Hooks are special steps that run before or after each scenario's steps.\n\n Scenario: No tags and a passed step\n When a step passes\n\n Scenario: No tags and a failed step\n When a step fails\n\n Scenario: No tags and a undefined step\n When a step does not exist\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks/hooks.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":4},"name":"No tags and a passed step","steps":[{"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":5},"text":"a step passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":7},"name":"No tags and a failed step","steps":[{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a step fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":10},"name":"No tags and a undefined step","steps":[{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":11},"text":"a step does not exist"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks","tags":[]},"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["5"],"id":"11","language":"en","name":"No tags and a passed step","steps":[{"astNodeIds":["4"],"id":"10","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"13","language":"en","name":"No tags and a failed step","steps":[{"astNodeIds":["6"],"id":"12","text":"a step fails","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"15","language":"en","name":"No tags and a undefined step","steps":[{"astNodeIds":["8"],"id":"14","text":"a step does not exist","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/hooks/hooks.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/hooks/hooks.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/hooks/hooks.feature.ts"},"type":"BEFORE_TEST_CASE"}} -{"hook":{"id":"3","sourceReference":{"location":{"line":15},"uri":"samples/hooks/hooks.feature.ts"},"type":"AFTER_TEST_CASE"}} -{"testRunStarted":{"id":"16","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"20","pickleId":"11","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"17"},{"id":"18","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"19"}]}} -{"testCase":{"id":"24","pickleId":"13","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"21"},{"id":"22","pickleStepId":"12","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"3","id":"23"}]}} -{"testCase":{"id":"28","pickleId":"15","testRunStartedId":"16","testSteps":[{"hookId":"0","id":"25"},{"id":"26","pickleStepId":"14","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"hookId":"3","id":"27"}]}} -{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"17","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"17","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"18","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"18","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"19","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"19","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"24","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"21","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"22","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:8","status":"FAILED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"23","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"23","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"28","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"25","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"26","timestamp":{"nanos":20000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"26","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"27","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"16","timestamp":{"nanos":25000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json b/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json deleted file mode 100644 index 8c4fb304..00000000 --- a/dotnet/Query/QueryTest/Resources/hooks.feature.query-results.json +++ /dev/null @@ -1,221 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 1, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 1, - "AMBIGUOUS" : 0, - "FAILED" : 1 - }, - "countTestCasesStarted" : 3, - "findAllPickles" : 3, - "findAllPickleSteps" : 3, - "findAllTestCaseStarted" : 3, - "findAllTestSteps" : 9, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "Hooks", - [ - "29", - "30", - "31" - ] - ] - ], - "findFeatureBy" : [ - "Hooks", - "Hooks", - "Hooks" - ], - "findHookBy" : [ - "0", - "3", - "0", - "3", - "0", - "3" - ], - "findLocationOf" : [ - { - "line" : 4, - "column" : 3 - }, - { - "line" : 7, - "column" : 3 - }, - { - "line" : 10, - "column" : 3 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - "PASSED", - "FAILED", - "UNDEFINED" - ], - "findNameOf" : { - "long" : [ - "Hooks - No tags and a passed step", - "Hooks - No tags and a failed step", - "Hooks - No tags and a undefined step" - ], - "excludeFeatureName" : [ - "No tags and a passed step", - "No tags and a failed step", - "No tags and a undefined step" - ], - "longPickleName" : [ - "Hooks - No tags and a passed step", - "Hooks - No tags and a failed step", - "Hooks - No tags and a undefined step" - ], - "short" : [ - "No tags and a passed step", - "No tags and a failed step", - "No tags and a undefined step" - ], - "shortPickleName" : [ - "No tags and a passed step", - "No tags and a failed step", - "No tags and a undefined step" - ] - }, - "findPickleBy" : [ - "No tags and a passed step", - "No tags and a failed step", - "No tags and a undefined step" - ], - "findPickleStepBy" : [ - "a step passes", - "a step fails", - "a step does not exist" - ], - "findStepBy" : [ - "a step passes", - "a step fails", - "a step does not exist" - ], - "findTestCaseBy" : [ - "20", - "24", - "28" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - }, - { - "seconds" : 0, - "nanos" : 7000000 - } - ], - "findTestCaseFinishedBy" : [ - "29", - "30", - "31" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 25000000 - }, - "findTestRunFinished" : { - "success" : false, - "timestamp" : { - "seconds" : 0, - "nanos" : 25000000 - }, - "testRunStartedId" : "16" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "16" - }, - "findTestStepByTestStepStarted" : [ - "17", - "18", - "19", - "21", - "22", - "23", - "25", - "26", - "27" - ], - "findTestStepByTestStepFinished" : [ - "17", - "18", - "19", - "21", - "22", - "23", - "25", - "26", - "27" - ], - "findTestStepsFinishedBy" : [ - [ - "17", - "18", - "19" - ], - [ - "21", - "22", - "23" - ], - [ - "25", - "26", - "27" - ] - ], - "findTestStepFinishedAndTestStepBy" : [ - [ - "17", - "17" - ], - [ - "18", - "18" - ], - [ - "19", - "19" - ], - [ - "21", - "21" - ], - [ - "22", - "22" - ], - [ - "23", - "23" - ], - [ - "25", - "25" - ], - [ - "26", - "26" - ], - [ - "27", - "27" - ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson b/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson deleted file mode 100644 index d7d088f9..00000000 --- a/dotnet/Query/QueryTest/Resources/markdown.feature.md.ndjson +++ /dev/null @@ -1,35 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"# Feature: Cheese\n\nThis table is not picked up by Gherkin (not indented 2+ spaces)\n\n| foo | bar |\n| --- | --- |\n| boz | boo |\n\n\n## Rule: Nom nom nom\n\nI love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese.\n\n### Scenario Outline: Ylajali!\n\n* Given some TypeScript code:\n ```typescript\n type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'\n ```\n* And some classic Gherkin:\n ```gherkin\n Given there are 24 apples in Mary's basket\n ```\n* When we use a data table and attach something and then \n | name | age |\n | ---- | --: |\n | Bill | 3 |\n | Jane | 6 |\n | Isla | 5 |\n* Then this might or might not run\n\n#### Examples: because we need more tables\n\nThis table is indented 2 spaces, so Gherkin will pick it up\n\n | what |\n | ---- |\n | fail |\n | pass |\n\nAnd oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent:\n\n| cheese |\n| -------- |\n| gouda |\n| gamalost |\n","mediaType":"text/x.cucumber.gherkin+markdown","uri":"samples/markdown/markdown.feature.md"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"15","keyword":"Examples","location":{"column":6,"line":32},"name":"because we need more tables","tableBody":[{"cells":[{"location":{"column":5,"line":38},"value":"fail"}],"id":"13","location":{"column":3,"line":38}},{"cells":[{"location":{"column":5,"line":39},"value":"pass"}],"id":"14","location":{"column":3,"line":39}}],"tableHeader":{"cells":[{"location":{"column":5,"line":36},"value":"what"}],"id":"12","location":{"column":3,"line":36}},"tags":[]}],"id":"16","keyword":"Scenario Outline","location":{"column":5,"line":14},"name":"Ylajali!","steps":[{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","delimiter":"```","location":{"column":3,"line":17},"mediaType":"typescript"},"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":3,"line":16},"text":"some TypeScript code:"},{"docString":{"content":"Given there are 24 apples in Mary's basket","delimiter":"```","location":{"column":3,"line":21},"mediaType":"gherkin"},"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":3,"line":20},"text":"some classic Gherkin:"},{"dataTable":{"location":{"column":3,"line":25},"rows":[{"cells":[{"location":{"column":5,"line":25},"value":"name"},{"location":{"column":12,"line":25},"value":"age"}],"id":"6","location":{"column":3,"line":25}},{"cells":[{"location":{"column":5,"line":27},"value":"Bill"},{"location":{"column":14,"line":27},"value":"3"}],"id":"7","location":{"column":3,"line":27}},{"cells":[{"location":{"column":5,"line":28},"value":"Jane"},{"location":{"column":14,"line":28},"value":"6"}],"id":"8","location":{"column":3,"line":28}},{"cells":[{"location":{"column":5,"line":29},"value":"Isla"},{"location":{"column":14,"line":29},"value":"5"}],"id":"9","location":{"column":3,"line":29}}]},"id":"10","keyword":"When ","keywordType":"Action","location":{"column":3,"line":24},"text":"we use a data table and attach something and then "},{"id":"11","keyword":"Then ","keywordType":"Outcome","location":{"column":3,"line":30},"text":"this might or might not run"}],"tags":[]}}],"description":"","id":"17","keyword":"Rule","location":{"column":4,"line":10},"name":"Nom nom nom","tags":[]}}],"description":"","keyword":"Feature","language":"en","location":{"column":3,"line":1},"name":"Cheese","tags":[]},"uri":"samples/markdown/markdown.feature.md"}} -{"pickle":{"astNodeIds":["16","13"],"id":"22","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","13"],"id":"18","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","13"],"id":"19","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","13"],"id":"20","text":"we use a data table and attach something and then fail","type":"Action"},{"astNodeIds":["11","13"],"id":"21","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} -{"pickle":{"astNodeIds":["16","14"],"id":"27","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","14"],"id":"23","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","14"],"id":"24","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","14"],"id":"25","text":"we use a data table and attach something and then pass","type":"Action"},{"astNodeIds":["11","14"],"id":"26","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} -{"stepDefinition":{"id":"0","pattern":{"source":"some TypeScript code:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"some classic Gherkin:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"we use a data table and attach something and then {word}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"this might or might not run","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"testRunStarted":{"id":"28","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"33","pickleId":"22","testRunStartedId":"28","testSteps":[{"id":"29","pickleStepId":"18","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"30","pickleStepId":"19","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"31","pickleStepId":"20","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"fail"},"parameterTypeName":"word"}]}]},{"id":"32","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"38","pickleId":"27","testRunStartedId":"28","testSteps":[{"id":"34","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"35","pickleStepId":"24","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"36","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"pass"},"parameterTypeName":"word"}]}]},{"id":"37","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"39","testCaseId":"33","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"29","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"30","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"31","timestamp":{"nanos":6000000,"seconds":0}}} -{"attachment":{"body":"We are logging some plain text (fail)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"39","testStepId":"31"}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"You asked me to fail","type":"Error"},"message":"You asked me to fail\nsamples/markdown/markdown.feature.md:24\nsamples/markdown/markdown.feature.md:38","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"32","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"32","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"40","testCaseId":"38","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"34","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"35","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"36","timestamp":{"nanos":16000000,"seconds":0}}} -{"attachment":{"body":"We are logging some plain text (pass)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"40","testStepId":"36"}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"37","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"28","timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson b/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson deleted file mode 100644 index 6d974e09..00000000 --- a/dotnet/Query/QueryTest/Resources/minimal.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: minimal\n \n Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list\n \n Scenario: cukes\n Given I have 42 cukes in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/minimal/minimal.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":9},"name":"cukes","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"I have 42 cukes in my belly"}],"tags":[]}}],"description":" Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"minimal","tags":[]},"uri":"samples/minimal/minimal.feature"}} -{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cukes","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 cukes in my belly","type":"Context"}],"tags":[],"uri":"samples/minimal/minimal.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} cukes in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/minimal/minimal.feature.ts"}}} -{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json b/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json deleted file mode 100644 index c4892efa..00000000 --- a/dotnet/Query/QueryTest/Resources/minimal.feature.query-results.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 1, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 0, - "AMBIGUOUS" : 0, - "FAILED" : 0 - }, - "countTestCasesStarted" : 1, - "findAllPickles" : 1, - "findAllPickleSteps" : 1, - "findAllTestCaseStarted" : 1, - "findAllTestSteps" : 1, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "minimal", - [ - "8" - ] - ] - ], - "findFeatureBy" : [ - "minimal" - ], - "findLocationOf" : [ - { - "line" : 9, - "column" : 3 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - "PASSED" - ], - "findNameOf" : { - "long" : [ - "minimal - cukes" - ], - "excludeFeatureName" : [ - "cukes" - ], - "longPickleName" : [ - "minimal - cukes" - ], - "short" : [ - "cukes" - ], - "shortPickleName" : [ - "cukes" - ] - }, - "findPickleBy" : [ - "cukes" - ], - "findPickleStepBy" : [ - "I have 42 cukes in my belly" - ], - "findStepBy" : [ - "I have 42 cukes in my belly" - ], - "findTestCaseBy" : [ - "7" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 3000000 - } - ], - "findTestCaseFinishedBy" : [ - "8" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 5000000 - }, - "findTestRunFinished" : { - "success" : true, - "timestamp" : { - "seconds" : 0, - "nanos" : 5000000 - }, - "testRunStartedId" : "5" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "5" - }, - "findTestStepByTestStepStarted" : [ - "6" - ], - "findTestStepByTestStepFinished" : [ - "6" - ], - "findTestStepsFinishedBy" : [ - [ - "6" - ] - ], - "findTestStepFinishedAndTestStepBy" : [ - [ - "6", - "6" - ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson b/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson deleted file mode 100644 index f538d6f4..00000000 --- a/dotnet/Query/QueryTest/Resources/parameter-types.feature.ndjson +++ /dev/null @@ -1,13 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Parameter Types\n Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions.\n\n This lets you define a precise domain-specific vocabulary which can be used to\n generate a glossary with examples taken from your scenarios.\n\n Parameter types also enable you to transform strings and tables into different types.\n\n Scenario: Flight transformer\n Given LHR-CDG has been delayed\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/parameter-types/parameter-types.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":10},"name":"Flight transformer","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"LHR-CDG has been delayed"}],"tags":[]}}],"description":" Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions.\n\n This lets you define a precise domain-specific vocabulary which can be used to\n generate a glossary with examples taken from your scenarios.\n\n Parameter types also enable you to transform strings and tables into different types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/parameter-types/parameter-types.feature"}} -{"pickle":{"astNodeIds":["3"],"id":"5","language":"en","name":"Flight transformer","steps":[{"astNodeIds":["2"],"id":"4","text":"LHR-CDG has been delayed","type":"Context"}],"tags":[],"uri":"samples/parameter-types/parameter-types.feature"}} -{"parameterType":{"id":"0","name":"flight","preferForRegularExpressionMatch":false,"regularExpressions":["([A-Z]{3})-([A-Z]{3})"],"sourceReference":{"location":{"line":8},"uri":"samples/parameter-types/parameter-types.feature.ts"},"useForSnippets":true}} -{"stepDefinition":{"id":"1","pattern":{"source":"{flight} has been delayed","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/parameter-types/parameter-types.feature.ts"}}} -{"testRunStarted":{"id":"6","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"8","pickleId":"5","testRunStartedId":"6","testSteps":[{"id":"7","pickleStepId":"4","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[],"start":0,"value":"LHR"},{"children":[],"start":4,"value":"CDG"}],"start":0,"value":"LHR-CDG"},"parameterTypeName":"flight"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"9","testCaseId":"8","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"9","testStepId":"7","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"9","testStepId":"7","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"9","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"6","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/pending.feature.ndjson b/dotnet/Query/QueryTest/Resources/pending.feature.ndjson deleted file mode 100644 index 5ece61bc..00000000 --- a/dotnet/Query/QueryTest/Resources/pending.feature.ndjson +++ /dev/null @@ -1,30 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Pending steps\n During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.\n\n Scenario: Unimplemented step signals pending status\n Given an unimplemented pending step\n\n Scenario: Steps before unimplemented steps are executed\n Given an implemented non-pending step\n And an unimplemented pending step\n\n Scenario: Steps after unimplemented steps are skipped\n Given an unimplemented pending step\n And an implemented step that is skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/pending/pending.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":9},"name":"Unimplemented step signals pending status","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"an unimplemented pending step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":12},"name":"Steps before unimplemented steps are executed","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":13},"text":"an implemented non-pending step"},{"id":"6","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":14},"text":"an unimplemented pending step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":16},"name":"Steps after unimplemented steps are skipped","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":17},"text":"an unimplemented pending step"},{"id":"9","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":18},"text":"an implemented step that is skipped"}],"tags":[]}}],"description":" During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Pending steps","tags":[]},"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["4"],"id":"12","language":"en","name":"Unimplemented step signals pending status","steps":[{"astNodeIds":["3"],"id":"11","text":"an unimplemented pending step","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"Steps before unimplemented steps are executed","steps":[{"astNodeIds":["5"],"id":"13","text":"an implemented non-pending step","type":"Context"},{"astNodeIds":["6"],"id":"14","text":"an unimplemented pending step","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"18","language":"en","name":"Steps after unimplemented steps are skipped","steps":[{"astNodeIds":["8"],"id":"16","text":"an unimplemented pending step","type":"Context"},{"astNodeIds":["9"],"id":"17","text":"an implemented step that is skipped","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"an implemented non-pending step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/pending/pending.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"an implemented step that is skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/pending/pending.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"an unimplemented pending step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/pending/pending.feature.ts"}}} -{"testRunStarted":{"id":"19","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"21","pickleId":"12","testRunStartedId":"19","testSteps":[{"id":"20","pickleStepId":"11","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"24","pickleId":"15","testRunStartedId":"19","testSteps":[{"id":"22","pickleStepId":"13","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"23","pickleStepId":"14","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"27","pickleId":"18","testRunStartedId":"19","testSteps":[{"id":"25","pickleStepId":"16","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"26","pickleStepId":"17","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"21","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"20","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"20","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"24","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"22","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"23","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"23","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"27","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"25","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"TODO","status":"PENDING"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"26","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"26","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"19","timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/retry.feature.ndjson b/dotnet/Query/QueryTest/Resources/retry.feature.ndjson deleted file mode 100644 index 4143f1d2..00000000 --- a/dotnet/Query/QueryTest/Resources/retry.feature.ndjson +++ /dev/null @@ -1,59 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Retry\n Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED won't trigger a retry, as they are not\n going to pass however many times we attempt them.\n\n Scenario: Test cases that pass aren't retried\n Given a step that always passes\n\n Scenario: Test cases that fail are retried if within the --retry limit\n Given a step that passes the second time\n\n Scenario: Test cases that fail will continue to retry up to the --retry limit\n Given a step that passes the third time\n\n Scenario: Test cases won't retry after failing more than the --retry limit\n Given a step that always fails\n\n Scenario: Test cases won't retry when the status is UNDEFINED\n Given a non-existent step\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/retry/retry.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":8},"name":"Test cases that pass aren't retried","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"a step that always passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":11},"name":"Test cases that fail are retried if within the --retry limit","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"a step that passes the second time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":14},"name":"Test cases that fail will continue to retry up to the --retry limit","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":15},"text":"a step that passes the third time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":17},"name":"Test cases won't retry after failing more than the --retry limit","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that always fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":20},"name":"Test cases won't retry when the status is UNDEFINED","steps":[{"id":"12","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":21},"text":"a non-existent step"}],"tags":[]}}],"description":" Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED won't trigger a retry, as they are not\n going to pass however many times we attempt them.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Retry","tags":[]},"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["5"],"id":"15","language":"en","name":"Test cases that pass aren't retried","steps":[{"astNodeIds":["4"],"id":"14","text":"a step that always passes","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"17","language":"en","name":"Test cases that fail are retried if within the --retry limit","steps":[{"astNodeIds":["6"],"id":"16","text":"a step that passes the second time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"19","language":"en","name":"Test cases that fail will continue to retry up to the --retry limit","steps":[{"astNodeIds":["8"],"id":"18","text":"a step that passes the third time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["11"],"id":"21","language":"en","name":"Test cases won't retry after failing more than the --retry limit","steps":[{"astNodeIds":["10"],"id":"20","text":"a step that always fails","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["13"],"id":"23","language":"en","name":"Test cases won't retry when the status is UNDEFINED","steps":[{"astNodeIds":["12"],"id":"22","text":"a non-existent step","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"a step that always passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that passes the second time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step that passes the third time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"a step that always fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/retry/retry.feature.ts"}}} -{"testRunStarted":{"id":"24","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"26","pickleId":"15","testRunStartedId":"24","testSteps":[{"id":"25","pickleStepId":"14","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"28","pickleId":"17","testRunStartedId":"24","testSteps":[{"id":"27","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"30","pickleId":"19","testRunStartedId":"24","testSteps":[{"id":"29","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"32","pickleId":"21","testRunStartedId":"24","testSteps":[{"id":"31","pickleStepId":"20","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"34","pickleId":"23","testRunStartedId":"24","testSteps":[{"id":"33","pickleStepId":"22","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCaseStarted":{"attempt":0,"id":"35","testCaseId":"26","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"35","testStepId":"25","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"35","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"35","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"36","testCaseId":"28","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"36","testStepId":"27","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"36","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:12","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"36","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"37","testCaseId":"28","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"37","testStepId":"27","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"37","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"37","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"38","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"29","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:15","status":"FAILED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"39","testCaseId":"30","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"29","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:15","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":2,"id":"40","testCaseId":"30","timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"29","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"41","testCaseId":"32","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"41","testStepId":"31","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"41","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"41","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"42","testCaseId":"32","timestamp":{"nanos":29000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"42","testStepId":"31","timestamp":{"nanos":30000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"42","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"42","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":2,"id":"43","testCaseId":"32","timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"43","testStepId":"31","timestamp":{"nanos":34000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"43","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:18","status":"FAILED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"43","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"44","testCaseId":"34","timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"44","testStepId":"33","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"44","testStepId":"33","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"44","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"24","timestamp":{"nanos":41000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/rules.feature.ndjson b/dotnet/Query/QueryTest/Resources/rules.feature.ndjson deleted file mode 100644 index 81ac0e1c..00000000 --- a/dotnet/Query/QueryTest/Resources/rules.feature.ndjson +++ /dev/null @@ -1,47 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Usage of a `Rule`\n You can place scenarios inside rules. This makes it possible to structure Gherkin documents\n in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n\n You can also use the Examples synonym for Scenario to make them even similar.\n\n Rule: A sale cannot happen if the customer does not have enough money\n # Unhappy path\n Example: Not enough money\n Given the customer has 100 cents\n And there are chocolate bars in stock\n When the customer tries to buy a 125 cent chocolate bar\n Then the sale should not happen\n\n # Happy path\n Example: Enough money\n Given the customer has 100 cents\n And there are chocolate bars in stock\n When the customer tries to buy a 75 cent chocolate bar\n Then the sale should happen\n\n @some-tag\n Rule: a sale cannot happen if there is no stock\n # Unhappy path\n Example: No chocolates left\n Given the customer has 100 cents\n And there are no chocolate bars in stock\n When the customer tries to buy a 1 cent chocolate bar\n Then the sale should not happen\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/rules/rules.feature"}} -{"gherkinDocument":{"comments":[{"location":{"column":1,"line":8},"text":" # Unhappy path"},{"location":{"column":1,"line":15},"text":" # Happy path"},{"location":{"column":1,"line":24},"text":" # Unhappy path"}],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"10","keyword":"Example","location":{"column":5,"line":9},"name":"Not enough money","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":10},"text":"the customer has 100 cents"},{"id":"7","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":11},"text":"there are chocolate bars in stock"},{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":7,"line":12},"text":"the customer tries to buy a 125 cent chocolate bar"},{"id":"9","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":13},"text":"the sale should not happen"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Example","location":{"column":5,"line":16},"name":"Enough money","steps":[{"id":"11","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":17},"text":"the customer has 100 cents"},{"id":"12","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":18},"text":"there are chocolate bars in stock"},{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":7,"line":19},"text":"the customer tries to buy a 75 cent chocolate bar"},{"id":"14","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":20},"text":"the sale should happen"}],"tags":[]}}],"description":"","id":"16","keyword":"Rule","location":{"column":3,"line":7},"name":"A sale cannot happen if the customer does not have enough money","tags":[]}},{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"21","keyword":"Example","location":{"column":5,"line":25},"name":"No chocolates left","steps":[{"id":"17","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":26},"text":"the customer has 100 cents"},{"id":"18","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":27},"text":"there are no chocolate bars in stock"},{"id":"19","keyword":"When ","keywordType":"Action","location":{"column":7,"line":28},"text":"the customer tries to buy a 1 cent chocolate bar"},{"id":"20","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":29},"text":"the sale should not happen"}],"tags":[]}}],"description":"","id":"23","keyword":"Rule","location":{"column":3,"line":23},"name":"a sale cannot happen if there is no stock","tags":[{"id":"22","location":{"column":3,"line":22},"name":"@some-tag"}]}}],"description":" You can place scenarios inside rules. This makes it possible to structure Gherkin documents\n in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n\n You can also use the Examples synonym for Scenario to make them even similar.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Usage of a `Rule`","tags":[]},"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"28","language":"en","name":"Not enough money","steps":[{"astNodeIds":["6"],"id":"24","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["7"],"id":"25","text":"there are chocolate bars in stock","type":"Context"},{"astNodeIds":["8"],"id":"26","text":"the customer tries to buy a 125 cent chocolate bar","type":"Action"},{"astNodeIds":["9"],"id":"27","text":"the sale should not happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["15"],"id":"33","language":"en","name":"Enough money","steps":[{"astNodeIds":["11"],"id":"29","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["12"],"id":"30","text":"there are chocolate bars in stock","type":"Context"},{"astNodeIds":["13"],"id":"31","text":"the customer tries to buy a 75 cent chocolate bar","type":"Action"},{"astNodeIds":["14"],"id":"32","text":"the sale should happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["21"],"id":"38","language":"en","name":"No chocolates left","steps":[{"astNodeIds":["17"],"id":"34","text":"the customer has 100 cents","type":"Context"},{"astNodeIds":["18"],"id":"35","text":"there are no chocolate bars in stock","type":"Context"},{"astNodeIds":["19"],"id":"36","text":"the customer tries to buy a 1 cent chocolate bar","type":"Action"},{"astNodeIds":["20"],"id":"37","text":"the sale should not happen","type":"Outcome"}],"tags":[{"astNodeId":"22","name":"@some-tag"}],"uri":"samples/rules/rules.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"the customer has {int} cents","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"there are chocolate bars in stock","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"there are no chocolate bars in stock","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"the customer tries to buy a {int} cent chocolate bar","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"4","pattern":{"source":"the sale should not happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"5","pattern":{"source":"the sale should happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":26},"uri":"samples/rules/rules.feature.ts"}}} -{"testRunStarted":{"id":"39","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"44","pickleId":"28","testRunStartedId":"39","testSteps":[{"id":"40","pickleStepId":"24","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"41","pickleStepId":"25","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"42","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"125"},"parameterTypeName":"int"}]}]},{"id":"43","pickleStepId":"27","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"49","pickleId":"33","testRunStartedId":"39","testSteps":[{"id":"45","pickleStepId":"29","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"46","pickleStepId":"30","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"47","pickleStepId":"31","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"75"},"parameterTypeName":"int"}]}]},{"id":"48","pickleStepId":"32","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"54","pickleId":"38","testRunStartedId":"39","testSteps":[{"id":"50","pickleStepId":"34","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":17,"value":"100"},"parameterTypeName":"int"}]}]},{"id":"51","pickleStepId":"35","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"52","pickleStepId":"36","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"53","pickleStepId":"37","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"55","testCaseId":"44","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"55","testStepId":"40","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"55","testStepId":"40","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"55","testStepId":"41","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"55","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"55","testStepId":"42","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"55","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"55","testStepId":"43","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"55","testStepId":"43","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"55","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"56","testCaseId":"49","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"45","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"46","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"47","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"48","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"56","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"57","testCaseId":"54","timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"50","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"51","timestamp":{"nanos":24000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"52","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"53","timestamp":{"nanos":28000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"53","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"57","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"39","timestamp":{"nanos":31000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json b/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json deleted file mode 100644 index a49b48ed..00000000 --- a/dotnet/Query/QueryTest/Resources/rules.feature.query-results.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "countMostSevereTestStepResultStatus" : { - "UNKNOWN" : 0, - "PASSED" : 3, - "SKIPPED" : 0, - "PENDING" : 0, - "UNDEFINED" : 0, - "AMBIGUOUS" : 0, - "FAILED" : 0 - }, - "countTestCasesStarted" : 3, - "findAllPickles" : 3, - "findAllPickleSteps" : 12, - "findAllTestCaseStarted" : 3, - "findAllTestSteps" : 12, - "findAllTestCaseStartedGroupedByFeature" : [ - [ - "Usage of a `Rule`", - [ - "55", - "56", - "57" - ] - ] - ], - "findFeatureBy" : [ - "Usage of a `Rule`", - "Usage of a `Rule`", - "Usage of a `Rule`" - ], - "findLocationOf" : [ - { - "line" : 9, - "column" : 5 - }, - { - "line" : 16, - "column" : 5 - }, - { - "line" : 25, - "column" : 5 - } - ], - "findMeta" : "fake-cucumber", - "findMostSevereTestStepResultBy" : [ - "PASSED", - "PASSED", - "PASSED" - ], - "findNameOf" : { - "long" : [ - "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Not enough money", - "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Enough money", - "Usage of a `Rule` - a sale cannot happen if there is no stock - No chocolates left" - ], - "excludeFeatureName" : [ - "A sale cannot happen if the customer does not have enough money - Not enough money", - "A sale cannot happen if the customer does not have enough money - Enough money", - "a sale cannot happen if there is no stock - No chocolates left" - ], - "longPickleName" : [ - "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Not enough money", - "Usage of a `Rule` - A sale cannot happen if the customer does not have enough money - Enough money", - "Usage of a `Rule` - a sale cannot happen if there is no stock - No chocolates left" - ], - "short" : [ - "Not enough money", - "Enough money", - "No chocolates left" - ], - "shortPickleName" : [ - "Not enough money", - "Enough money", - "No chocolates left" - ] - }, - "findPickleBy" : [ - "Not enough money", - "Enough money", - "No chocolates left" - ], - "findPickleStepBy" : [ - "the customer has 100 cents", - "there are chocolate bars in stock", - "the customer tries to buy a 125 cent chocolate bar", - "the sale should not happen", - "the customer has 100 cents", - "there are chocolate bars in stock", - "the customer tries to buy a 75 cent chocolate bar", - "the sale should happen", - "the customer has 100 cents", - "there are no chocolate bars in stock", - "the customer tries to buy a 1 cent chocolate bar", - "the sale should not happen" - ], - "findStepBy" : [ - "the customer has 100 cents", - "there are chocolate bars in stock", - "the customer tries to buy a 125 cent chocolate bar", - "the sale should not happen", - "the customer has 100 cents", - "there are chocolate bars in stock", - "the customer tries to buy a 75 cent chocolate bar", - "the sale should happen", - "the customer has 100 cents", - "there are no chocolate bars in stock", - "the customer tries to buy a 1 cent chocolate bar", - "the sale should not happen" - ], - "findTestCaseBy" : [ - "44", - "49", - "54" - ], - "findTestCaseDurationBy" : [ - { - "seconds" : 0, - "nanos" : 9000000 - }, - { - "seconds" : 0, - "nanos" : 9000000 - }, - { - "seconds" : 0, - "nanos" : 9000000 - } - ], - "findTestCaseFinishedBy" : [ - "55", - "56", - "57" - ], - "findTestRunDuration" : { - "seconds" : 0, - "nanos" : 31000000 - }, - "findTestRunFinished" : { - "success" : true, - "timestamp" : { - "seconds" : 0, - "nanos" : 31000000 - }, - "testRunStartedId" : "39" - }, - "findTestRunStarted" : { - "timestamp" : { - "seconds" : 0, - "nanos" : 0 - }, - "id" : "39" - }, - "findTestStepByTestStepStarted" : [ - "40", - "41", - "42", - "43", - "45", - "46", - "47", - "48", - "50", - "51", - "52", - "53" - ], - "findTestStepByTestStepFinished" : [ - "40", - "41", - "42", - "43", - "45", - "46", - "47", - "48", - "50", - "51", - "52", - "53" - ], - "findTestStepsFinishedBy" : [ - [ - "40", - "41", - "42", - "43" - ], - [ - "45", - "46", - "47", - "48" - ], - [ - "50", - "51", - "52", - "53" - ] - ], - "findTestStepFinishedAndTestStepBy" : [ - [ - "40", - "40" - ], - [ - "41", - "41" - ], - [ - "42", - "42" - ], - [ - "43", - "43" - ], - [ - "45", - "45" - ], - [ - "46", - "46" - ], - [ - "47", - "47" - ], - [ - "48", - "48" - ], - [ - "50", - "50" - ], - [ - "51", - "51" - ], - [ - "52", - "52" - ], - [ - "53", - "53" - ] - ] -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson b/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson deleted file mode 100644 index 3b1808ba..00000000 --- a/dotnet/Query/QueryTest/Resources/skipped.feature.ndjson +++ /dev/null @@ -1,33 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Skipping scenarios\n\n Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by raising a particular kind of exception status (For example PENDING or SKIPPED).\n\n This can be useful in certain situations e.g. the current environment doesn't have\n the right conditions for running a particular scenario.\n\n @skip\n Scenario: Skipping from a Before hook\n Given a step that is skipped\n\n Scenario: Skipping from a step doesn't affect the previous steps\n Given a step that does not skip\n And I skip a step\n\n Scenario: Skipping from a step causes the rest of the scenario to be skipped\n Given I skip a step\n And a step that is skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/skipped/skipped.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Skipping from a Before hook","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that is skipped"}],"tags":[{"id":"5","location":{"column":3,"line":9},"name":"@skip"}]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":13},"name":"Skipping from a step doesn't affect the previous steps","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"a step that does not skip"},{"id":"8","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":15},"text":"I skip a step"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":17},"name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"I skip a step"},{"id":"11","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":19},"text":"a step that is skipped"}],"tags":[]}}],"description":" Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by raising a particular kind of exception status (For example PENDING or SKIPPED).\n\n This can be useful in certain situations e.g. the current environment doesn't have\n the right conditions for running a particular scenario.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Skipping scenarios","tags":[]},"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Skipping from a Before hook","steps":[{"astNodeIds":["4"],"id":"13","text":"a step that is skipped","type":"Context"}],"tags":[{"astNodeId":"5","name":"@skip"}],"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Skipping from a step doesn't affect the previous steps","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that does not skip","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"I skip a step","type":"Context"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["12"],"id":"20","language":"en","name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"astNodeIds":["10"],"id":"18","text":"I skip a step","type":"Context"},{"astNodeIds":["11"],"id":"19","text":"a step that is skipped","type":"Context"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that does not skip","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/skipped/skipped.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step that is skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/skipped/skipped.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"I skip a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":15},"uri":"samples/skipped/skipped.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/skipped/skipped.feature.ts"},"tagExpression":"@skip","type":"BEFORE_TEST_CASE"}} -{"testRunStarted":{"id":"21","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"24","pickleId":"14","testRunStartedId":"21","testSteps":[{"hookId":"0","id":"22"},{"id":"23","pickleStepId":"13","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"27","pickleId":"17","testRunStartedId":"21","testSteps":[{"id":"25","pickleStepId":"15","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"26","pickleStepId":"16","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"30","pickleId":"20","testRunStartedId":"21","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"29","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"24","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"22","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"23","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"23","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"27","timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"25","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"26","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"33","testCaseId":"30","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"33","testStepId":"28","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"33","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"33","testStepId":"29","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"33","testStepId":"29","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"33","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"testRunStartedId":"21","timestamp":{"nanos":19000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson b/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson deleted file mode 100644 index 49d10f54..00000000 --- a/dotnet/Query/QueryTest/Resources/stack-traces.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Stack traces\n Stack traces can help you diagnose the source of a bug.\n Cucumber provides helpful stack traces that includes the stack frames from the\n Gherkin document and remove uninteresting frames by default\n\n The first line of the stack trace will contain a reference to the feature file.\n\n Scenario: A failing step\n When a step throws an exception\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/stack-traces/stack-traces.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":8},"name":"A failing step","steps":[{"id":"1","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"a step throws an exception"}],"tags":[]}}],"description":" Stack traces can help you diagnose the source of a bug.\n Cucumber provides helpful stack traces that includes the stack frames from the\n Gherkin document and remove uninteresting frames by default\n\n The first line of the stack trace will contain a reference to the feature file.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Stack traces","tags":[]},"uri":"samples/stack-traces/stack-traces.feature"}} -{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"A failing step","steps":[{"astNodeIds":["1"],"id":"3","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/stack-traces/stack-traces.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/stack-traces/stack-traces.feature.ts"}}} -{"testRunStarted":{"id":"5","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"7","pickleId":"4","testRunStartedId":"5","testSteps":[{"id":"6","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"BOOM","type":"Error"},"message":"BOOM\nsamples/stack-traces/stack-traces.feature:9","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"5","timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson b/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson deleted file mode 100644 index aafa4d47..00000000 --- a/dotnet/Query/QueryTest/Resources/undefined.feature.ndjson +++ /dev/null @@ -1,29 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Undefined steps\n\n At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario is not able to run and so the step status\n will be UNDEFINED, with subsequent steps being SKIPPED and the overall result will be FAILURE\n\n Scenario: An undefined step causes a failure\n Given a step that is yet to be defined\n\n Scenario: Steps before undefined steps are executed\n Given an implemented step\n And a step that is yet to be defined\n\n Scenario: Steps after undefined steps are skipped\n Given a step that is yet to be defined\n And a step that will be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/undefined/undefined.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":7},"name":"An undefined step causes a failure","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":8},"text":"a step that is yet to be defined"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Steps before undefined steps are executed","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"an implemented step"},{"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":12},"text":"a step that is yet to be defined"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":14},"name":"Steps after undefined steps are skipped","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":15},"text":"a step that is yet to be defined"},{"id":"8","keyword":"And ","keywordType":"Conjunction","location":{"column":5,"line":16},"text":"a step that will be skipped"}],"tags":[]}}],"description":" At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario is not able to run and so the step status\n will be UNDEFINED, with subsequent steps being SKIPPED and the overall result will be FAILURE","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Undefined steps","tags":[]},"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["3"],"id":"11","language":"en","name":"An undefined step causes a failure","steps":[{"astNodeIds":["2"],"id":"10","text":"a step that is yet to be defined","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Steps before undefined steps are executed","steps":[{"astNodeIds":["4"],"id":"12","text":"an implemented step","type":"Context"},{"astNodeIds":["5"],"id":"13","text":"a step that is yet to be defined","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Steps after undefined steps are skipped","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that is yet to be defined","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that will be skipped","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/undefined/undefined.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that will be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/undefined/undefined.feature.ts"}}} -{"testRunStarted":{"id":"18","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"20","pickleId":"11","testRunStartedId":"18","testSteps":[{"id":"19","pickleStepId":"10","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCase":{"id":"23","pickleId":"14","testRunStartedId":"18","testSteps":[{"id":"21","pickleStepId":"12","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"22","pickleStepId":"13","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCase":{"id":"26","pickleId":"17","testRunStartedId":"18","testSteps":[{"id":"24","pickleStepId":"15","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"25","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"27","testStepId":"19","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"27","testStepId":"19","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"23","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"21","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"22","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"26","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"24","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"24","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"25","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"25","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"18","timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson b/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson deleted file mode 100644 index 40f7ebd4..00000000 --- a/dotnet/Query/QueryTest/Resources/unknown-parameter-type.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"darwin","version":"23.6.0"},"protocolVersion":"27.0.0","runtime":{"name":"node.js","version":"22.7.0"}}} -{"source":{"data":"Feature: Parameter Types\n Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.\n\n Scenario: undefined parameter type\n Given CDG is closed because of a strike\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"1","keyword":"Scenario","location":{"column":3,"line":5},"name":"undefined parameter type","steps":[{"id":"0","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"CDG is closed because of a strike"}],"tags":[]}}],"description":" Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"pickle":{"astNodeIds":["1"],"id":"3","language":"en","name":"undefined parameter type","steps":[{"astNodeIds":["0"],"id":"2","text":"CDG is closed because of a strike","type":"Context"}],"tags":[],"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"undefinedParameterType":{"expression":"{airport} is closed because of a strike","name":"airport"}} -{"testRunStarted":{"id":"4","timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"6","pickleId":"3","testRunStartedId":"4","testSteps":[{"id":"5","pickleStepId":"2","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"testRunStartedId":"4","timestamp":{"nanos":5000000,"seconds":0}}} From 3327bcfdfb32a0e9bc51d949d809ba2a30dd4eb0 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:54:33 -0500 Subject: [PATCH 6/8] Enhance Lineage equality and improve timestamp handling - Updated `Lineage` class to implement `IEquatable`, adding a specific `Equals` method and `GetHashCode`. - Simplified timestamp conversion in `Query` class using `ToDateTimeOffset()` extension method. - Changed `TimestampComparer` visibility from public to internal. - Added `TimestampExtensions` class for converting `Timestamp` to `DateTimeOffset`. - Minor fix in `QueryAcceptanceTest.cs` to default null names to empty strings. --- .../{LineageReducer.cs => ILineageReducer.cs} | 0 dotnet/Query/Query/Lineage.cs | 10 +++++----- dotnet/Query/Query/LineageReducerAscending.cs | 2 +- dotnet/Query/Query/LineageReducerDescending.cs | 2 +- dotnet/Query/Query/Query.cs | 16 ++++------------ dotnet/Query/Query/TimestampComparer.cs | 2 +- dotnet/Query/Query/TimestampExtensions.cs | 17 +++++++++++++++++ dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 2 +- 8 files changed, 30 insertions(+), 21 deletions(-) rename dotnet/Query/Query/{LineageReducer.cs => ILineageReducer.cs} (100%) create mode 100644 dotnet/Query/Query/TimestampExtensions.cs diff --git a/dotnet/Query/Query/LineageReducer.cs b/dotnet/Query/Query/ILineageReducer.cs similarity index 100% rename from dotnet/Query/Query/LineageReducer.cs rename to dotnet/Query/Query/ILineageReducer.cs diff --git a/dotnet/Query/Query/Lineage.cs b/dotnet/Query/Query/Lineage.cs index e40f8822..b2dd324b 100644 --- a/dotnet/Query/Query/Lineage.cs +++ b/dotnet/Query/Query/Lineage.cs @@ -12,7 +12,7 @@ namespace Io.Cucumber.Query; /// /// See . /// -public sealed class Lineage +public class Lineage : IEquatable { private readonly GherkinDocument _document; private readonly Feature? _feature; @@ -69,10 +69,10 @@ private Lineage( public int? ExamplesIndex => _examplesIndex; public int? ExampleIndex => _exampleIndex; - public override bool Equals(object? obj) + public bool Equals(Lineage? other) { - if (ReferenceEquals(this, obj)) return true; - if (obj is not Lineage other) return false; + if (ReferenceEquals(this, other)) return true; + if (other is null) return false; return Equals(_document, other._document) && Equals(_feature, other._feature) && Equals(_rule, other._rule) @@ -83,7 +83,7 @@ public override bool Equals(object? obj) && Equals(_exampleIndex, other._exampleIndex); } - // Rest of the code remains unchanged + public override bool Equals(object? obj) => Equals(obj as Lineage); public override int GetHashCode() { diff --git a/dotnet/Query/Query/LineageReducerAscending.cs b/dotnet/Query/Query/LineageReducerAscending.cs index b3c9f10b..b7ad08cf 100644 --- a/dotnet/Query/Query/LineageReducerAscending.cs +++ b/dotnet/Query/Query/LineageReducerAscending.cs @@ -3,7 +3,7 @@ namespace Io.Cucumber.Query { - // Faithful port of io.cucumber.query.LineageReducerAscending (Java) + // port of io.cucumber.query.LineageReducerAscending (Java) public class LineageReducerAscending : ILineageReducer { private readonly Func> _collectorSupplier; diff --git a/dotnet/Query/Query/LineageReducerDescending.cs b/dotnet/Query/Query/LineageReducerDescending.cs index a525458e..92bf0644 100644 --- a/dotnet/Query/Query/LineageReducerDescending.cs +++ b/dotnet/Query/Query/LineageReducerDescending.cs @@ -3,7 +3,7 @@ namespace Io.Cucumber.Query { - // Faithful port of io.cucumber.query.LineageReducerDescending (Java) + // port of io.cucumber.query.LineageReducerDescending (Java) public class LineageReducerDescending : ILineageReducer { private readonly Func> _collectorSupplier; diff --git a/dotnet/Query/Query/Query.cs b/dotnet/Query/Query/Query.cs index 699d1911..d8055a12 100644 --- a/dotnet/Query/Query/Query.cs +++ b/dotnet/Query/Query/Query.cs @@ -192,8 +192,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => var finished = FindTestCaseFinishedBy(testCaseStarted)?.Timestamp; if (finished != null) { - var startTime = TimestampToDateTimeOffset(started); - var finishTime = TimestampToDateTimeOffset(finished); + var startTime = started.ToDateTimeOffset(); + var finishTime = finished.ToDateTimeOffset(); return finishTime - startTime; } return null; @@ -210,8 +210,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => // Java: if (testRunStarted == null || testRunFinished == null) return Optional.empty(); if (_testRunStarted == null || _testRunFinished == null) return null; - var start = TimestampToDateTimeOffset(_testRunStarted.Timestamp); - var finish = TimestampToDateTimeOffset(_testRunFinished.Timestamp); + var start = _testRunStarted.Timestamp.ToDateTimeOffset(); + var finish = _testRunFinished.Timestamp.ToDateTimeOffset(); return finish - start; } @@ -269,14 +269,6 @@ public IList FindTestStepsFinishedBy(TestCaseStarted testCaseS return mostSevere?.TestStepResult; } - private static DateTimeOffset TimestampToDateTimeOffset(Timestamp timestamp) - { - // Java: Convertor.toInstant(timestamp) - // C#: Timestamp has Seconds and Nanos - var dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp.Seconds); - return dateTime.AddTicks(timestamp.Nanos / 100); - } - // Update methods for each message type (ported from Java) internal void UpdateAttachment(Attachment attachment) { diff --git a/dotnet/Query/Query/TimestampComparer.cs b/dotnet/Query/Query/TimestampComparer.cs index 1cd133e4..566750e1 100644 --- a/dotnet/Query/Query/TimestampComparer.cs +++ b/dotnet/Query/Query/TimestampComparer.cs @@ -4,7 +4,7 @@ namespace Io.Cucumber.Query { // Port of io.cucumber.query.TimestampComparator (Java) - public class TimestampComparer : IComparer + internal class TimestampComparer : IComparer { public int Compare(Timestamp a, Timestamp b) { diff --git a/dotnet/Query/Query/TimestampExtensions.cs b/dotnet/Query/Query/TimestampExtensions.cs new file mode 100644 index 00000000..62c1cbdd --- /dev/null +++ b/dotnet/Query/Query/TimestampExtensions.cs @@ -0,0 +1,17 @@ +using Io.Cucumber.Messages.Types; +using System; + +namespace Io.Cucumber.Query +{ + internal static class TimestampExtensions + { + + internal static DateTimeOffset ToDateTimeOffset(this Timestamp timestamp) + { + // Java: Convertor.toInstant(timestamp) + // C#: Timestamp has Seconds and Nanos + var dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp.Seconds); + return dateTime.AddTicks(timestamp.Nanos / 100); + } + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs index 4649e0c8..ef2139c9 100644 --- a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -105,7 +105,7 @@ private static string WriteQueryResults(TestCase testCase) ["findAllTestCaseStartedGroupedByFeature"] = query.FindAllTestCaseStartedGroupedByFeature() .Select(entry => new object[] { - entry.Key?.Name, + entry.Key?.Name ?? String.Empty, entry.Value.Select(tcs => tcs.Id).ToList() }).ToList(), ["findAttachmentsBy"] = query.FindAllTestCaseStarted() From 0c69735f3d05dfc869f125cc5bfd2198c2bbe42d Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Thu, 17 Jul 2025 11:21:15 -0500 Subject: [PATCH 7/8] cleanup - per review comments --- dotnet/Query/Query/Query.cs | 9 +++++---- dotnet/Query/Query/TimestampExtensions.cs | 17 ----------------- dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 2 +- dotnet/Query/QueryTest/QueryTest.csproj | 9 --------- 4 files changed, 6 insertions(+), 31 deletions(-) delete mode 100644 dotnet/Query/Query/TimestampExtensions.cs diff --git a/dotnet/Query/Query/Query.cs b/dotnet/Query/Query/Query.cs index d8055a12..8a745785 100644 --- a/dotnet/Query/Query/Query.cs +++ b/dotnet/Query/Query/Query.cs @@ -5,6 +5,7 @@ using System.Linq; using Io.Cucumber.Messages.Types; using System.Collections.Concurrent; +using Cucumber.Messages; namespace Io.Cucumber.Query; @@ -192,8 +193,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => var finished = FindTestCaseFinishedBy(testCaseStarted)?.Timestamp; if (finished != null) { - var startTime = started.ToDateTimeOffset(); - var finishTime = finished.ToDateTimeOffset(); + var startTime = Converters.ToDateTime(started); + var finishTime = Converters.ToDateTime(finished); return finishTime - startTime; } return null; @@ -210,8 +211,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => // Java: if (testRunStarted == null || testRunFinished == null) return Optional.empty(); if (_testRunStarted == null || _testRunFinished == null) return null; - var start = _testRunStarted.Timestamp.ToDateTimeOffset(); - var finish = _testRunFinished.Timestamp.ToDateTimeOffset(); + var start = Converters.ToDateTime(_testRunStarted.Timestamp); + var finish = Converters.ToDateTime(_testRunFinished.Timestamp); return finish - start; } diff --git a/dotnet/Query/Query/TimestampExtensions.cs b/dotnet/Query/Query/TimestampExtensions.cs deleted file mode 100644 index 62c1cbdd..00000000 --- a/dotnet/Query/Query/TimestampExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Io.Cucumber.Messages.Types; -using System; - -namespace Io.Cucumber.Query -{ - internal static class TimestampExtensions - { - - internal static DateTimeOffset ToDateTimeOffset(this Timestamp timestamp) - { - // Java: Convertor.toInstant(timestamp) - // C#: Timestamp has Seconds and Nanos - var dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp.Seconds); - return dateTime.AddTicks(timestamp.Nanos / 100); - } - } -} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs index ef2139c9..1cd3b447 100644 --- a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -208,7 +208,7 @@ private static Stream ReadResourceAsStream(string resourceName) if (assemblyLocation == null) throw new InvalidOperationException("Assembly location could not be determined."); - var fullName = Path.Combine(assemblyLocation, "testdata", resourceName); + var fullName = Path.Combine(assemblyLocation, "..\\..\\..\\..\\..\\..\\testdata", resourceName); if (!File.Exists(fullName)) throw new FileNotFoundException($"Resource {fullName} not found."); return File.OpenRead(fullName); diff --git a/dotnet/Query/QueryTest/QueryTest.csproj b/dotnet/Query/QueryTest/QueryTest.csproj index 1ded2e6c..77bd71e4 100644 --- a/dotnet/Query/QueryTest/QueryTest.csproj +++ b/dotnet/Query/QueryTest/QueryTest.csproj @@ -28,13 +28,4 @@ - - - Always - - - Always - - - From 828599ee838e2800f1a02984e70e59601a390035 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Fri, 18 Jul 2025 09:07:00 -0500 Subject: [PATCH 8/8] Modified to conform to changes coming in Query #84 (Deprecate lineage derived methods). --- dotnet/Query/Query/NamingCollector.cs | 20 +-- dotnet/Query/Query/NamingStrategy.cs | 39 +++--- dotnet/Query/Query/Query.cs | 100 --------------- .../QueryTest/NamingStrategyAcceptanceTest.cs | 119 ++++++++++++++++++ dotnet/Query/QueryTest/QueryAcceptanceTest.cs | 17 --- 5 files changed, 149 insertions(+), 146 deletions(-) create mode 100644 dotnet/Query/QueryTest/NamingStrategyAcceptanceTest.cs diff --git a/dotnet/Query/Query/NamingCollector.cs b/dotnet/Query/Query/NamingCollector.cs index 6d518123..c959a7b6 100644 --- a/dotnet/Query/Query/NamingCollector.cs +++ b/dotnet/Query/Query/NamingCollector.cs @@ -13,20 +13,20 @@ internal class NamingCollector : ICollector // There are at most 5 levels to a feature file. private readonly List parts = new List(5); private readonly string delimiter = " - "; - private readonly Strategy strategy; - private readonly FeatureName featureName; - private readonly ExampleName exampleName; + private readonly NamingStrategy.Strategy strategy; + private readonly NamingStrategy.FeatureName featureName; + private readonly NamingStrategy.ExampleName exampleName; private string scenarioName; private bool isExample; private int examplesIndex; - public static Func Of(Strategy strategy, FeatureName featureName, ExampleName exampleName) + public static Func Of(NamingStrategy.Strategy strategy, NamingStrategy.FeatureName featureName, NamingStrategy.ExampleName exampleName) { return () => new NamingCollector(strategy, featureName, exampleName); } - public NamingCollector(Strategy strategy, FeatureName featureName, ExampleName exampleName) + public NamingCollector(NamingStrategy.Strategy strategy, NamingStrategy.FeatureName featureName, NamingStrategy.ExampleName exampleName) { this.strategy = strategy; this.featureName = featureName; @@ -36,7 +36,7 @@ public NamingCollector(Strategy strategy, FeatureName featureName, ExampleName e public void Add(GherkinDocument document) { } public void Add(Feature feature) { - if (featureName == FeatureName.INCLUDE || strategy == Strategy.SHORT) + if (featureName == NamingStrategy.FeatureName.INCLUDE || strategy == NamingStrategy.Strategy.SHORT) { parts.Add(feature.Name); } @@ -76,9 +76,9 @@ public void Add(Pickle pickle) { switch (exampleName) { - case ExampleName.NUMBER: + case NamingStrategy.ExampleName.NUMBER: break; - case ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED: + case NamingStrategy.ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED: bool parameterized = !scenarioName.Equals(pickleName); if (parameterized) { @@ -87,7 +87,7 @@ public void Add(Pickle pickle) parts.Add(exampleNumber + ": " + pickleName); } break; - case ExampleName.PICKLE: + case NamingStrategy.ExampleName.PICKLE: parts.RemoveAt(parts.Count - 1); // Remove example number parts.Add(pickleName); break; @@ -99,7 +99,7 @@ public void Add(Pickle pickle) public string Finish() { - if (strategy == Strategy.SHORT) + if (strategy == NamingStrategy.Strategy.SHORT) { return parts.Count > 0 ? parts[parts.Count - 1] : string.Empty; } diff --git a/dotnet/Query/Query/NamingStrategy.cs b/dotnet/Query/Query/NamingStrategy.cs index 73af2f03..705547f6 100644 --- a/dotnet/Query/Query/NamingStrategy.cs +++ b/dotnet/Query/Query/NamingStrategy.cs @@ -6,26 +6,27 @@ namespace Io.Cucumber.Query /// /// Names Pickles and other elements in a GherkinDocument. /// - public enum Strategy + public abstract class NamingStrategy : ILineageReducer { - LONG, - SHORT - } + public enum Strategy + { + LONG, + SHORT + } - public enum ExampleName - { - NUMBER, - PICKLE, - NUMBER_AND_PICKLE_IF_PARAMETERIZED - } + public enum ExampleName + { + NUMBER, + PICKLE, + NUMBER_AND_PICKLE_IF_PARAMETERIZED + } - public enum FeatureName - { - INCLUDE, - EXCLUDE - } - public abstract class NamingStrategy : ILineageReducer - { + + public enum FeatureName + { + INCLUDE, + EXCLUDE + } public static Builder Create(Strategy strategy) { @@ -40,8 +41,8 @@ protected NamingStrategy() { } public class Builder { private readonly Strategy _strategy; - private FeatureName _featureName = Io.Cucumber.Query.FeatureName.INCLUDE; - private ExampleName _exampleName = Io.Cucumber.Query.ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED; + private FeatureName _featureName = NamingStrategy.FeatureName.INCLUDE; + private ExampleName _exampleName = NamingStrategy.ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED; public Builder(Strategy strategy) { diff --git a/dotnet/Query/Query/Query.cs b/dotnet/Query/Query/Query.cs index 8a745785..c8e96bac 100644 --- a/dotnet/Query/Query/Query.cs +++ b/dotnet/Query/Query/Query.cs @@ -71,14 +71,6 @@ public IList FindAllTestCaseStarted() => _testCaseStartedById.V public IList FindAllTestSteps() => _testStepById.Values.OrderBy(ts => ts.Id).ToList(); - public IDictionary> FindAllTestCaseStartedGroupedByFeature() - { - // Group TestCaseStarted by Feature (null if not found) - return FindAllTestCaseStarted() - .GroupBy(tcs => FindFeatureBy(tcs)) - .ToDictionary(g => g.Key, g => g.ToList()); - } - public Meta? FindMeta() => _meta; public TestRunStarted? FindTestRunStarted() => _testRunStarted; public TestRunFinished? FindTestRunFinished() => _testRunFinished; @@ -88,14 +80,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => ? attachments.Where(a => a.TestStepId == testStepFinished.TestStepId).ToList() : new List(); - public Feature? FindFeatureBy(TestCaseStarted testCaseStarted) - { - return FindLineageBy(testCaseStarted)?.Feature; - } - public Hook? FindHookBy(TestStep testStep) { - // Java: testStep.getHookId().map(hookById::get) if (!string.IsNullOrEmpty(testStep.HookId) && _hookById.TryGetValue(testStep.HookId, out var hook)) { return hook; @@ -105,7 +91,6 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public Pickle? FindPickleBy(TestCaseStarted testCaseStarted) { - // Java: findTestCaseBy(testCaseStarted).map(TestCase::getPickleId).map(pickleById::get) var testCase = FindTestCaseBy(testCaseStarted); if (testCase != null && _pickleById.TryGetValue(testCase.PickleId, out var pickle)) { @@ -116,7 +101,6 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public Pickle? FindPickleBy(TestStepStarted testStepStarted) { - // Java: findTestCaseBy(testStepStarted).map(TestCase::getPickleId).map(pickleById::get) var testCaseStarted = FindTestCaseStartedBy(testStepStarted); if (testCaseStarted != null) { @@ -127,7 +111,6 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public TestCase? FindTestCaseBy(TestCaseStarted testCaseStarted) { - // Java: testCaseById.get(testCaseStarted.getTestCaseId()) if (_testCaseById.TryGetValue(testCaseStarted.TestCaseId, out var testCase)) { return testCase; @@ -137,32 +120,27 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public TestCaseStarted? FindTestCaseStartedBy(TestStepStarted testStepStarted) { - // Java: testCaseStartedById.get(testStepStarted.getTestCaseStartedId()) return _testCaseStartedById.TryGetValue(testStepStarted.TestCaseStartedId, out var tcs) ? tcs : null; } public TestCase? FindTestCaseBy(TestStepStarted testStepStarted) { - // Java: findTestCaseStartedBy(testStepStarted).flatMap(this::findTestCaseBy) var testCaseStarted = FindTestCaseStartedBy(testStepStarted); return testCaseStarted != null ? FindTestCaseBy(testCaseStarted) : null; } public TestStep? FindTestStepBy(TestStepStarted testStepStarted) { - // Java: testStepById.get(testStepStarted.getTestStepId()) return _testStepById.TryGetValue(testStepStarted.TestStepId, out var testStep) ? testStep : null; } public TestStep? FindTestStepBy(TestStepFinished testStepFinished) { - // Java: testStepById.get(testStepFinished.getTestStepId()) return _testStepById.TryGetValue(testStepFinished.TestStepId, out var testStep) ? testStep : null; } public PickleStep? FindPickleStepBy(TestStep testStep) { - // Java: testStep.getPickleStepId().map(pickleStepById::get) if (!string.IsNullOrEmpty(testStep.PickleStepId)) { if (_pickleStepById.TryGetValue(testStep.PickleStepId, out var pickleStep)) @@ -175,7 +153,6 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public Step? FindStepBy(PickleStep pickleStep) { - // Java: String stepId = pickleStep.getAstNodeIds().get(0); stepById.get(stepId) if (pickleStep.AstNodeIds != null && pickleStep.AstNodeIds.Count > 0) { var stepId = pickleStep.AstNodeIds[0]; @@ -202,13 +179,11 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public TestCaseFinished? FindTestCaseFinishedBy(TestCaseStarted testCaseStarted) { - // Java: testCaseFinishedByTestCaseStartedId.get(testCaseStarted.getId()) return _testCaseFinishedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var finished) ? finished : null; } public System.TimeSpan? FindTestRunDuration() { - // Java: if (testRunStarted == null || testRunFinished == null) return Optional.empty(); if (_testRunStarted == null || _testRunFinished == null) return null; var start = Converters.ToDateTime(_testRunStarted.Timestamp); @@ -218,10 +193,8 @@ public IList FindAttachmentsBy(TestStepFinished testStepFinished) => public IList FindTestStepsStartedBy(TestCaseStarted testCaseStarted) { - // Java: testStepsStartedByTestCaseStartedId.getOrDefault(testCaseStarted.getId(), emptyList()) if (_testStepsStartedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var steps)) { - // Return a copy for concurrency safety return new List(steps); } return new List(); @@ -229,7 +202,6 @@ public IList FindTestStepsStartedBy(TestCaseStarted testCaseSta public IList FindTestStepsFinishedBy(TestCaseStarted testCaseStarted) { - // Java: testStepsFinishedByTestCaseStartedId.getOrDefault(testCaseStarted.getId(), emptyList()) if (_testStepsFinishedByTestCaseStartedId.TryGetValue(testCaseStarted.Id, out var steps)) { // Return a copy for concurrency safety @@ -240,11 +212,6 @@ public IList FindTestStepsFinishedBy(TestCaseStarted testCaseS public IList<(TestStepFinished, TestStep)> FindTestStepFinishedAndTestStepBy(TestCaseStarted testCaseStarted) { - // Java: findTestStepsFinishedBy(testCaseStarted).stream() - // .map(testStepFinished -> findTestStepBy(testStepFinished).map(testStep -> new SimpleEntry<>(testStepFinished, testStep))) - // .filter(Optional::isPresent) - // .map(Optional::get) - // .collect(toList()); var finishedSteps = FindTestStepsFinishedBy(testCaseStarted); var result = new List<(TestStepFinished, TestStep)>(); foreach (var testStepFinished in finishedSteps) @@ -470,62 +437,6 @@ public void Update(Envelope envelope) } return FindLineageBy(pickle); } - - public string FindNameOf(GherkinDocument element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(Feature element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(Rule element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(Scenario element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(Examples element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(TableRow element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - return GetNameFromStrategy(element, lineage, namingStrategy); - } - - public string FindNameOf(Pickle element, NamingStrategy namingStrategy) - { - if (element == null) return string.Empty; - var lineage = FindLineageBy(element); - var result = namingStrategy.Reduce(lineage, element); - if (result == null) - { - throw new ArgumentException("Element was not part of this query object"); - } - return result; - - } - public Location? FindLocationOf(Pickle pickle) { var lineage = FindLineageBy(pickle); @@ -537,15 +448,4 @@ public string FindNameOf(Pickle element, NamingStrategy namingStrategy) return lineage.Scenario.Location; return null; } - - // Placeholder for actual naming strategy logic - private string GetNameFromStrategy(object element, Lineage? lineage, NamingStrategy namingStrategy) - { - var result = namingStrategy.Reduce(lineage); - if (result == null) - { - throw new ArgumentException("Element was not part of this query object"); - } - return result; - } } diff --git a/dotnet/Query/QueryTest/NamingStrategyAcceptanceTest.cs b/dotnet/Query/QueryTest/NamingStrategyAcceptanceTest.cs new file mode 100644 index 00000000..8e64932b --- /dev/null +++ b/dotnet/Query/QueryTest/NamingStrategyAcceptanceTest.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using FluentAssertions; +using Io.Cucumber.Messages.Types; +using Io.Cucumber.Query; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace QueryTest +{ + [TestClass] + public class NamingStrategyAcceptanceTest + { + private static readonly Dictionary Strategies = new() + { + { "long", NamingStrategy.Create(NamingStrategy.Strategy.LONG).Build() }, + { "long-exclude-feature-name", NamingStrategy.Create(NamingStrategy.Strategy.LONG).FeatureName(NamingStrategy.FeatureName.EXCLUDE).Build() }, + { "long-with-pickle-name", NamingStrategy.Create(NamingStrategy.Strategy.LONG).ExampleName(NamingStrategy.ExampleName.PICKLE).Build() }, + { "long-with-pickle-name-if-parameterized", NamingStrategy.Create(NamingStrategy.Strategy.LONG).ExampleName(NamingStrategy.ExampleName.NUMBER_AND_PICKLE_IF_PARAMETERIZED).Build() }, + { "short", NamingStrategy.Create(NamingStrategy.Strategy.SHORT).Build() } + }; + + public static IEnumerable Acceptance() + { + var sources = new[] + { + Path.Combine("..", "..", "..", "..", "..", "..", "testdata", "minimal.feature.ndjson"), + Path.Combine("..", "..", "..", "..", "..", "..", "testdata", "rules.feature.ndjson"), + Path.Combine("..", "..", "..", "..", "..", "..", "testdata", "examples-tables.feature.ndjson") + }; + + foreach (var source in sources) + { + foreach (var kvp in Strategies) + { + yield return new object[] { new TestCase(source, kvp.Key, kvp.Value) }; + } + } + } + + [TestMethod] + [DynamicData(nameof(Acceptance), DynamicDataSourceType.Method)] + public void Test(TestCase testCase) + { + var actual = WriteResults(testCase, testCase.Strategy); + var expected = File.ReadAllText(testCase.Expected, Encoding.UTF8); + actual.Should().Be(expected, $"NamingStrategy results for {testCase} do not match expected results."); + } + + // Disabled: Only for updating expected files + // [TestMethod] + // [DynamicData(nameof(Acceptance), DynamicDataSourceType.Method)] + // [Ignore] + public void UpdateExpectedQueryResultFiles(TestCase testCase) + { + using var outStream = File.Open(testCase.Expected, FileMode.Create, FileAccess.Write); + WriteResults(testCase.Strategy, testCase, outStream); + } + + private static string WriteResults(TestCase testCase, NamingStrategy strategy) + { + using var outStream = new MemoryStream(); + WriteResults(strategy, testCase, outStream); + return Encoding.UTF8.GetString(outStream.ToArray()); + } + + private static void WriteResults(NamingStrategy strategy, TestCase testCase, Stream outStream) + { + using var inStream = File.OpenRead(testCase.Source); + using var reader = new StreamReader(inStream, Encoding.UTF8); + using var writer = new StreamWriter(outStream, Encoding.UTF8, leaveOpen: true); + var query = new Query(); + + string? line; + while ((line = reader.ReadLine()) != null) + { + if (string.IsNullOrWhiteSpace(line)) continue; + var envelope = NdjsonSerializer.Deserialize(line); + query.Update(envelope); + } + + foreach (var pickle in query.FindAllPickles()) + { + var lineage = query.FindLineageBy(pickle); + if (lineage != null) + { + var name = strategy.Reduce(lineage, pickle); + if (name != null) + writer.WriteLine(name); + } + } + writer.Flush(); + } + + public class TestCase + { + public string Source { get; } + public NamingStrategy Strategy { get; } + public string Expected { get; } + public string Name { get; } + public string StrategyName { get; } + + public TestCase(string source, string strategyName, NamingStrategy strategy) + { + Source = source; + Strategy = strategy; + StrategyName = strategyName; + var fileName = Path.GetFileName(source); + Name = fileName.Substring(0, fileName.LastIndexOf(".ndjson", StringComparison.Ordinal)); + Expected = Path.Combine(Path.GetDirectoryName(source)!, $"{Name}.naming-strategy.{strategyName}.txt"); + } + + public override string ToString() => $"{Name} -> {StrategyName}"; + } + } +} \ No newline at end of file diff --git a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs index 1cd3b447..98dac716 100644 --- a/dotnet/Query/QueryTest/QueryAcceptanceTest.cs +++ b/dotnet/Query/QueryTest/QueryAcceptanceTest.cs @@ -102,12 +102,6 @@ private static string WriteQueryResults(TestCase testCase) ["findAllPickleSteps"] = query.FindAllPickleSteps().Count, ["findAllTestCaseStarted"] = query.FindAllTestCaseStarted().Count, ["findAllTestSteps"] = query.FindAllTestSteps().Count, - ["findAllTestCaseStartedGroupedByFeature"] = query.FindAllTestCaseStartedGroupedByFeature() - .Select(entry => new object[] - { - entry.Key?.Name ?? String.Empty, - entry.Value.Select(tcs => tcs.Id).ToList() - }).ToList(), ["findAttachmentsBy"] = query.FindAllTestCaseStarted() .SelectMany(tcs => query.FindTestStepFinishedAndTestStepBy(tcs)) .Select(pair => pair.Item1) @@ -119,9 +113,6 @@ private static string WriteQueryResults(TestCase testCase) att.MediaType, att.ContentEncoding }).ToList(), - ["findFeatureBy"] = query.FindAllTestCaseStarted() - .Select(tcs => query.FindFeatureBy(tcs)?.Name) - .ToList(), ["findHookBy"] = query.FindAllTestSteps() .Select(ts => query.FindHookBy(ts)?.Id) .Where(id => id != null) @@ -134,14 +125,6 @@ private static string WriteQueryResults(TestCase testCase) ["findMostSevereTestStepResultBy"] = query.FindAllTestCaseStarted() .Select(tcs => query.FindMostSevereTestStepResultBy(tcs)?.Status.ToString()) .ToList(), - ["findNameOf"] = new Dictionary - { - ["long"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).Build())).ToList(), - ["excludeFeatureName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).FeatureName(FeatureName.EXCLUDE).Build())).ToList(), - ["longPickleName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.LONG).ExampleName(ExampleName.PICKLE).Build())).ToList(), - ["short"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.SHORT).Build())).ToList(), - ["shortPickleName"] = query.FindAllPickles().Select(p => query.FindNameOf(p, NamingStrategy.Create(Strategy.SHORT).ExampleName(ExampleName.PICKLE).Build())).ToList(), - }, ["findPickleBy"] = query.FindAllTestCaseStarted() .Select(tcs => query.FindPickleBy(tcs)?.Name) .ToList(),