From e42c6cdacdc00e9c8e6cca5f03ba96db06cb1e8d Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 24 May 2024 16:17:17 +0200 Subject: [PATCH] Add hook type Hooks in Cucumber can either execute before/after a scenario or before/after a step. Depending on which implementation is used these are put into the json report as either all part of the `element.steps` field[1] or the `element.before` and `element.steps` fields[2][3]. So to create a json reports from messages the type of hook must be included in the message. 1. https://github.com/cucumber/cucumber-json-converter/blob/main/testdata/cucumber-js/7.3.2/json/failing-before-hook.json 2. https://github.com/cucumber/cucumber-json-converter/blob/main/testdata/cucumber-jvm/7.2.3/json/failing-before-hook.json 3. https://github.com/cucumber/cucumber-json-converter/blob/main/testdata/cucumber-jvm/7.2.3/json/failing-after-step-hook.json --- .gitignore | 1 + .../messages/cucumber/messages/hook.hpp | 2 + .../messages/cucumber/messages/hook_type.hpp | 21 ++++++++++ .../lib/messages/cucumber/messages/hook.cpp | 2 + .../messages/cucumber/messages/hook_type.cpp | 31 +++++++++++++++ go/messages.go | 25 ++++++++++++ .../java/io/cucumber/messages/types/Hook.java | 16 ++++++-- .../io/cucumber/messages/types/HookType.java | 38 +++++++++++++++++++ javascript/src/messages.ts | 9 +++++ jsonschema/Hook.json | 9 +++++ messages.md | 11 ++++++ perl/lib/Cucumber/Messages.pm | 34 +++++++++++++++++ php/src-generated/Hook.php | 13 +++++++ php/src-generated/Hook/Type.php | 17 +++++++++ ruby/lib/cucumber/messages.deserializers.rb | 1 + ruby/lib/cucumber/messages.dtos.rb | 13 ++++++- 16 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 cpp/include/messages/cucumber/messages/hook_type.hpp create mode 100644 cpp/src/lib/messages/cucumber/messages/hook_type.cpp create mode 100644 java/src/generated/java/io/cucumber/messages/types/HookType.java create mode 100644 php/src-generated/Hook/Type.php diff --git a/.gitignore b/.gitignore index 811a2387..fd32185b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .idea *.iml +.php-cs-fixer.cache \ No newline at end of file diff --git a/cpp/include/messages/cucumber/messages/hook.hpp b/cpp/include/messages/cucumber/messages/hook.hpp index 8a9c1f7d..123665b2 100644 --- a/cpp/include/messages/cucumber/messages/hook.hpp +++ b/cpp/include/messages/cucumber/messages/hook.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace cucumber::messages { @@ -24,6 +25,7 @@ struct hook std::optional name; cucumber::messages::source_reference source_reference; std::optional tag_expression; + std::optional type; std::string to_string() const; diff --git a/cpp/include/messages/cucumber/messages/hook_type.hpp b/cpp/include/messages/cucumber/messages/hook_type.hpp new file mode 100644 index 00000000..0c5ec179 --- /dev/null +++ b/cpp/include/messages/cucumber/messages/hook_type.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace cucumber::messages { + +enum class hook_type +{ + BEFORE, + AFTER, + BEFORE_STEP, + AFTER_STEP +}; + +std::string_view +to_string(hook_type v); + +std::ostream& +operator<<(std::ostream& os, hook_type v); + +} diff --git a/cpp/src/lib/messages/cucumber/messages/hook.cpp b/cpp/src/lib/messages/cucumber/messages/hook.cpp index 7566258a..bfd5e186 100644 --- a/cpp/src/lib/messages/cucumber/messages/hook.cpp +++ b/cpp/src/lib/messages/cucumber/messages/hook.cpp @@ -14,6 +14,7 @@ hook::to_string() const cucumber::messages::to_string(oss, ", name=", name); cucumber::messages::to_string(oss, ", source_reference=", source_reference); cucumber::messages::to_string(oss, ", tag_expression=", tag_expression); + cucumber::messages::to_string(oss, ", type=", type); return oss.str(); } @@ -25,6 +26,7 @@ hook::to_json(json& j) const cucumber::messages::to_json(j, camelize("name"), name); cucumber::messages::to_json(j, camelize("source_reference"), source_reference); cucumber::messages::to_json(j, camelize("tag_expression"), tag_expression); + cucumber::messages::to_json(j, camelize("type"), type); } std::string diff --git a/cpp/src/lib/messages/cucumber/messages/hook_type.cpp b/cpp/src/lib/messages/cucumber/messages/hook_type.cpp new file mode 100644 index 00000000..0de6a81b --- /dev/null +++ b/cpp/src/lib/messages/cucumber/messages/hook_type.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include + +namespace cucumber::messages { + +std::string_view +to_string(hook_type v) +{ + using map_type = std::unordered_map; + + static const map_type m = { + { hook_type::BEFORE, "BEFORE" }, + { hook_type::AFTER, "AFTER" }, + { hook_type::BEFORE_STEP, "BEFORE_STEP" }, + { hook_type::AFTER_STEP, "AFTER_STEP" } + }; + + return m.at(v); +} + +std::ostream& +operator<<(std::ostream& os, hook_type v) +{ + os << to_string(v); + + return os; +} + +} diff --git a/go/messages.go b/go/messages.go index e7dc6169..3b241f98 100644 --- a/go/messages.go +++ b/go/messages.go @@ -159,6 +159,7 @@ type Hook struct { Name string `json:"name,omitempty"` SourceReference *SourceReference `json:"sourceReference"` TagExpression string `json:"tagExpression,omitempty"` + Type HookType `json:"type,omitempty"` } type Location struct { @@ -391,6 +392,30 @@ func (e AttachmentContentEncoding) String() string { } } +type HookType string + +const ( + HookType_BEFORE HookType = "BEFORE" + HookType_AFTER HookType = "AFTER" + HookType_BEFORE_STEP HookType = "BEFORE_STEP" + HookType_AFTER_STEP HookType = "AFTER_STEP" +) + +func (e HookType) String() string { + switch e { + case HookType_BEFORE: + return "BEFORE" + case HookType_AFTER: + return "AFTER" + case HookType_BEFORE_STEP: + return "BEFORE_STEP" + case HookType_AFTER_STEP: + return "AFTER_STEP" + default: + panic("Bad enum value for HookType") + } +} + type PickleStepType string const ( diff --git a/java/src/generated/java/io/cucumber/messages/types/Hook.java b/java/src/generated/java/io/cucumber/messages/types/Hook.java index f8ea3331..3527d566 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Hook.java +++ b/java/src/generated/java/io/cucumber/messages/types/Hook.java @@ -18,17 +18,20 @@ public final class Hook { private final String name; private final SourceReference sourceReference; private final String tagExpression; + private final HookType type; public Hook( String id, String name, SourceReference sourceReference, - String tagExpression + String tagExpression, + HookType type ) { this.id = requireNonNull(id, "Hook.id cannot be null"); this.name = name; this.sourceReference = requireNonNull(sourceReference, "Hook.sourceReference cannot be null"); this.tagExpression = tagExpression; + this.type = type; } public String getId() { @@ -47,6 +50,10 @@ public Optional getTagExpression() { return Optional.ofNullable(tagExpression); } + public Optional getType() { + return Optional.ofNullable(type); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -56,7 +63,8 @@ public boolean equals(Object o) { id.equals(that.id) && Objects.equals(name, that.name) && sourceReference.equals(that.sourceReference) && - Objects.equals(tagExpression, that.tagExpression); + Objects.equals(tagExpression, that.tagExpression) && + Objects.equals(type, that.type); } @Override @@ -65,7 +73,8 @@ public int hashCode() { id, name, sourceReference, - tagExpression + tagExpression, + type ); } @@ -76,6 +85,7 @@ public String toString() { ", name=" + name + ", sourceReference=" + sourceReference + ", tagExpression=" + tagExpression + + ", type=" + type + '}'; } } diff --git a/java/src/generated/java/io/cucumber/messages/types/HookType.java b/java/src/generated/java/io/cucumber/messages/types/HookType.java new file mode 100644 index 00000000..962c8825 --- /dev/null +++ b/java/src/generated/java/io/cucumber/messages/types/HookType.java @@ -0,0 +1,38 @@ +package io.cucumber.messages.types; + +// Generated code +@SuppressWarnings("unused") +public enum HookType { + + BEFORE("BEFORE"), + + AFTER("AFTER"), + + BEFORE_STEP("BEFORE_STEP"), + + AFTER_STEP("AFTER_STEP"); + + private final String value; + + HookType(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + public String value() { + return this.value; + } + + public static HookType fromValue(String value) { + for (HookType v : values()) { + if (v.value.equals(value)) { + return v; + } + } + throw new IllegalArgumentException(value); + } +} diff --git a/javascript/src/messages.ts b/javascript/src/messages.ts index ceec6923..0be7e050 100644 --- a/javascript/src/messages.ts +++ b/javascript/src/messages.ts @@ -314,6 +314,8 @@ export class Hook { sourceReference: SourceReference = new SourceReference() tagExpression?: string + + type?: HookType } export class Location { @@ -675,6 +677,13 @@ export enum AttachmentContentEncoding { BASE64 = 'BASE64', } +export enum HookType { + BEFORE = 'BEFORE', + AFTER = 'AFTER', + BEFORE_STEP = 'BEFORE_STEP', + AFTER_STEP = 'AFTER_STEP', +} + export enum PickleStepType { UNKNOWN = 'Unknown', CONTEXT = 'Context', diff --git a/jsonschema/Hook.json b/jsonschema/Hook.json index 6e64289b..b2a98424 100644 --- a/jsonschema/Hook.json +++ b/jsonschema/Hook.json @@ -18,6 +18,15 @@ }, "tagExpression": { "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "BEFORE", + "AFTER", + "BEFORE_STEP", + "AFTER_STEP" + ] } }, "type": "object" diff --git a/messages.md b/messages.md index 8183c829..4c977ec2 100644 --- a/messages.md +++ b/messages.md @@ -203,6 +203,7 @@ will only have one of its fields set, which indicates the payload of the message | `name` | string | no | | | `sourceReference` | [SourceReference](#sourcereference) | yes | | | `tagExpression` | string | no | | +| `type` | [HookType](#hooktype) | no | | ## Location @@ -494,6 +495,16 @@ One of the following: * `"BASE64"` +## HookType + +One of the following: + +* `"BEFORE"` +* `"AFTER"` +* `"BEFORE_STEP"` +* `"AFTER_STEP"` + + ## PickleStepType One of the following: diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 5e5d51e8..668eb55c 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -2026,6 +2026,7 @@ my %types = ( name => 'string', source_reference => 'Cucumber::Messages::SourceReference', tag_expression => 'string', + type => '', ); # This is a work-around for the fact that Moo doesn't have introspection @@ -2080,6 +2081,39 @@ has tag_expression => ); +=head4 type + + + +Available constants for valid values of this field: + +=over + +=item * TYPE_BEFORE + +=item * TYPE_AFTER + +=item * TYPE_BEFORE_STEP + +=item * TYPE_AFTER_STEP + +=back + +=cut + + +use constant { + TYPE_BEFORE => 'BEFORE', + TYPE_AFTER => 'AFTER', + TYPE_BEFORE_STEP => 'BEFORE_STEP', + TYPE_AFTER_STEP => 'AFTER_STEP', + }; + +has type => + (is => 'ro', + ); + + } package Cucumber::Messages::Location { diff --git a/php/src-generated/Hook.php b/php/src-generated/Hook.php index 0715735e..13c7785e 100644 --- a/php/src-generated/Hook.php +++ b/php/src-generated/Hook.php @@ -29,6 +29,7 @@ public function __construct( public readonly ?string $name = null, public readonly SourceReference $sourceReference = new SourceReference(), public readonly ?string $tagExpression = null, + public readonly ?Hook\Type $type = null, ) { } @@ -43,12 +44,14 @@ public static function fromArray(array $arr): self self::ensureName($arr); self::ensureSourceReference($arr); self::ensureTagExpression($arr); + self::ensureType($arr); return new self( (string) $arr['id'], isset($arr['name']) ? (string) $arr['name'] : null, SourceReference::fromArray($arr['sourceReference']), isset($arr['tagExpression']) ? (string) $arr['tagExpression'] : null, + isset($arr['type']) ? Hook\Type::from((string) $arr['type']) : null, ); } @@ -97,4 +100,14 @@ private static function ensureTagExpression(array $arr): void throw new SchemaViolationException('Property \'tagExpression\' was array'); } } + + /** + * @psalm-assert array{type?: string|int|bool} $arr + */ + private static function ensureType(array $arr): void + { + if (array_key_exists('type', $arr) && is_array($arr['type'])) { + throw new SchemaViolationException('Property \'type\' was array'); + } + } } diff --git a/php/src-generated/Hook/Type.php b/php/src-generated/Hook/Type.php new file mode 100644 index 00000000..5f905fac --- /dev/null +++ b/php/src-generated/Hook/Type.php @@ -0,0 +1,17 @@ +