diff --git a/CHANGELOG.md b/CHANGELOG.md index 248c2300..cdc0c068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- Add new `TestRunHookStarted` and `TestRunHookFinished` messages ([#102](https://github.com/cucumber/messages/pull/102)) + +### Changed +- BREAKING CHANGE: Add `id` property to `TestRunStarted`, optionally reference in `TestCase`, `Attachment` and `TestRunFinished` ([#102](https://github.com/cucumber/messages/pull/102)) +- BREAKING CHANGE: Add `type` property to `Hook` ([#102](https://github.com/cucumber/messages/pull/102)) ## [26.0.1] - 2024-09-22 ### Changed diff --git a/Makefile b/Makefile index a540e214..297f25ec 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,11 @@ schemas = \ ./jsonschema/TestRunFinished.json \ ./jsonschema/TestRunStarted.json \ ./jsonschema/Duration.json \ + ./jsonschema/TestStepResult.json \ ./jsonschema/TestStepFinished.json \ ./jsonschema/TestStepStarted.json \ + ./jsonschema/TestRunHookFinished.json \ + ./jsonschema/TestRunHookStarted.json \ ./jsonschema/UndefinedParameterType.json \ ./jsonschema/Envelope.json diff --git a/cpp/include/messages/cucumber/messages/all.hpp b/cpp/include/messages/cucumber/messages/all.hpp index 4b4dc10c..18507d0a 100644 --- a/cpp/include/messages/cucumber/messages/all.hpp +++ b/cpp/include/messages/cucumber/messages/all.hpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/cpp/include/messages/cucumber/messages/attachment.hpp b/cpp/include/messages/cucumber/messages/attachment.hpp index 3bfcbf0b..3e0cd97a 100644 --- a/cpp/include/messages/cucumber/messages/attachment.hpp +++ b/cpp/include/messages/cucumber/messages/attachment.hpp @@ -41,6 +41,7 @@ struct attachment std::optional test_case_started_id; std::optional test_step_id; std::optional url; + std::optional test_run_started_id; std::string to_string() const; diff --git a/cpp/include/messages/cucumber/messages/envelope.hpp b/cpp/include/messages/cucumber/messages/envelope.hpp index 0528621d..52fa6cdc 100644 --- a/cpp/include/messages/cucumber/messages/envelope.hpp +++ b/cpp/include/messages/cucumber/messages/envelope.hpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include namespace cucumber::messages { @@ -59,6 +61,8 @@ struct envelope std::optional test_run_started; std::optional test_step_finished; std::optional test_step_started; + std::optional test_run_hook_started; + std::optional test_run_hook_finished; std::optional undefined_parameter_type; std::string to_string() const; 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..a69e5493 --- /dev/null +++ b/cpp/include/messages/cucumber/messages/hook_type.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace cucumber::messages { + +enum class hook_type +{ + BEFORE_TEST_RUN, + AFTER_TEST_RUN, + BEFORE_TEST_CASE, + AFTER_TEST_CASE, + BEFORE_TEST_STEP, + AFTER_TEST_STEP +}; + +std::string_view +to_string(hook_type v); + +std::ostream& +operator<<(std::ostream& os, hook_type v); + +} diff --git a/cpp/include/messages/cucumber/messages/test_case.hpp b/cpp/include/messages/cucumber/messages/test_case.hpp index 146c0e6d..a5c726af 100644 --- a/cpp/include/messages/cucumber/messages/test_case.hpp +++ b/cpp/include/messages/cucumber/messages/test_case.hpp @@ -27,6 +27,7 @@ struct test_case std::string id; std::string pickle_id; std::vector test_steps; + std::optional test_run_started_id; std::string to_string() const; diff --git a/cpp/include/messages/cucumber/messages/test_run_finished.hpp b/cpp/include/messages/cucumber/messages/test_run_finished.hpp index d3213792..27cff76c 100644 --- a/cpp/include/messages/cucumber/messages/test_run_finished.hpp +++ b/cpp/include/messages/cucumber/messages/test_run_finished.hpp @@ -25,6 +25,7 @@ struct test_run_finished bool success; cucumber::messages::timestamp timestamp; std::optional exception; + std::optional test_run_started_id; std::string to_string() const; diff --git a/cpp/include/messages/cucumber/messages/test_run_hook_finished.hpp b/cpp/include/messages/cucumber/messages/test_run_hook_finished.hpp new file mode 100644 index 00000000..6fb4de76 --- /dev/null +++ b/cpp/include/messages/cucumber/messages/test_run_hook_finished.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include + +namespace cucumber::messages { + +using json = nlohmann::json; + +// +// Represents the TestRunHookFinished message in Cucumber's message protocol +// @see Github - Cucumber - Messages +// +// Generated code + +struct test_run_hook_finished +{ + std::string test_run_hook_started_id; + cucumber::messages::test_step_result result; + cucumber::messages::timestamp timestamp; + + std::string to_string() const; + + void to_json(json& j) const; + std::string to_json() const; +}; + +std::ostream& +operator<<(std::ostream& os, const test_run_hook_finished& msg); + +void to_json(json& j, const test_run_hook_finished& m); + +} diff --git a/cpp/include/messages/cucumber/messages/test_run_hook_started.hpp b/cpp/include/messages/cucumber/messages/test_run_hook_started.hpp new file mode 100644 index 00000000..5293b467 --- /dev/null +++ b/cpp/include/messages/cucumber/messages/test_run_hook_started.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include + +#include + +namespace cucumber::messages { + +using json = nlohmann::json; + +// +// Represents the TestRunHookStarted message in Cucumber's message protocol +// @see Github - Cucumber - Messages +// +// Generated code + +struct test_run_hook_started +{ + std::string id; + std::string test_run_started_id; + std::string hook_id; + cucumber::messages::timestamp timestamp; + + std::string to_string() const; + + void to_json(json& j) const; + std::string to_json() const; +}; + +std::ostream& +operator<<(std::ostream& os, const test_run_hook_started& msg); + +void to_json(json& j, const test_run_hook_started& m); + +} diff --git a/cpp/include/messages/cucumber/messages/test_run_started.hpp b/cpp/include/messages/cucumber/messages/test_run_started.hpp index 24f2fc62..bcf1a30d 100644 --- a/cpp/include/messages/cucumber/messages/test_run_started.hpp +++ b/cpp/include/messages/cucumber/messages/test_run_started.hpp @@ -21,6 +21,7 @@ using json = nlohmann::json; struct test_run_started { cucumber::messages::timestamp timestamp; + std::optional id; std::string to_string() const; diff --git a/cpp/src/lib/messages/cucumber/messages/attachment.cpp b/cpp/src/lib/messages/cucumber/messages/attachment.cpp index d4661e0c..ba133cdb 100644 --- a/cpp/src/lib/messages/cucumber/messages/attachment.cpp +++ b/cpp/src/lib/messages/cucumber/messages/attachment.cpp @@ -18,6 +18,7 @@ attachment::to_string() const cucumber::messages::to_string(oss, ", test_case_started_id=", test_case_started_id); cucumber::messages::to_string(oss, ", test_step_id=", test_step_id); cucumber::messages::to_string(oss, ", url=", url); + cucumber::messages::to_string(oss, ", test_run_started_id=", test_run_started_id); return oss.str(); } @@ -33,6 +34,7 @@ attachment::to_json(json& j) const cucumber::messages::to_json(j, camelize("test_case_started_id"), test_case_started_id); cucumber::messages::to_json(j, camelize("test_step_id"), test_step_id); cucumber::messages::to_json(j, camelize("url"), url); + cucumber::messages::to_json(j, camelize("test_run_started_id"), test_run_started_id); } std::string diff --git a/cpp/src/lib/messages/cucumber/messages/envelope.cpp b/cpp/src/lib/messages/cucumber/messages/envelope.cpp index 88e63702..e780f0c7 100644 --- a/cpp/src/lib/messages/cucumber/messages/envelope.cpp +++ b/cpp/src/lib/messages/cucumber/messages/envelope.cpp @@ -26,6 +26,8 @@ envelope::to_string() const cucumber::messages::to_string(oss, ", test_run_started=", test_run_started); cucumber::messages::to_string(oss, ", test_step_finished=", test_step_finished); cucumber::messages::to_string(oss, ", test_step_started=", test_step_started); + cucumber::messages::to_string(oss, ", test_run_hook_started=", test_run_hook_started); + cucumber::messages::to_string(oss, ", test_run_hook_finished=", test_run_hook_finished); cucumber::messages::to_string(oss, ", undefined_parameter_type=", undefined_parameter_type); return oss.str(); @@ -50,6 +52,8 @@ envelope::to_json(json& j) const cucumber::messages::to_json(j, camelize("test_run_started"), test_run_started); cucumber::messages::to_json(j, camelize("test_step_finished"), test_step_finished); cucumber::messages::to_json(j, camelize("test_step_started"), test_step_started); + cucumber::messages::to_json(j, camelize("test_run_hook_started"), test_run_hook_started); + cucumber::messages::to_json(j, camelize("test_run_hook_finished"), test_run_hook_finished); cucumber::messages::to_json(j, camelize("undefined_parameter_type"), undefined_parameter_type); } 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..1f9c0aa4 --- /dev/null +++ b/cpp/src/lib/messages/cucumber/messages/hook_type.cpp @@ -0,0 +1,33 @@ +#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_TEST_RUN, "BEFORE_TEST_RUN" }, + { hook_type::AFTER_TEST_RUN, "AFTER_TEST_RUN" }, + { hook_type::BEFORE_TEST_CASE, "BEFORE_TEST_CASE" }, + { hook_type::AFTER_TEST_CASE, "AFTER_TEST_CASE" }, + { hook_type::BEFORE_TEST_STEP, "BEFORE_TEST_STEP" }, + { hook_type::AFTER_TEST_STEP, "AFTER_TEST_STEP" } + }; + + return m.at(v); +} + +std::ostream& +operator<<(std::ostream& os, hook_type v) +{ + os << to_string(v); + + return os; +} + +} diff --git a/cpp/src/lib/messages/cucumber/messages/test_case.cpp b/cpp/src/lib/messages/cucumber/messages/test_case.cpp index 6a9070f3..c2af5362 100644 --- a/cpp/src/lib/messages/cucumber/messages/test_case.cpp +++ b/cpp/src/lib/messages/cucumber/messages/test_case.cpp @@ -13,6 +13,7 @@ test_case::to_string() const cucumber::messages::to_string(oss, "id=", id); cucumber::messages::to_string(oss, ", pickle_id=", pickle_id); cucumber::messages::to_string(oss, ", test_steps=", test_steps); + cucumber::messages::to_string(oss, ", test_run_started_id=", test_run_started_id); return oss.str(); } @@ -23,6 +24,7 @@ test_case::to_json(json& j) const cucumber::messages::to_json(j, camelize("id"), id); cucumber::messages::to_json(j, camelize("pickle_id"), pickle_id); cucumber::messages::to_json(j, camelize("test_steps"), test_steps); + cucumber::messages::to_json(j, camelize("test_run_started_id"), test_run_started_id); } std::string diff --git a/cpp/src/lib/messages/cucumber/messages/test_run_finished.cpp b/cpp/src/lib/messages/cucumber/messages/test_run_finished.cpp index f2c179e8..ce8ff84d 100644 --- a/cpp/src/lib/messages/cucumber/messages/test_run_finished.cpp +++ b/cpp/src/lib/messages/cucumber/messages/test_run_finished.cpp @@ -14,6 +14,7 @@ test_run_finished::to_string() const cucumber::messages::to_string(oss, ", success=", success); cucumber::messages::to_string(oss, ", timestamp=", timestamp); cucumber::messages::to_string(oss, ", exception=", exception); + cucumber::messages::to_string(oss, ", test_run_started_id=", test_run_started_id); return oss.str(); } @@ -25,6 +26,7 @@ test_run_finished::to_json(json& j) const cucumber::messages::to_json(j, camelize("success"), success); cucumber::messages::to_json(j, camelize("timestamp"), timestamp); cucumber::messages::to_json(j, camelize("exception"), exception); + cucumber::messages::to_json(j, camelize("test_run_started_id"), test_run_started_id); } std::string diff --git a/cpp/src/lib/messages/cucumber/messages/test_run_hook_finished.cpp b/cpp/src/lib/messages/cucumber/messages/test_run_hook_finished.cpp new file mode 100644 index 00000000..a850dcd6 --- /dev/null +++ b/cpp/src/lib/messages/cucumber/messages/test_run_hook_finished.cpp @@ -0,0 +1,52 @@ +#include + +#include +#include + +namespace cucumber::messages { + +std::string +test_run_hook_finished::to_string() const +{ + std::ostringstream oss; + + cucumber::messages::to_string(oss, "test_run_hook_started_id=", test_run_hook_started_id); + cucumber::messages::to_string(oss, ", result=", result); + cucumber::messages::to_string(oss, ", timestamp=", timestamp); + + return oss.str(); +} + +void +test_run_hook_finished::to_json(json& j) const +{ + cucumber::messages::to_json(j, camelize("test_run_hook_started_id"), test_run_hook_started_id); + cucumber::messages::to_json(j, camelize("result"), result); + cucumber::messages::to_json(j, camelize("timestamp"), timestamp); +} + +std::string +test_run_hook_finished::to_json() const +{ + std::ostringstream oss; + json j; + + to_json(j); + + oss << j; + + return oss.str(); +} + +std::ostream& +operator<<(std::ostream& os, const test_run_hook_finished& msg) +{ + os << msg.to_string(); + + return os; +} + +void to_json(json& j, const test_run_hook_finished& m) +{ m.to_json(j); } + +} diff --git a/cpp/src/lib/messages/cucumber/messages/test_run_hook_started.cpp b/cpp/src/lib/messages/cucumber/messages/test_run_hook_started.cpp new file mode 100644 index 00000000..6cfda313 --- /dev/null +++ b/cpp/src/lib/messages/cucumber/messages/test_run_hook_started.cpp @@ -0,0 +1,54 @@ +#include + +#include +#include + +namespace cucumber::messages { + +std::string +test_run_hook_started::to_string() const +{ + std::ostringstream oss; + + cucumber::messages::to_string(oss, "id=", id); + cucumber::messages::to_string(oss, ", test_run_started_id=", test_run_started_id); + cucumber::messages::to_string(oss, ", hook_id=", hook_id); + cucumber::messages::to_string(oss, ", timestamp=", timestamp); + + return oss.str(); +} + +void +test_run_hook_started::to_json(json& j) const +{ + cucumber::messages::to_json(j, camelize("id"), id); + cucumber::messages::to_json(j, camelize("test_run_started_id"), test_run_started_id); + cucumber::messages::to_json(j, camelize("hook_id"), hook_id); + cucumber::messages::to_json(j, camelize("timestamp"), timestamp); +} + +std::string +test_run_hook_started::to_json() const +{ + std::ostringstream oss; + json j; + + to_json(j); + + oss << j; + + return oss.str(); +} + +std::ostream& +operator<<(std::ostream& os, const test_run_hook_started& msg) +{ + os << msg.to_string(); + + return os; +} + +void to_json(json& j, const test_run_hook_started& m) +{ m.to_json(j); } + +} diff --git a/cpp/src/lib/messages/cucumber/messages/test_run_started.cpp b/cpp/src/lib/messages/cucumber/messages/test_run_started.cpp index 0ce5fdd9..5ef9a001 100644 --- a/cpp/src/lib/messages/cucumber/messages/test_run_started.cpp +++ b/cpp/src/lib/messages/cucumber/messages/test_run_started.cpp @@ -11,6 +11,7 @@ test_run_started::to_string() const std::ostringstream oss; cucumber::messages::to_string(oss, "timestamp=", timestamp); + cucumber::messages::to_string(oss, ", id=", id); return oss.str(); } @@ -19,6 +20,7 @@ void test_run_started::to_json(json& j) const { cucumber::messages::to_json(j, camelize("timestamp"), timestamp); + cucumber::messages::to_json(j, camelize("id"), id); } std::string diff --git a/dotnet/Cucumber.Messages.Specs/BasicMessageSerializationTests.cs b/dotnet/Cucumber.Messages.Specs/BasicMessageSerializationTests.cs index 7085b391..88e6730c 100644 --- a/dotnet/Cucumber.Messages.Specs/BasicMessageSerializationTests.cs +++ b/dotnet/Cucumber.Messages.Specs/BasicMessageSerializationTests.cs @@ -24,7 +24,7 @@ public void SerializesAnEnvelopeToNDJSONCorrectly() null, null, new Location(3, null)); var stepDefPattern = new StepDefinitionPattern("I have {int} cukes in my belly", StepDefinitionPatternType.CUCUMBER_EXPRESSION); var stepDefinition = new StepDefinition("0", stepDefPattern, sourceReference); - var env = new Envelope(null, null, null, null, null, null, null, null, stepDefinition, null, null, null, null, null, null, null, null); + var env = new Envelope(null, null, null, null, null, null, null, null, stepDefinition, null, null, null, null, null, null, null, null, null, null); var serializedStepDefinition = NdjsonSerializer.Serialize(env); var reconstructedStepDefinition = NdjsonSerializer.Deserialize(serializedStepDefinition); diff --git a/dotnet/Cucumber.Messages.Specs/MessagesTest.cs b/dotnet/Cucumber.Messages.Specs/MessagesTest.cs index eeb4e64a..88d4d5f0 100644 --- a/dotnet/Cucumber.Messages.Specs/MessagesTest.cs +++ b/dotnet/Cucumber.Messages.Specs/MessagesTest.cs @@ -21,7 +21,7 @@ public void ThrowsWhenRequiredFieldsAreMissing() public void IsValidWhenNoRequiredFieldsAreMissing() { // This should succeed as no constructor arguments to an Envelope are required. - var env = new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + var env = new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); } } } diff --git a/dotnet/Cucumber.Messages.Specs/NdjsonStreamSerializationTests.cs b/dotnet/Cucumber.Messages.Specs/NdjsonStreamSerializationTests.cs index cb51b3ed..3c763579 100644 --- a/dotnet/Cucumber.Messages.Specs/NdjsonStreamSerializationTests.cs +++ b/dotnet/Cucumber.Messages.Specs/NdjsonStreamSerializationTests.cs @@ -30,7 +30,7 @@ public void DoesNotSerializeNullFields() { MemoryStream memoryStream = new MemoryStream(); var writer = new MessageToNdjsonWriterSUT(memoryStream); - writer.Write(new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)); + writer.Write(new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)); var json = Encoding.UTF8.GetString(memoryStream.ToArray()); Assert.Equal("{}"+Environment.NewLine, json); @@ -42,7 +42,7 @@ public void IgnoresEmptyLines() MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes("{}\n{}\n\n{}\n")); var enumerator = new NdjsonMessageReaderSUT(memoryStream).GetEnumerator(); - var expectedEnvelope = new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + var expectedEnvelope = new Envelope(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); for (int i = 0; i < 3; i++) { Assert.True(enumerator.MoveNext()); @@ -66,19 +66,6 @@ public void Handles_Enums() Assert.False(enumerator.MoveNext()); } - [Fact] - public void Handles_Single_Argument_Constructor() - { - MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes("{\"testRunStarted\": {\"timestamp\":{\"nanos\":0,\"seconds\":0}}}\n")); - var enumerator = new NdjsonMessageReaderSUT(memoryStream).GetEnumerator(); - Assert.True(enumerator.MoveNext()); - Envelope envelope = enumerator.Current; - Envelope expected = Envelope.Create(new TestRunStarted(new Timestamp(0, 0))); - - Assert.Equal(expected, envelope); - Assert.False(enumerator.MoveNext()); - } - [Fact] public void Includes_Offending_Line_In_Error_Message() { diff --git a/dotnet/Cucumber.Messages/generated/Attachment.cs b/dotnet/Cucumber.Messages/generated/Attachment.cs index 40eee186..0177ba31 100644 --- a/dotnet/Cucumber.Messages/generated/Attachment.cs +++ b/dotnet/Cucumber.Messages/generated/Attachment.cs @@ -73,6 +73,7 @@ public sealed class Attachment * separately from reports. */ public string Url { get; private set; } + public string TestRunStartedId { get; private set; } public Attachment( @@ -83,7 +84,8 @@ public Attachment( Source source, string testCaseStartedId, string testStepId, - string url + string url, + string testRunStartedId ) { RequireNonNull(body, "Body", "Attachment.Body cannot be null"); @@ -97,6 +99,7 @@ string url this.TestCaseStartedId = testCaseStartedId; this.TestStepId = testStepId; this.Url = url; + this.TestRunStartedId = testRunStartedId; } public override bool Equals(Object o) @@ -112,7 +115,8 @@ public override bool Equals(Object o) Object.Equals(Source, that.Source) && Object.Equals(TestCaseStartedId, that.TestCaseStartedId) && Object.Equals(TestStepId, that.TestStepId) && - Object.Equals(Url, that.Url); + Object.Equals(Url, that.Url) && + Object.Equals(TestRunStartedId, that.TestRunStartedId); } public override int GetHashCode() @@ -133,6 +137,8 @@ public override int GetHashCode() hash = hash * 31 + TestStepId.GetHashCode(); if (Url != null) hash = hash * 31 + Url.GetHashCode(); + if (TestRunStartedId != null) + hash = hash * 31 + TestRunStartedId.GetHashCode(); return hash; } @@ -147,6 +153,7 @@ public override string ToString() ", testCaseStartedId=" + TestCaseStartedId + ", testStepId=" + TestStepId + ", url=" + Url + + ", testRunStartedId=" + TestRunStartedId + '}'; } diff --git a/dotnet/Cucumber.Messages/generated/Envelope.cs b/dotnet/Cucumber.Messages/generated/Envelope.cs index cf9a0340..8c7c3449 100644 --- a/dotnet/Cucumber.Messages/generated/Envelope.cs +++ b/dotnet/Cucumber.Messages/generated/Envelope.cs @@ -39,6 +39,8 @@ public sealed class Envelope public TestRunStarted TestRunStarted { get; private set; } public TestStepFinished TestStepFinished { get; private set; } public TestStepStarted TestStepStarted { get; private set; } + public TestRunHookStarted TestRunHookStarted { get; private set; } + public TestRunHookFinished TestRunHookFinished { get; private set; } public UndefinedParameterType UndefinedParameterType { get; private set; } @@ -61,6 +63,8 @@ public static Envelope Create(Attachment attachment) null, null, null, + null, + null, null ); } @@ -84,6 +88,8 @@ public static Envelope Create(GherkinDocument gherkinDocument) null, null, null, + null, + null, null ); } @@ -107,6 +113,8 @@ public static Envelope Create(Hook hook) null, null, null, + null, + null, null ); } @@ -130,6 +138,8 @@ public static Envelope Create(Meta meta) null, null, null, + null, + null, null ); } @@ -153,6 +163,8 @@ public static Envelope Create(ParameterType parameterType) null, null, null, + null, + null, null ); } @@ -176,6 +188,8 @@ public static Envelope Create(ParseError parseError) null, null, null, + null, + null, null ); } @@ -199,6 +213,8 @@ public static Envelope Create(Pickle pickle) null, null, null, + null, + null, null ); } @@ -222,6 +238,8 @@ public static Envelope Create(Source source) null, null, null, + null, + null, null ); } @@ -245,6 +263,8 @@ public static Envelope Create(StepDefinition stepDefinition) null, null, null, + null, + null, null ); } @@ -268,6 +288,8 @@ public static Envelope Create(TestCase testCase) null, null, null, + null, + null, null ); } @@ -291,6 +313,8 @@ public static Envelope Create(TestCaseFinished testCaseFinished) null, null, null, + null, + null, null ); } @@ -314,6 +338,8 @@ public static Envelope Create(TestCaseStarted testCaseStarted) null, null, null, + null, + null, null ); } @@ -337,6 +363,8 @@ public static Envelope Create(TestRunFinished testRunFinished) null, null, null, + null, + null, null ); } @@ -360,6 +388,8 @@ public static Envelope Create(TestRunStarted testRunStarted) Require(testRunStarted, "TestRunStarted", "Envelope.TestRunStarted cannot be null"), null, null, + null, + null, null ); } @@ -383,6 +413,8 @@ public static Envelope Create(TestStepFinished testStepFinished) null, Require(testStepFinished, "TestStepFinished", "Envelope.TestStepFinished cannot be null"), null, + null, + null, null ); } @@ -406,6 +438,58 @@ public static Envelope Create(TestStepStarted testStepStarted) null, null, Require(testStepStarted, "TestStepStarted", "Envelope.TestStepStarted cannot be null"), + null, + null, + null + ); + } + + public static Envelope Create(TestRunHookStarted testRunHookStarted) + { + return new Envelope( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + Require(testRunHookStarted, "TestRunHookStarted", "Envelope.TestRunHookStarted cannot be null"), + null, + null + ); + } + + public static Envelope Create(TestRunHookFinished testRunHookFinished) + { + return new Envelope( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + Require(testRunHookFinished, "TestRunHookFinished", "Envelope.TestRunHookFinished cannot be null"), null ); } @@ -429,6 +513,8 @@ public static Envelope Create(UndefinedParameterType undefinedParameterType) null, null, null, + null, + null, Require(undefinedParameterType, "UndefinedParameterType", "Envelope.UndefinedParameterType cannot be null") ); } @@ -450,6 +536,8 @@ public Envelope( TestRunStarted testRunStarted, TestStepFinished testStepFinished, TestStepStarted testStepStarted, + TestRunHookStarted testRunHookStarted, + TestRunHookFinished testRunHookFinished, UndefinedParameterType undefinedParameterType ) { @@ -469,6 +557,8 @@ UndefinedParameterType undefinedParameterType this.TestRunStarted = testRunStarted; this.TestStepFinished = testStepFinished; this.TestStepStarted = testStepStarted; + this.TestRunHookStarted = testRunHookStarted; + this.TestRunHookFinished = testRunHookFinished; this.UndefinedParameterType = undefinedParameterType; } @@ -494,6 +584,8 @@ public override bool Equals(Object o) Object.Equals(TestRunStarted, that.TestRunStarted) && Object.Equals(TestStepFinished, that.TestStepFinished) && Object.Equals(TestStepStarted, that.TestStepStarted) && + Object.Equals(TestRunHookStarted, that.TestRunHookStarted) && + Object.Equals(TestRunHookFinished, that.TestRunHookFinished) && Object.Equals(UndefinedParameterType, that.UndefinedParameterType); } @@ -532,6 +624,10 @@ public override int GetHashCode() hash = hash * 31 + TestStepFinished.GetHashCode(); if (TestStepStarted != null) hash = hash * 31 + TestStepStarted.GetHashCode(); + if (TestRunHookStarted != null) + hash = hash * 31 + TestRunHookStarted.GetHashCode(); + if (TestRunHookFinished != null) + hash = hash * 31 + TestRunHookFinished.GetHashCode(); if (UndefinedParameterType != null) hash = hash * 31 + UndefinedParameterType.GetHashCode(); return hash; @@ -556,6 +652,8 @@ public override string ToString() ", testRunStarted=" + TestRunStarted + ", testStepFinished=" + TestStepFinished + ", testStepStarted=" + TestStepStarted + + ", testRunHookStarted=" + TestRunHookStarted + + ", testRunHookFinished=" + TestRunHookFinished + ", undefinedParameterType=" + UndefinedParameterType + '}'; } diff --git a/dotnet/Cucumber.Messages/generated/Hook.cs b/dotnet/Cucumber.Messages/generated/Hook.cs index 48249f1e..eaca150b 100644 --- a/dotnet/Cucumber.Messages/generated/Hook.cs +++ b/dotnet/Cucumber.Messages/generated/Hook.cs @@ -20,13 +20,15 @@ public sealed class Hook public string Name { get; private set; } public SourceReference SourceReference { get; private set; } public string TagExpression { get; private set; } + public HookType Type { get; private set; } public Hook( string id, string name, SourceReference sourceReference, - string tagExpression + string tagExpression, + HookType type ) { RequireNonNull(id, "Id", "Hook.Id cannot be null"); @@ -35,6 +37,7 @@ string tagExpression RequireNonNull(sourceReference, "SourceReference", "Hook.SourceReference cannot be null"); this.SourceReference = sourceReference; this.TagExpression = tagExpression; + this.Type = type; } public override bool Equals(Object o) @@ -46,7 +49,8 @@ public override bool Equals(Object o) Id.Equals(that.Id) && Object.Equals(Name, that.Name) && SourceReference.Equals(that.SourceReference) && - Object.Equals(TagExpression, that.TagExpression); + Object.Equals(TagExpression, that.TagExpression) && + Object.Equals(Type, that.Type); } public override int GetHashCode() @@ -60,6 +64,7 @@ public override int GetHashCode() hash = hash * 31 + SourceReference.GetHashCode(); if (TagExpression != null) hash = hash * 31 + TagExpression.GetHashCode(); + hash = hash * 31 + Type.GetHashCode(); return hash; } @@ -70,6 +75,7 @@ public override string ToString() ", name=" + Name + ", sourceReference=" + SourceReference + ", tagExpression=" + TagExpression + + ", type=" + Type + '}'; } diff --git a/dotnet/Cucumber.Messages/generated/HookType.cs b/dotnet/Cucumber.Messages/generated/HookType.cs new file mode 100644 index 00000000..ebc0e22a --- /dev/null +++ b/dotnet/Cucumber.Messages/generated/HookType.cs @@ -0,0 +1,40 @@ +using System; +using System.ComponentModel; +using System.Reflection; + +namespace Io.Cucumber.Messages.Types; + +// ------------------------------------------------------------------------------ +// This code was generated based on the Cucumber JSON schema +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// ------------------------------------------------------------------------------ + +public enum HookType { + + [Description("BEFORE_TEST_RUN")] + BEFORE_TEST_RUN, + + [Description("AFTER_TEST_RUN")] + AFTER_TEST_RUN, + + [Description("BEFORE_TEST_CASE")] + BEFORE_TEST_CASE, + + [Description("AFTER_TEST_CASE")] + AFTER_TEST_CASE, + + [Description("BEFORE_TEST_STEP")] + BEFORE_TEST_STEP, + + [Description("AFTER_TEST_STEP")] + AFTER_TEST_STEP +} + +public static class HookTypeExtensions +{ + public static string Value(this HookType v) { + var attribute = v.GetType().GetField(v.ToString()).GetCustomAttribute(); + return attribute == null ? v.ToString() : attribute.Description; + } +} diff --git a/dotnet/Cucumber.Messages/generated/TestCase.cs b/dotnet/Cucumber.Messages/generated/TestCase.cs index ff83e89a..79667bbd 100644 --- a/dotnet/Cucumber.Messages/generated/TestCase.cs +++ b/dotnet/Cucumber.Messages/generated/TestCase.cs @@ -26,12 +26,17 @@ public sealed class TestCase */ public string PickleId { get; private set; } public List TestSteps { get; private set; } + /** + * Identifier for the test run that this test case belongs to + */ + public string TestRunStartedId { get; private set; } public TestCase( string id, string pickleId, - List testSteps + List testSteps, + string testRunStartedId ) { RequireNonNull(id, "Id", "TestCase.Id cannot be null"); @@ -40,6 +45,7 @@ List testSteps this.PickleId = pickleId; RequireNonNull>(testSteps, "TestSteps", "TestCase.TestSteps cannot be null"); this.TestSteps = new List(testSteps); + this.TestRunStartedId = testRunStartedId; } public override bool Equals(Object o) @@ -50,7 +56,8 @@ public override bool Equals(Object o) return Id.Equals(that.Id) && PickleId.Equals(that.PickleId) && - TestSteps.Equals(that.TestSteps); + TestSteps.Equals(that.TestSteps) && + Object.Equals(TestRunStartedId, that.TestRunStartedId); } public override int GetHashCode() @@ -62,6 +69,8 @@ public override int GetHashCode() hash = hash * 31 + PickleId.GetHashCode(); if (TestSteps != null) hash = hash * 31 + TestSteps.GetHashCode(); + if (TestRunStartedId != null) + hash = hash * 31 + TestRunStartedId.GetHashCode(); return hash; } @@ -71,6 +80,7 @@ public override string ToString() "id=" + Id + ", pickleId=" + PickleId + ", testSteps=" + TestSteps + + ", testRunStartedId=" + TestRunStartedId + '}'; } diff --git a/dotnet/Cucumber.Messages/generated/TestRunFinished.cs b/dotnet/Cucumber.Messages/generated/TestRunFinished.cs index 97c60929..804f27f6 100644 --- a/dotnet/Cucumber.Messages/generated/TestRunFinished.cs +++ b/dotnet/Cucumber.Messages/generated/TestRunFinished.cs @@ -32,13 +32,15 @@ public sealed class TestRunFinished * Any exception thrown during the test run, if any. Does not include exceptions thrown while executing steps. */ public Exception Exception { get; private set; } + public string TestRunStartedId { get; private set; } public TestRunFinished( string message, bool success, Timestamp timestamp, - Exception exception + Exception exception, + string testRunStartedId ) { this.Message = message; @@ -47,6 +49,7 @@ Exception exception RequireNonNull(timestamp, "Timestamp", "TestRunFinished.Timestamp cannot be null"); this.Timestamp = timestamp; this.Exception = exception; + this.TestRunStartedId = testRunStartedId; } public override bool Equals(Object o) @@ -58,7 +61,8 @@ public override bool Equals(Object o) Object.Equals(Message, that.Message) && Success.Equals(that.Success) && Timestamp.Equals(that.Timestamp) && - Object.Equals(Exception, that.Exception); + Object.Equals(Exception, that.Exception) && + Object.Equals(TestRunStartedId, that.TestRunStartedId); } public override int GetHashCode() @@ -71,6 +75,8 @@ public override int GetHashCode() hash = hash * 31 + Timestamp.GetHashCode(); if (Exception != null) hash = hash * 31 + Exception.GetHashCode(); + if (TestRunStartedId != null) + hash = hash * 31 + TestRunStartedId.GetHashCode(); return hash; } @@ -81,6 +87,7 @@ public override string ToString() ", success=" + Success + ", timestamp=" + Timestamp + ", exception=" + Exception + + ", testRunStartedId=" + TestRunStartedId + '}'; } diff --git a/dotnet/Cucumber.Messages/generated/TestRunHookFinished.cs b/dotnet/Cucumber.Messages/generated/TestRunHookFinished.cs new file mode 100644 index 00000000..a5b92907 --- /dev/null +++ b/dotnet/Cucumber.Messages/generated/TestRunHookFinished.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; + +// ------------------------------------------------------------------------------ +// This code was generated based on the Cucumber JSON schema +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// ------------------------------------------------------------------------------ + +namespace Io.Cucumber.Messages.Types; + +/** + * Represents the TestRunHookFinished message in Cucumber's message protocol + * @see Github - Cucumber - Messages + */ + +public sealed class TestRunHookFinished +{ + /** + * Identifier for the hook execution that has finished + */ + public string TestRunHookStartedId { get; private set; } + public TestStepResult Result { get; private set; } + public Timestamp Timestamp { get; private set; } + + + public TestRunHookFinished( + string testRunHookStartedId, + TestStepResult result, + Timestamp timestamp + ) + { + RequireNonNull(testRunHookStartedId, "TestRunHookStartedId", "TestRunHookFinished.TestRunHookStartedId cannot be null"); + this.TestRunHookStartedId = testRunHookStartedId; + RequireNonNull(result, "Result", "TestRunHookFinished.Result cannot be null"); + this.Result = result; + RequireNonNull(timestamp, "Timestamp", "TestRunHookFinished.Timestamp cannot be null"); + this.Timestamp = timestamp; + } + + public override bool Equals(Object o) + { + if (this == o) return true; + if (o == null || this.GetType() != o.GetType()) return false; + TestRunHookFinished that = (TestRunHookFinished) o; + return + TestRunHookStartedId.Equals(that.TestRunHookStartedId) && + Result.Equals(that.Result) && + Timestamp.Equals(that.Timestamp); + } + + public override int GetHashCode() + { + int hash = 17; + if (TestRunHookStartedId != null) + hash = hash * 31 + TestRunHookStartedId.GetHashCode(); + if (Result != null) + hash = hash * 31 + Result.GetHashCode(); + if (Timestamp != null) + hash = hash * 31 + Timestamp.GetHashCode(); + return hash; + } + + public override string ToString() + { + return "TestRunHookFinished{" + + "testRunHookStartedId=" + TestRunHookStartedId + + ", result=" + Result + + ", timestamp=" + Timestamp + + '}'; + } + + private static T Require(T property, string propertyName, string errorMessage) + { + RequireNonNull(property, propertyName, errorMessage); + return property; + } + private static void RequireNonNull(T property, string propertyName, string errorMessage) + { + if (property == null) throw new ArgumentNullException(propertyName, errorMessage); + } +} diff --git a/dotnet/Cucumber.Messages/generated/TestRunHookStarted.cs b/dotnet/Cucumber.Messages/generated/TestRunHookStarted.cs new file mode 100644 index 00000000..3f8a92a6 --- /dev/null +++ b/dotnet/Cucumber.Messages/generated/TestRunHookStarted.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; + +// ------------------------------------------------------------------------------ +// This code was generated based on the Cucumber JSON schema +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// ------------------------------------------------------------------------------ + +namespace Io.Cucumber.Messages.Types; + +/** + * Represents the TestRunHookStarted message in Cucumber's message protocol + * @see Github - Cucumber - Messages + */ + +public sealed class TestRunHookStarted +{ + /** + * Unique identifier for this hook execution + */ + public string Id { get; private set; } + /** + * Identifier for the test run that this hook execution belongs to + */ + public string TestRunStartedId { get; private set; } + /** + * Identifier for the hook that will be executed + */ + public string HookId { get; private set; } + public Timestamp Timestamp { get; private set; } + + + public TestRunHookStarted( + string id, + string testRunStartedId, + string hookId, + Timestamp timestamp + ) + { + RequireNonNull(id, "Id", "TestRunHookStarted.Id cannot be null"); + this.Id = id; + RequireNonNull(testRunStartedId, "TestRunStartedId", "TestRunHookStarted.TestRunStartedId cannot be null"); + this.TestRunStartedId = testRunStartedId; + RequireNonNull(hookId, "HookId", "TestRunHookStarted.HookId cannot be null"); + this.HookId = hookId; + RequireNonNull(timestamp, "Timestamp", "TestRunHookStarted.Timestamp cannot be null"); + this.Timestamp = timestamp; + } + + public override bool Equals(Object o) + { + if (this == o) return true; + if (o == null || this.GetType() != o.GetType()) return false; + TestRunHookStarted that = (TestRunHookStarted) o; + return + Id.Equals(that.Id) && + TestRunStartedId.Equals(that.TestRunStartedId) && + HookId.Equals(that.HookId) && + Timestamp.Equals(that.Timestamp); + } + + public override int GetHashCode() + { + int hash = 17; + if (Id != null) + hash = hash * 31 + Id.GetHashCode(); + if (TestRunStartedId != null) + hash = hash * 31 + TestRunStartedId.GetHashCode(); + if (HookId != null) + hash = hash * 31 + HookId.GetHashCode(); + if (Timestamp != null) + hash = hash * 31 + Timestamp.GetHashCode(); + return hash; + } + + public override string ToString() + { + return "TestRunHookStarted{" + + "id=" + Id + + ", testRunStartedId=" + TestRunStartedId + + ", hookId=" + HookId + + ", timestamp=" + Timestamp + + '}'; + } + + private static T Require(T property, string propertyName, string errorMessage) + { + RequireNonNull(property, propertyName, errorMessage); + return property; + } + private static void RequireNonNull(T property, string propertyName, string errorMessage) + { + if (property == null) throw new ArgumentNullException(propertyName, errorMessage); + } +} diff --git a/dotnet/Cucumber.Messages/generated/TestRunStarted.cs b/dotnet/Cucumber.Messages/generated/TestRunStarted.cs index e6ec5c0e..8be53ece 100644 --- a/dotnet/Cucumber.Messages/generated/TestRunStarted.cs +++ b/dotnet/Cucumber.Messages/generated/TestRunStarted.cs @@ -17,14 +17,17 @@ namespace Io.Cucumber.Messages.Types; public sealed class TestRunStarted { public Timestamp Timestamp { get; private set; } + public string Id { get; private set; } public TestRunStarted( - Timestamp timestamp + Timestamp timestamp, + string id ) { RequireNonNull(timestamp, "Timestamp", "TestRunStarted.Timestamp cannot be null"); this.Timestamp = timestamp; + this.Id = id; } public override bool Equals(Object o) @@ -33,7 +36,8 @@ public override bool Equals(Object o) if (o == null || this.GetType() != o.GetType()) return false; TestRunStarted that = (TestRunStarted) o; return - Timestamp.Equals(that.Timestamp); + Timestamp.Equals(that.Timestamp) && + Object.Equals(Id, that.Id); } public override int GetHashCode() @@ -41,6 +45,8 @@ public override int GetHashCode() int hash = 17; if (Timestamp != null) hash = hash * 31 + Timestamp.GetHashCode(); + if (Id != null) + hash = hash * 31 + Id.GetHashCode(); return hash; } @@ -48,6 +54,7 @@ public override string ToString() { return "TestRunStarted{" + "timestamp=" + Timestamp + + ", id=" + Id + '}'; } diff --git a/go/messages.go b/go/messages.go index e7dc6169..eaba8e4b 100644 --- a/go/messages.go +++ b/go/messages.go @@ -9,6 +9,7 @@ type Attachment struct { TestCaseStartedId string `json:"testCaseStartedId,omitempty"` TestStepId string `json:"testStepId,omitempty"` Url string `json:"url,omitempty"` + TestRunStartedId string `json:"testRunStartedId,omitempty"` } type Duration struct { @@ -33,6 +34,8 @@ type Envelope struct { TestRunStarted *TestRunStarted `json:"testRunStarted,omitempty"` TestStepFinished *TestStepFinished `json:"testStepFinished,omitempty"` TestStepStarted *TestStepStarted `json:"testStepStarted,omitempty"` + TestRunHookStarted *TestRunHookStarted `json:"testRunHookStarted,omitempty"` + TestRunHookFinished *TestRunHookFinished `json:"testRunHookFinished,omitempty"` UndefinedParameterType *UndefinedParameterType `json:"undefinedParameterType,omitempty"` } @@ -159,6 +162,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 { @@ -290,9 +294,10 @@ type StepDefinitionPattern struct { } type TestCase struct { - Id string `json:"id"` - PickleId string `json:"pickleId"` - TestSteps []*TestStep `json:"testSteps"` + Id string `json:"id"` + PickleId string `json:"pickleId"` + TestSteps []*TestStep `json:"testSteps"` + TestRunStartedId string `json:"testRunStartedId,omitempty"` } type Group struct { @@ -333,14 +338,29 @@ type TestCaseStarted struct { } type TestRunFinished struct { - Message string `json:"message,omitempty"` - Success bool `json:"success"` - Timestamp *Timestamp `json:"timestamp"` - Exception *Exception `json:"exception,omitempty"` + Message string `json:"message,omitempty"` + Success bool `json:"success"` + Timestamp *Timestamp `json:"timestamp"` + Exception *Exception `json:"exception,omitempty"` + TestRunStartedId string `json:"testRunStartedId,omitempty"` +} + +type TestRunHookFinished struct { + TestRunHookStartedId string `json:"testRunHookStartedId"` + Result *TestStepResult `json:"result"` + Timestamp *Timestamp `json:"timestamp"` +} + +type TestRunHookStarted struct { + Id string `json:"id"` + TestRunStartedId string `json:"testRunStartedId"` + HookId string `json:"hookId"` + Timestamp *Timestamp `json:"timestamp"` } type TestRunStarted struct { Timestamp *Timestamp `json:"timestamp"` + Id string `json:"id,omitempty"` } type TestStepFinished struct { @@ -391,6 +411,36 @@ func (e AttachmentContentEncoding) String() string { } } +type HookType string + +const ( + HookType_BEFORE_TEST_RUN HookType = "BEFORE_TEST_RUN" + HookType_AFTER_TEST_RUN HookType = "AFTER_TEST_RUN" + HookType_BEFORE_TEST_CASE HookType = "BEFORE_TEST_CASE" + HookType_AFTER_TEST_CASE HookType = "AFTER_TEST_CASE" + HookType_BEFORE_TEST_STEP HookType = "BEFORE_TEST_STEP" + HookType_AFTER_TEST_STEP HookType = "AFTER_TEST_STEP" +) + +func (e HookType) String() string { + switch e { + case HookType_BEFORE_TEST_RUN: + return "BEFORE_TEST_RUN" + case HookType_AFTER_TEST_RUN: + return "AFTER_TEST_RUN" + case HookType_BEFORE_TEST_CASE: + return "BEFORE_TEST_CASE" + case HookType_AFTER_TEST_CASE: + return "AFTER_TEST_CASE" + case HookType_BEFORE_TEST_STEP: + return "BEFORE_TEST_STEP" + case HookType_AFTER_TEST_STEP: + return "AFTER_TEST_STEP" + default: + panic("Bad enum value for HookType") + } +} + type PickleStepType string const ( diff --git a/java/src/generated/java/io/cucumber/messages/types/Attachment.java b/java/src/generated/java/io/cucumber/messages/types/Attachment.java index 91e3fe25..3bf3401e 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Attachment.java +++ b/java/src/generated/java/io/cucumber/messages/types/Attachment.java @@ -34,6 +34,7 @@ public final class Attachment { private final String testCaseStartedId; private final String testStepId; private final String url; + private final String testRunStartedId; public Attachment( String body, @@ -43,7 +44,8 @@ public Attachment( Source source, String testCaseStartedId, String testStepId, - String url + String url, + String testRunStartedId ) { this.body = requireNonNull(body, "Attachment.body cannot be null"); this.contentEncoding = requireNonNull(contentEncoding, "Attachment.contentEncoding cannot be null"); @@ -53,6 +55,7 @@ public Attachment( this.testCaseStartedId = testCaseStartedId; this.testStepId = testStepId; this.url = url; + this.testRunStartedId = testRunStartedId; } /** @@ -124,6 +127,10 @@ public Optional getUrl() { return Optional.ofNullable(url); } + public Optional getTestRunStartedId() { + return Optional.ofNullable(testRunStartedId); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -137,7 +144,8 @@ public boolean equals(Object o) { Objects.equals(source, that.source) && Objects.equals(testCaseStartedId, that.testCaseStartedId) && Objects.equals(testStepId, that.testStepId) && - Objects.equals(url, that.url); + Objects.equals(url, that.url) && + Objects.equals(testRunStartedId, that.testRunStartedId); } @Override @@ -150,7 +158,8 @@ public int hashCode() { source, testCaseStartedId, testStepId, - url + url, + testRunStartedId ); } @@ -165,6 +174,7 @@ public String toString() { ", testCaseStartedId=" + testCaseStartedId + ", testStepId=" + testStepId + ", url=" + url + + ", testRunStartedId=" + testRunStartedId + '}'; } } diff --git a/java/src/generated/java/io/cucumber/messages/types/Envelope.java b/java/src/generated/java/io/cucumber/messages/types/Envelope.java index 9b764ba9..2aaf01af 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Envelope.java +++ b/java/src/generated/java/io/cucumber/messages/types/Envelope.java @@ -37,6 +37,8 @@ public final class Envelope { private final TestRunStarted testRunStarted; private final TestStepFinished testStepFinished; private final TestStepStarted testStepStarted; + private final TestRunHookStarted testRunHookStarted; + private final TestRunHookFinished testRunHookFinished; private final UndefinedParameterType undefinedParameterType; public static Envelope of(Attachment attachment) { @@ -57,6 +59,8 @@ public static Envelope of(Attachment attachment) { null, null, null, + null, + null, null ); } @@ -79,6 +83,8 @@ public static Envelope of(GherkinDocument gherkinDocument) { null, null, null, + null, + null, null ); } @@ -101,6 +107,8 @@ public static Envelope of(Hook hook) { null, null, null, + null, + null, null ); } @@ -123,6 +131,8 @@ public static Envelope of(Meta meta) { null, null, null, + null, + null, null ); } @@ -145,6 +155,8 @@ public static Envelope of(ParameterType parameterType) { null, null, null, + null, + null, null ); } @@ -167,6 +179,8 @@ public static Envelope of(ParseError parseError) { null, null, null, + null, + null, null ); } @@ -189,6 +203,8 @@ public static Envelope of(Pickle pickle) { null, null, null, + null, + null, null ); } @@ -211,6 +227,8 @@ public static Envelope of(Source source) { null, null, null, + null, + null, null ); } @@ -233,6 +251,8 @@ public static Envelope of(StepDefinition stepDefinition) { null, null, null, + null, + null, null ); } @@ -255,6 +275,8 @@ public static Envelope of(TestCase testCase) { null, null, null, + null, + null, null ); } @@ -277,6 +299,8 @@ public static Envelope of(TestCaseFinished testCaseFinished) { null, null, null, + null, + null, null ); } @@ -299,6 +323,8 @@ public static Envelope of(TestCaseStarted testCaseStarted) { null, null, null, + null, + null, null ); } @@ -321,6 +347,8 @@ public static Envelope of(TestRunFinished testRunFinished) { null, null, null, + null, + null, null ); } @@ -343,6 +371,8 @@ public static Envelope of(TestRunStarted testRunStarted) { requireNonNull(testRunStarted, "Envelope.testRunStarted cannot be null"), null, null, + null, + null, null ); } @@ -365,6 +395,8 @@ public static Envelope of(TestStepFinished testStepFinished) { null, requireNonNull(testStepFinished, "Envelope.testStepFinished cannot be null"), null, + null, + null, null ); } @@ -387,6 +419,56 @@ public static Envelope of(TestStepStarted testStepStarted) { null, null, requireNonNull(testStepStarted, "Envelope.testStepStarted cannot be null"), + null, + null, + null + ); + } + + public static Envelope of(TestRunHookStarted testRunHookStarted) { + return new Envelope( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + requireNonNull(testRunHookStarted, "Envelope.testRunHookStarted cannot be null"), + null, + null + ); + } + + public static Envelope of(TestRunHookFinished testRunHookFinished) { + return new Envelope( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + requireNonNull(testRunHookFinished, "Envelope.testRunHookFinished cannot be null"), null ); } @@ -409,6 +491,8 @@ public static Envelope of(UndefinedParameterType undefinedParameterType) { null, null, null, + null, + null, requireNonNull(undefinedParameterType, "Envelope.undefinedParameterType cannot be null") ); } @@ -430,6 +514,8 @@ public Envelope( TestRunStarted testRunStarted, TestStepFinished testStepFinished, TestStepStarted testStepStarted, + TestRunHookStarted testRunHookStarted, + TestRunHookFinished testRunHookFinished, UndefinedParameterType undefinedParameterType ) { this.attachment = attachment; @@ -448,6 +534,8 @@ public Envelope( this.testRunStarted = testRunStarted; this.testStepFinished = testStepFinished; this.testStepStarted = testStepStarted; + this.testRunHookStarted = testRunHookStarted; + this.testRunHookFinished = testRunHookFinished; this.undefinedParameterType = undefinedParameterType; } @@ -515,6 +603,14 @@ public Optional getTestStepStarted() { return Optional.ofNullable(testStepStarted); } + public Optional getTestRunHookStarted() { + return Optional.ofNullable(testRunHookStarted); + } + + public Optional getTestRunHookFinished() { + return Optional.ofNullable(testRunHookFinished); + } + public Optional getUndefinedParameterType() { return Optional.ofNullable(undefinedParameterType); } @@ -541,6 +637,8 @@ public boolean equals(Object o) { Objects.equals(testRunStarted, that.testRunStarted) && Objects.equals(testStepFinished, that.testStepFinished) && Objects.equals(testStepStarted, that.testStepStarted) && + Objects.equals(testRunHookStarted, that.testRunHookStarted) && + Objects.equals(testRunHookFinished, that.testRunHookFinished) && Objects.equals(undefinedParameterType, that.undefinedParameterType); } @@ -563,6 +661,8 @@ public int hashCode() { testRunStarted, testStepFinished, testStepStarted, + testRunHookStarted, + testRunHookFinished, undefinedParameterType ); } @@ -586,6 +686,8 @@ public String toString() { ", testRunStarted=" + testRunStarted + ", testStepFinished=" + testStepFinished + ", testStepStarted=" + testStepStarted + + ", testRunHookStarted=" + testRunHookStarted + + ", testRunHookFinished=" + testRunHookFinished + ", undefinedParameterType=" + undefinedParameterType + '}'; } 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..0b66ca3a --- /dev/null +++ b/java/src/generated/java/io/cucumber/messages/types/HookType.java @@ -0,0 +1,42 @@ +package io.cucumber.messages.types; + +// Generated code +@SuppressWarnings("unused") +public enum HookType { + + BEFORE_TEST_RUN("BEFORE_TEST_RUN"), + + AFTER_TEST_RUN("AFTER_TEST_RUN"), + + BEFORE_TEST_CASE("BEFORE_TEST_CASE"), + + AFTER_TEST_CASE("AFTER_TEST_CASE"), + + BEFORE_TEST_STEP("BEFORE_TEST_STEP"), + + AFTER_TEST_STEP("AFTER_TEST_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/java/src/generated/java/io/cucumber/messages/types/TestCase.java b/java/src/generated/java/io/cucumber/messages/types/TestCase.java index b7f99366..ee13d471 100644 --- a/java/src/generated/java/io/cucumber/messages/types/TestCase.java +++ b/java/src/generated/java/io/cucumber/messages/types/TestCase.java @@ -21,15 +21,18 @@ public final class TestCase { private final String id; private final String pickleId; private final java.util.List testSteps; + private final String testRunStartedId; public TestCase( String id, String pickleId, - java.util.List testSteps + java.util.List testSteps, + String testRunStartedId ) { this.id = requireNonNull(id, "TestCase.id cannot be null"); this.pickleId = requireNonNull(pickleId, "TestCase.pickleId cannot be null"); this.testSteps = unmodifiableList(new ArrayList<>(requireNonNull(testSteps, "TestCase.testSteps cannot be null"))); + this.testRunStartedId = testRunStartedId; } public String getId() { @@ -47,6 +50,13 @@ public java.util.List getTestSteps() { return testSteps; } + /** + * Identifier for the test run that this test case belongs to + */ + public Optional getTestRunStartedId() { + return Optional.ofNullable(testRunStartedId); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -55,7 +65,8 @@ public boolean equals(Object o) { return id.equals(that.id) && pickleId.equals(that.pickleId) && - testSteps.equals(that.testSteps); + testSteps.equals(that.testSteps) && + Objects.equals(testRunStartedId, that.testRunStartedId); } @Override @@ -63,7 +74,8 @@ public int hashCode() { return Objects.hash( id, pickleId, - testSteps + testSteps, + testRunStartedId ); } @@ -73,6 +85,7 @@ public String toString() { "id=" + id + ", pickleId=" + pickleId + ", testSteps=" + testSteps + + ", testRunStartedId=" + testRunStartedId + '}'; } } diff --git a/java/src/generated/java/io/cucumber/messages/types/TestRunFinished.java b/java/src/generated/java/io/cucumber/messages/types/TestRunFinished.java index 845c0f97..562ec42d 100644 --- a/java/src/generated/java/io/cucumber/messages/types/TestRunFinished.java +++ b/java/src/generated/java/io/cucumber/messages/types/TestRunFinished.java @@ -18,17 +18,20 @@ public final class TestRunFinished { private final Boolean success; private final Timestamp timestamp; private final Exception exception; + private final String testRunStartedId; public TestRunFinished( String message, Boolean success, Timestamp timestamp, - Exception exception + Exception exception, + String testRunStartedId ) { this.message = message; this.success = requireNonNull(success, "TestRunFinished.success cannot be null"); this.timestamp = requireNonNull(timestamp, "TestRunFinished.timestamp cannot be null"); this.exception = exception; + this.testRunStartedId = testRunStartedId; } /** @@ -59,6 +62,10 @@ public Optional getException() { return Optional.ofNullable(exception); } + public Optional getTestRunStartedId() { + return Optional.ofNullable(testRunStartedId); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -68,7 +75,8 @@ public boolean equals(Object o) { Objects.equals(message, that.message) && success.equals(that.success) && timestamp.equals(that.timestamp) && - Objects.equals(exception, that.exception); + Objects.equals(exception, that.exception) && + Objects.equals(testRunStartedId, that.testRunStartedId); } @Override @@ -77,7 +85,8 @@ public int hashCode() { message, success, timestamp, - exception + exception, + testRunStartedId ); } @@ -88,6 +97,7 @@ public String toString() { ", success=" + success + ", timestamp=" + timestamp + ", exception=" + exception + + ", testRunStartedId=" + testRunStartedId + '}'; } } diff --git a/java/src/generated/java/io/cucumber/messages/types/TestRunHookFinished.java b/java/src/generated/java/io/cucumber/messages/types/TestRunHookFinished.java new file mode 100644 index 00000000..3e519319 --- /dev/null +++ b/java/src/generated/java/io/cucumber/messages/types/TestRunHookFinished.java @@ -0,0 +1,74 @@ +package io.cucumber.messages.types; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +import static java.util.Collections.unmodifiableList; +import static java.util.Objects.requireNonNull; + +/** + * Represents the TestRunHookFinished message in Cucumber's message protocol + * @see Github - Cucumber - Messages + */ +// Generated code +@SuppressWarnings("unused") +public final class TestRunHookFinished { + private final String testRunHookStartedId; + private final TestStepResult result; + private final Timestamp timestamp; + + public TestRunHookFinished( + String testRunHookStartedId, + TestStepResult result, + Timestamp timestamp + ) { + this.testRunHookStartedId = requireNonNull(testRunHookStartedId, "TestRunHookFinished.testRunHookStartedId cannot be null"); + this.result = requireNonNull(result, "TestRunHookFinished.result cannot be null"); + this.timestamp = requireNonNull(timestamp, "TestRunHookFinished.timestamp cannot be null"); + } + + /** + * Identifier for the hook execution that has finished + */ + public String getTestRunHookStartedId() { + return testRunHookStartedId; + } + + public TestStepResult getResult() { + return result; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TestRunHookFinished that = (TestRunHookFinished) o; + return + testRunHookStartedId.equals(that.testRunHookStartedId) && + result.equals(that.result) && + timestamp.equals(that.timestamp); + } + + @Override + public int hashCode() { + return Objects.hash( + testRunHookStartedId, + result, + timestamp + ); + } + + @Override + public String toString() { + return "TestRunHookFinished{" + + "testRunHookStartedId=" + testRunHookStartedId + + ", result=" + result + + ", timestamp=" + timestamp + + '}'; + } +} diff --git a/java/src/generated/java/io/cucumber/messages/types/TestRunHookStarted.java b/java/src/generated/java/io/cucumber/messages/types/TestRunHookStarted.java new file mode 100644 index 00000000..97a7295b --- /dev/null +++ b/java/src/generated/java/io/cucumber/messages/types/TestRunHookStarted.java @@ -0,0 +1,90 @@ +package io.cucumber.messages.types; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +import static java.util.Collections.unmodifiableList; +import static java.util.Objects.requireNonNull; + +/** + * Represents the TestRunHookStarted message in Cucumber's message protocol + * @see Github - Cucumber - Messages + */ +// Generated code +@SuppressWarnings("unused") +public final class TestRunHookStarted { + private final String id; + private final String testRunStartedId; + private final String hookId; + private final Timestamp timestamp; + + public TestRunHookStarted( + String id, + String testRunStartedId, + String hookId, + Timestamp timestamp + ) { + this.id = requireNonNull(id, "TestRunHookStarted.id cannot be null"); + this.testRunStartedId = requireNonNull(testRunStartedId, "TestRunHookStarted.testRunStartedId cannot be null"); + this.hookId = requireNonNull(hookId, "TestRunHookStarted.hookId cannot be null"); + this.timestamp = requireNonNull(timestamp, "TestRunHookStarted.timestamp cannot be null"); + } + + /** + * Unique identifier for this hook execution + */ + public String getId() { + return id; + } + + /** + * Identifier for the test run that this hook execution belongs to + */ + public String getTestRunStartedId() { + return testRunStartedId; + } + + /** + * Identifier for the hook that will be executed + */ + public String getHookId() { + return hookId; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TestRunHookStarted that = (TestRunHookStarted) o; + return + id.equals(that.id) && + testRunStartedId.equals(that.testRunStartedId) && + hookId.equals(that.hookId) && + timestamp.equals(that.timestamp); + } + + @Override + public int hashCode() { + return Objects.hash( + id, + testRunStartedId, + hookId, + timestamp + ); + } + + @Override + public String toString() { + return "TestRunHookStarted{" + + "id=" + id + + ", testRunStartedId=" + testRunStartedId + + ", hookId=" + hookId + + ", timestamp=" + timestamp + + '}'; + } +} diff --git a/java/src/generated/java/io/cucumber/messages/types/TestRunStarted.java b/java/src/generated/java/io/cucumber/messages/types/TestRunStarted.java index 94be6c1a..bcf2f3a5 100644 --- a/java/src/generated/java/io/cucumber/messages/types/TestRunStarted.java +++ b/java/src/generated/java/io/cucumber/messages/types/TestRunStarted.java @@ -15,30 +15,39 @@ @SuppressWarnings("unused") public final class TestRunStarted { private final Timestamp timestamp; + private final String id; public TestRunStarted( - Timestamp timestamp + Timestamp timestamp, + String id ) { this.timestamp = requireNonNull(timestamp, "TestRunStarted.timestamp cannot be null"); + this.id = id; } public Timestamp getTimestamp() { return timestamp; } + public Optional getId() { + return Optional.ofNullable(id); + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TestRunStarted that = (TestRunStarted) o; return - timestamp.equals(that.timestamp); + timestamp.equals(that.timestamp) && + Objects.equals(id, that.id); } @Override public int hashCode() { return Objects.hash( - timestamp + timestamp, + id ); } @@ -46,6 +55,7 @@ public int hashCode() { public String toString() { return "TestRunStarted{" + "timestamp=" + timestamp + + ", id=" + id + '}'; } } diff --git a/java/src/test/java/io/cucumber/messages/JacksonTest.java b/java/src/test/java/io/cucumber/messages/JacksonTest.java index d2b86d17..a8fc6f73 100644 --- a/java/src/test/java/io/cucumber/messages/JacksonTest.java +++ b/java/src/test/java/io/cucumber/messages/JacksonTest.java @@ -7,6 +7,8 @@ import io.cucumber.messages.types.Timestamp; import org.junit.jupiter.api.Test; +import java.util.UUID; + import static io.cucumber.messages.Jackson.OBJECT_MAPPER; import static io.cucumber.messages.types.SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -27,7 +29,7 @@ void serialize_enums_using_value() throws JsonProcessingException { @Test void can_deserialize_envelope() throws JsonProcessingException { - Envelope source = Envelope.of(new TestRunStarted(new Timestamp(3L, 14L))); + Envelope source = Envelope.of(new TestRunStarted(new Timestamp(3L, 14L), UUID.randomUUID().toString())); String json = OBJECT_MAPPER.writeValueAsString(source); assertEquals(source, OBJECT_MAPPER.readValue(json, Envelope.class)); } diff --git a/java/src/test/java/io/cucumber/messages/MessagesTest.java b/java/src/test/java/io/cucumber/messages/MessagesTest.java index 840037b9..4d7e3556 100644 --- a/java/src/test/java/io/cucumber/messages/MessagesTest.java +++ b/java/src/test/java/io/cucumber/messages/MessagesTest.java @@ -10,7 +10,7 @@ public class MessagesTest { @Test void is_invalid_when_required_fields_are_missing() { assertThrows(NullPointerException.class, () -> { - new Attachment(null, null, null, null, null, null, null, null); + new Attachment(null, null, null, null, null, null, null, null, null); }, "Attachment.body cannot be null"); } @@ -33,6 +33,8 @@ void is_valid_when_no_required_fields_are_missing() { null, null, null, + null, + null, null ); } diff --git a/java/src/test/java/io/cucumber/messages/NdjsonSerializationTest.java b/java/src/test/java/io/cucumber/messages/NdjsonSerializationTest.java index 1c05a2cc..b9185aa9 100644 --- a/java/src/test/java/io/cucumber/messages/NdjsonSerializationTest.java +++ b/java/src/test/java/io/cucumber/messages/NdjsonSerializationTest.java @@ -4,8 +4,6 @@ import io.cucumber.messages.types.Envelope; import io.cucumber.messages.types.Source; import io.cucumber.messages.types.SourceMediaType; -import io.cucumber.messages.types.TestRunStarted; -import io.cucumber.messages.types.Timestamp; import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; @@ -64,6 +62,8 @@ void does_not_serialize_null_fields() throws IOException { null, null, null, + null, + null, null )); writer.flush(); @@ -94,6 +94,8 @@ void ignores_missing_fields() { null, null, null, + null, + null, null ), envelope); assertFalse(iterator.hasNext()); @@ -124,6 +126,8 @@ void ignores_empty_lines() { null, null, null, + null, + null, null ), envelope); } @@ -143,19 +147,6 @@ void handles_enums() { assertFalse(iterator.hasNext()); } - @Test - void handles_single_argument_constructors() { - InputStream input = new ByteArrayInputStream( - "{\"testRunStarted\": {\"timestamp\":{\"nanos\":0,\"seconds\":0}}}\n".getBytes(UTF_8)); - Iterable incomingMessages = createMessageIterable(input); - Iterator iterator = incomingMessages.iterator(); - assertTrue(iterator.hasNext()); - Envelope testRunStarted = iterator.next(); - Envelope expected = Envelope.of(new TestRunStarted(new Timestamp(0L, 0L))); - assertEquals(expected, testRunStarted); - assertFalse(iterator.hasNext()); - } - @Test void includes_offending_line_in_error_message() { InputStream input = new ByteArrayInputStream("BLA BLA".getBytes(UTF_8)); diff --git a/javascript/src/messages.ts b/javascript/src/messages.ts index ceec6923..86e8abe0 100644 --- a/javascript/src/messages.ts +++ b/javascript/src/messages.ts @@ -19,6 +19,8 @@ export class Attachment { testStepId?: string url?: string + + testRunStartedId?: string } export class Duration { @@ -78,6 +80,12 @@ export class Envelope { @Type(() => TestStepStarted) testStepStarted?: TestStepStarted + @Type(() => TestRunHookStarted) + testRunHookStarted?: TestRunHookStarted + + @Type(() => TestRunHookFinished) + testRunHookFinished?: TestRunHookFinished + @Type(() => UndefinedParameterType) undefinedParameterType?: UndefinedParameterType } @@ -314,6 +322,8 @@ export class Hook { sourceReference: SourceReference = new SourceReference() tagExpression?: string + + type?: HookType } export class Location { @@ -537,6 +547,8 @@ export class TestCase { @Type(() => TestStep) testSteps: readonly TestStep[] = [] + + testRunStartedId?: string } export class Group { @@ -612,12 +624,39 @@ export class TestRunFinished { @Type(() => Exception) exception?: Exception + + testRunStartedId?: string +} + +export class TestRunHookFinished { + + testRunHookStartedId: string = '' + + @Type(() => TestStepResult) + result: TestStepResult = new TestStepResult() + + @Type(() => Timestamp) + timestamp: Timestamp = new Timestamp() +} + +export class TestRunHookStarted { + + id: string = '' + + testRunStartedId: string = '' + + hookId: string = '' + + @Type(() => Timestamp) + timestamp: Timestamp = new Timestamp() } export class TestRunStarted { @Type(() => Timestamp) timestamp: Timestamp = new Timestamp() + + id?: string } export class TestStepFinished { @@ -675,6 +714,15 @@ export enum AttachmentContentEncoding { BASE64 = 'BASE64', } +export enum HookType { + BEFORE_TEST_RUN = 'BEFORE_TEST_RUN', + AFTER_TEST_RUN = 'AFTER_TEST_RUN', + BEFORE_TEST_CASE = 'BEFORE_TEST_CASE', + AFTER_TEST_CASE = 'AFTER_TEST_CASE', + BEFORE_TEST_STEP = 'BEFORE_TEST_STEP', + AFTER_TEST_STEP = 'AFTER_TEST_STEP', +} + export enum PickleStepType { UNKNOWN = 'Unknown', CONTEXT = 'Context', diff --git a/jsonschema/Attachment.json b/jsonschema/Attachment.json index 91de12c9..5a88ac84 100644 --- a/jsonschema/Attachment.json +++ b/jsonschema/Attachment.json @@ -41,6 +41,9 @@ "url": { "description": "*\n A URL where the attachment can be retrieved. This field should not be set by Cucumber.\n It should be set by a program that reads a message stream and does the following for\n each Attachment message:\n\n - Writes the body (after base64 decoding if necessary) to a new file.\n - Sets `body` and `contentEncoding` to `null`\n - Writes out the new attachment message\n\n This will result in a smaller message stream, which can improve performance and\n reduce bandwidth of message consumers. It also makes it easier to process and download attachments\n separately from reports.", "type": "string" + }, + "testRunStartedId": { + "type": "string" } }, "type": "object" diff --git a/jsonschema/Envelope.json b/jsonschema/Envelope.json index e4e37f83..f96bb3bb 100644 --- a/jsonschema/Envelope.json +++ b/jsonschema/Envelope.json @@ -52,6 +52,12 @@ "testStepStarted": { "$ref": "./TestStepStarted.json" }, + "testRunHookStarted": { + "$ref": "TestRunHookStarted.json" + }, + "testRunHookFinished": { + "$ref": "TestRunHookFinished.json" + }, "undefinedParameterType": { "$ref": "./UndefinedParameterType.json" } diff --git a/jsonschema/Hook.json b/jsonschema/Hook.json index 6e64289b..5bbaf9ff 100644 --- a/jsonschema/Hook.json +++ b/jsonschema/Hook.json @@ -18,6 +18,17 @@ }, "tagExpression": { "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "BEFORE_TEST_RUN", + "AFTER_TEST_RUN", + "BEFORE_TEST_CASE", + "AFTER_TEST_CASE", + "BEFORE_TEST_STEP", + "AFTER_TEST_STEP" + ] } }, "type": "object" diff --git a/jsonschema/TestCase.json b/jsonschema/TestCase.json index ed4e8f9b..003d9e95 100644 --- a/jsonschema/TestCase.json +++ b/jsonschema/TestCase.json @@ -116,6 +116,10 @@ "$ref": "#/definitions/TestStep" }, "type": "array" + }, + "testRunStartedId": { + "description": "Identifier for the test run that this test case belongs to", + "type": "string" } }, "type": "object" diff --git a/jsonschema/TestRunFinished.json b/jsonschema/TestRunFinished.json index 51b79a83..817a37dd 100644 --- a/jsonschema/TestRunFinished.json +++ b/jsonschema/TestRunFinished.json @@ -22,6 +22,9 @@ "exception": { "$ref": "./Exception.json", "description": "Any exception thrown during the test run, if any. Does not include exceptions thrown while executing steps." + }, + "testRunStartedId": { + "type": "string" } }, "type": "object" diff --git a/jsonschema/TestRunHookFinished.json b/jsonschema/TestRunHookFinished.json new file mode 100644 index 00000000..a0a85442 --- /dev/null +++ b/jsonschema/TestRunHookFinished.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "TestRunHookFinished.json", + "additionalProperties": false, + "required": [ + "testRunHookStartedId", + "result", + "timestamp" + ], + "properties": { + "testRunHookStartedId": { + "description": "Identifier for the hook execution that has finished", + "type": "string" + }, + "result": { + "$ref": "./TestStepResult.json" + }, + "timestamp": { + "$ref": "./Timestamp.json" + } + }, + "type": "object" +} \ No newline at end of file diff --git a/jsonschema/TestRunHookStarted.json b/jsonschema/TestRunHookStarted.json new file mode 100644 index 00000000..ff149699 --- /dev/null +++ b/jsonschema/TestRunHookStarted.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "TestRunHookStarted.json", + "additionalProperties": false, + "required": [ + "id", + "testRunStartedId", + "hookId", + "timestamp" + ], + "properties": { + "id": { + "description": "Unique identifier for this hook execution", + "type": "string" + }, + "testRunStartedId": { + "description": "Identifier for the test run that this hook execution belongs to", + "type": "string" + }, + "hookId": { + "description": "Identifier for the hook that will be executed", + "type": "string" + }, + "timestamp": { + "$ref": "./Timestamp.json" + } + }, + "type": "object" +} \ No newline at end of file diff --git a/jsonschema/TestRunStarted.json b/jsonschema/TestRunStarted.json index 468a8e85..75358de3 100644 --- a/jsonschema/TestRunStarted.json +++ b/jsonschema/TestRunStarted.json @@ -8,6 +8,9 @@ "properties": { "timestamp": { "$ref": "./Timestamp.json" + }, + "id": { + "type": "string" } }, "type": "object" diff --git a/jsonschema/TestStepFinished.json b/jsonschema/TestStepFinished.json index c8ba99b8..69cca2ef 100644 --- a/jsonschema/TestStepFinished.json +++ b/jsonschema/TestStepFinished.json @@ -2,41 +2,6 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "TestStepFinished.json", "additionalProperties": false, - "definitions": { - "TestStepResult": { - "additionalProperties": false, - "required": [ - "duration", - "status" - ], - "properties": { - "duration": { - "$ref": "./Duration.json" - }, - "message": { - "type": "string", - "description": "An arbitrary bit of information that explains this result. This can be a stack trace of anything else." - }, - "status": { - "enum": [ - "UNKNOWN", - "PASSED", - "SKIPPED", - "PENDING", - "UNDEFINED", - "AMBIGUOUS", - "FAILED" - ], - "type": "string" - }, - "exception": { - "$ref": "./Exception.json", - "description": "Exception thrown while executing this step, if any." - } - }, - "type": "object" - } - }, "required": [ "testCaseStartedId", "testStepId", @@ -51,7 +16,7 @@ "type": "string" }, "testStepResult": { - "$ref": "#/definitions/TestStepResult" + "$ref": "./TestStepResult.json" }, "timestamp": { "$ref": "./Timestamp.json" diff --git a/jsonschema/TestStepResult.json b/jsonschema/TestStepResult.json new file mode 100644 index 00000000..fbbf16fc --- /dev/null +++ b/jsonschema/TestStepResult.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "TestStepResult.json", + "additionalProperties": false, + "required": [ + "duration", + "status" + ], + "properties": { + "duration": { + "$ref": "./Duration.json" + }, + "message": { + "type": "string", + "description": "An arbitrary bit of information that explains this result. This can be a stack trace of anything else." + }, + "status": { + "enum": [ + "UNKNOWN", + "PASSED", + "SKIPPED", + "PENDING", + "UNDEFINED", + "AMBIGUOUS", + "FAILED" + ], + "type": "string" + }, + "exception": { + "$ref": "./Exception.json", + "description": "Exception thrown while executing this step, if any." + } + }, + "type": "object" +} \ No newline at end of file diff --git a/messages.md b/messages.md index 8183c829..a878324c 100644 --- a/messages.md +++ b/messages.md @@ -15,6 +15,7 @@ will only have one of its fields set, which indicates the payload of the message | `testCaseStartedId` | string | no | | | `testStepId` | string | no | | | `url` | string | no | | +| `testRunStartedId` | string | no | | ## Duration @@ -43,6 +44,8 @@ will only have one of its fields set, which indicates the payload of the message | `testRunStarted` | [TestRunStarted](#testrunstarted) | no | | | `testStepFinished` | [TestStepFinished](#teststepfinished) | no | | | `testStepStarted` | [TestStepStarted](#teststepstarted) | no | | +| `testRunHookStarted` | [TestRunHookStarted](#testrunhookstarted) | no | | +| `testRunHookFinished` | [TestRunHookFinished](#testrunhookfinished) | no | | | `undefinedParameterType` | [UndefinedParameterType](#undefinedparametertype) | no | | ## Exception @@ -203,6 +206,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 @@ -381,6 +385,7 @@ will only have one of its fields set, which indicates the payload of the message | `id` | string | yes | | | `pickleId` | string | yes | | | `testSteps` | [TestStep](#teststep)[] | yes | | +| `testRunStartedId` | string | no | | ## Group @@ -439,12 +444,31 @@ will only have one of its fields set, which indicates the payload of the message | `success` | boolean | yes | | | `timestamp` | [Timestamp](#timestamp) | yes | | | `exception` | [Exception](#exception) | no | | +| `testRunStartedId` | string | no | | + +## TestRunHookFinished + +| Field | Type | Required | Description | +| ----- | ---- | ----------- | ----------- | +| `testRunHookStartedId` | string | yes | | +| `result` | [TestStepResult](#teststepresult) | yes | | +| `timestamp` | [Timestamp](#timestamp) | yes | | + +## TestRunHookStarted + +| Field | Type | Required | Description | +| ----- | ---- | ----------- | ----------- | +| `id` | string | yes | | +| `testRunStartedId` | string | yes | | +| `hookId` | string | yes | | +| `timestamp` | [Timestamp](#timestamp) | yes | | ## TestRunStarted | Field | Type | Required | Description | | ----- | ---- | ----------- | ----------- | | `timestamp` | [Timestamp](#timestamp) | yes | | +| `id` | string | no | | ## TestStepFinished @@ -494,6 +518,18 @@ One of the following: * `"BASE64"` +## HookType + +One of the following: + +* `"BEFORE_TEST_RUN"` +* `"AFTER_TEST_RUN"` +* `"BEFORE_TEST_CASE"` +* `"AFTER_TEST_CASE"` +* `"BEFORE_TEST_STEP"` +* `"AFTER_TEST_STEP"` + + ## PickleStepType One of the following: diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 7ed80582..9f76facf 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -86,6 +86,7 @@ my %types = ( test_case_started_id => 'string', test_step_id => 'string', url => 'string', + test_run_started_id => 'string', ); # This is a work-around for the fact that Moo doesn't have introspection @@ -226,6 +227,16 @@ has url => ); +=head4 test_run_started_id + + +=cut + +has test_run_started_id => + (is => 'ro', + ); + + } package Cucumber::Messages::Duration { @@ -334,6 +345,8 @@ my %types = ( test_run_started => 'Cucumber::Messages::TestRunStarted', test_step_finished => 'Cucumber::Messages::TestStepFinished', test_step_started => 'Cucumber::Messages::TestStepStarted', + test_run_hook_started => 'Cucumber::Messages::TestRunHookStarted', + test_run_hook_finished => 'Cucumber::Messages::TestRunHookFinished', undefined_parameter_type => 'Cucumber::Messages::UndefinedParameterType', ); @@ -505,6 +518,26 @@ has test_step_started => ); +=head4 test_run_hook_started + + +=cut + +has test_run_hook_started => + (is => 'ro', + ); + + +=head4 test_run_hook_finished + + +=cut + +has test_run_hook_finished => + (is => 'ro', + ); + + =head4 undefined_parameter_type @@ -1990,6 +2023,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 @@ -2044,6 +2078,45 @@ has tag_expression => ); +=head4 type + + + +Available constants for valid values of this field: + +=over + +=item * TYPE_BEFORE_TEST_RUN + +=item * TYPE_AFTER_TEST_RUN + +=item * TYPE_BEFORE_TEST_CASE + +=item * TYPE_AFTER_TEST_CASE + +=item * TYPE_BEFORE_TEST_STEP + +=item * TYPE_AFTER_TEST_STEP + +=back + +=cut + + +use constant { + TYPE_BEFORE_TEST_RUN => 'BEFORE_TEST_RUN', + TYPE_AFTER_TEST_RUN => 'AFTER_TEST_RUN', + TYPE_BEFORE_TEST_CASE => 'BEFORE_TEST_CASE', + TYPE_AFTER_TEST_CASE => 'AFTER_TEST_CASE', + TYPE_BEFORE_TEST_STEP => 'BEFORE_TEST_STEP', + TYPE_AFTER_TEST_STEP => 'AFTER_TEST_STEP', + }; + +has type => + (is => 'ro', + ); + + } package Cucumber::Messages::Location { @@ -3668,6 +3741,7 @@ my %types = ( id => 'string', pickle_id => 'string', test_steps => '[]Cucumber::Messages::TestStep', + test_run_started_id => 'string', ); # This is a work-around for the fact that Moo doesn't have introspection @@ -3714,6 +3788,16 @@ has test_steps => ); +=head4 test_run_started_id + +Identifier for the test run that this test case belongs to +=cut + +has test_run_started_id => + (is => 'ro', + ); + + } package Cucumber::Messages::Group { @@ -4186,6 +4270,7 @@ my %types = ( success => 'boolean', timestamp => 'Cucumber::Messages::Timestamp', exception => 'Cucumber::Messages::Exception', + test_run_started_id => 'string', ); # This is a work-around for the fact that Moo doesn't have introspection @@ -4240,6 +4325,173 @@ has exception => ); +=head4 test_run_started_id + + +=cut + +has test_run_started_id => + (is => 'ro', + ); + + +} + +package Cucumber::Messages::TestRunHookFinished { + +=head2 Cucumber::Messages::TestRunHookFinished + +=head3 DESCRIPTION + +Represents the TestRunHookFinished message in Cucumber's +L. + + + +=head3 ATTRIBUTES + +=cut + +use Moo; +extends 'Cucumber::Messages::Message'; + +use Scalar::Util qw( blessed ); + +my %types = ( + test_run_hook_started_id => 'string', + result => 'Cucumber::Messages::TestStepResult', + timestamp => 'Cucumber::Messages::Timestamp', +); + +# This is a work-around for the fact that Moo doesn't have introspection +# and Perl doesn't have boolean values... +sub _types { + return \%types; +} + + + +=head4 test_run_hook_started_id + +Identifier for the hook execution that has finished +=cut + +has test_run_hook_started_id => + (is => 'ro', + required => 1, + default => sub { '' }, + ); + + +=head4 result + + +=cut + +has result => + (is => 'ro', + required => 1, + default => sub { Cucumber::Messages::TestStepResult->new() }, + ); + + +=head4 timestamp + + +=cut + +has timestamp => + (is => 'ro', + required => 1, + default => sub { Cucumber::Messages::Timestamp->new() }, + ); + + +} + +package Cucumber::Messages::TestRunHookStarted { + +=head2 Cucumber::Messages::TestRunHookStarted + +=head3 DESCRIPTION + +Represents the TestRunHookStarted message in Cucumber's +L. + + + +=head3 ATTRIBUTES + +=cut + +use Moo; +extends 'Cucumber::Messages::Message'; + +use Scalar::Util qw( blessed ); + +my %types = ( + id => 'string', + test_run_started_id => 'string', + hook_id => 'string', + timestamp => 'Cucumber::Messages::Timestamp', +); + +# This is a work-around for the fact that Moo doesn't have introspection +# and Perl doesn't have boolean values... +sub _types { + return \%types; +} + + + +=head4 id + +Unique identifier for this hook execution +=cut + +has id => + (is => 'ro', + required => 1, + default => sub { '' }, + ); + + +=head4 test_run_started_id + +Identifier for the test run that this hook execution belongs to +=cut + +has test_run_started_id => + (is => 'ro', + required => 1, + default => sub { '' }, + ); + + +=head4 hook_id + +Identifier for the hook that will be executed +=cut + +has hook_id => + (is => 'ro', + required => 1, + default => sub { '' }, + ); + + +=head4 timestamp + + +=cut + +has timestamp => + (is => 'ro', + required => 1, + default => sub { Cucumber::Messages::Timestamp->new() }, + ); + + } package Cucumber::Messages::TestRunStarted { @@ -4264,6 +4516,7 @@ use Scalar::Util qw( blessed ); my %types = ( timestamp => 'Cucumber::Messages::Timestamp', + id => 'string', ); # This is a work-around for the fact that Moo doesn't have introspection @@ -4286,6 +4539,16 @@ has timestamp => ); +=head4 id + + +=cut + +has id => + (is => 'ro', + ); + + } package Cucumber::Messages::TestStepFinished { diff --git a/php/src-generated/Attachment.php b/php/src-generated/Attachment.php index 88c01aa8..7008644d 100644 --- a/php/src-generated/Attachment.php +++ b/php/src-generated/Attachment.php @@ -85,6 +85,7 @@ public function __construct( * separately from reports. */ public readonly ?string $url = null, + public readonly ?string $testRunStartedId = null, ) { } @@ -103,6 +104,7 @@ public static function fromArray(array $arr): self self::ensureTestCaseStartedId($arr); self::ensureTestStepId($arr); self::ensureUrl($arr); + self::ensureTestRunStartedId($arr); return new self( (string) $arr['body'], @@ -113,6 +115,7 @@ public static function fromArray(array $arr): self isset($arr['testCaseStartedId']) ? (string) $arr['testCaseStartedId'] : null, isset($arr['testStepId']) ? (string) $arr['testStepId'] : null, isset($arr['url']) ? (string) $arr['url'] : null, + isset($arr['testRunStartedId']) ? (string) $arr['testRunStartedId'] : null, ); } @@ -204,4 +207,14 @@ private static function ensureUrl(array $arr): void throw new SchemaViolationException('Property \'url\' was array'); } } + + /** + * @psalm-assert array{testRunStartedId?: string|int|bool} $arr + */ + private static function ensureTestRunStartedId(array $arr): void + { + if (array_key_exists('testRunStartedId', $arr) && is_array($arr['testRunStartedId'])) { + throw new SchemaViolationException('Property \'testRunStartedId\' was array'); + } + } } diff --git a/php/src-generated/Envelope.php b/php/src-generated/Envelope.php index 902073be..acf6639c 100644 --- a/php/src-generated/Envelope.php +++ b/php/src-generated/Envelope.php @@ -46,6 +46,8 @@ public function __construct( public readonly ?TestRunStarted $testRunStarted = null, public readonly ?TestStepFinished $testStepFinished = null, public readonly ?TestStepStarted $testStepStarted = null, + public readonly ?TestRunHookStarted $testRunHookStarted = null, + public readonly ?TestRunHookFinished $testRunHookFinished = null, public readonly ?UndefinedParameterType $undefinedParameterType = null, ) { } @@ -73,6 +75,8 @@ public static function fromArray(array $arr): self self::ensureTestRunStarted($arr); self::ensureTestStepFinished($arr); self::ensureTestStepStarted($arr); + self::ensureTestRunHookStarted($arr); + self::ensureTestRunHookFinished($arr); self::ensureUndefinedParameterType($arr); return new self( @@ -92,6 +96,8 @@ public static function fromArray(array $arr): self isset($arr['testRunStarted']) ? TestRunStarted::fromArray($arr['testRunStarted']) : null, isset($arr['testStepFinished']) ? TestStepFinished::fromArray($arr['testStepFinished']) : null, isset($arr['testStepStarted']) ? TestStepStarted::fromArray($arr['testStepStarted']) : null, + isset($arr['testRunHookStarted']) ? TestRunHookStarted::fromArray($arr['testRunHookStarted']) : null, + isset($arr['testRunHookFinished']) ? TestRunHookFinished::fromArray($arr['testRunHookFinished']) : null, isset($arr['undefinedParameterType']) ? UndefinedParameterType::fromArray($arr['undefinedParameterType']) : null, ); } @@ -256,6 +262,26 @@ private static function ensureTestStepStarted(array $arr): void } } + /** + * @psalm-assert array{testRunHookStarted?: array} $arr + */ + private static function ensureTestRunHookStarted(array $arr): void + { + if (array_key_exists('testRunHookStarted', $arr) && !is_array($arr['testRunHookStarted'])) { + throw new SchemaViolationException('Property \'testRunHookStarted\' was not array'); + } + } + + /** + * @psalm-assert array{testRunHookFinished?: array} $arr + */ + private static function ensureTestRunHookFinished(array $arr): void + { + if (array_key_exists('testRunHookFinished', $arr) && !is_array($arr['testRunHookFinished'])) { + throw new SchemaViolationException('Property \'testRunHookFinished\' was not array'); + } + } + /** * @psalm-assert array{undefinedParameterType?: array} $arr */ diff --git a/php/src-generated/Hook.php b/php/src-generated/Hook.php index 5132d4b8..391b879d 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..a3c24493 --- /dev/null +++ b/php/src-generated/Hook/Type.php @@ -0,0 +1,19 @@ + TestStep::fromArray($member), $arr['testSteps'])), + isset($arr['testRunStartedId']) ? (string) $arr['testRunStartedId'] : null, ); } @@ -94,4 +101,14 @@ private static function ensureTestSteps(array $arr): void throw new SchemaViolationException('Property \'testSteps\' was not array'); } } + + /** + * @psalm-assert array{testRunStartedId?: string|int|bool} $arr + */ + private static function ensureTestRunStartedId(array $arr): void + { + if (array_key_exists('testRunStartedId', $arr) && is_array($arr['testRunStartedId'])) { + throw new SchemaViolationException('Property \'testRunStartedId\' was array'); + } + } } diff --git a/php/src-generated/TestRunFinished.php b/php/src-generated/TestRunFinished.php index 2948a43e..d3402b3a 100644 --- a/php/src-generated/TestRunFinished.php +++ b/php/src-generated/TestRunFinished.php @@ -45,6 +45,7 @@ public function __construct( * Any exception thrown during the test run, if any. Does not include exceptions thrown while executing steps. */ public readonly ?Exception $exception = null, + public readonly ?string $testRunStartedId = null, ) { } @@ -59,12 +60,14 @@ public static function fromArray(array $arr): self self::ensureSuccess($arr); self::ensureTimestamp($arr); self::ensureException($arr); + self::ensureTestRunStartedId($arr); return new self( isset($arr['message']) ? (string) $arr['message'] : null, (bool) $arr['success'], Timestamp::fromArray($arr['timestamp']), isset($arr['exception']) ? Exception::fromArray($arr['exception']) : null, + isset($arr['testRunStartedId']) ? (string) $arr['testRunStartedId'] : null, ); } @@ -113,4 +116,14 @@ private static function ensureException(array $arr): void throw new SchemaViolationException('Property \'exception\' was not array'); } } + + /** + * @psalm-assert array{testRunStartedId?: string|int|bool} $arr + */ + private static function ensureTestRunStartedId(array $arr): void + { + if (array_key_exists('testRunStartedId', $arr) && is_array($arr['testRunStartedId'])) { + throw new SchemaViolationException('Property \'testRunStartedId\' was array'); + } + } } diff --git a/php/src-generated/TestRunHookFinished.php b/php/src-generated/TestRunHookFinished.php new file mode 100644 index 00000000..58df204e --- /dev/null +++ b/php/src-generated/TestRunHookFinished.php @@ -0,0 +1,94 @@ + # + ## + def self.from_h(hash) + return nil if hash.nil? + + new( + test_run_hook_started_id: hash[:testRunHookStartedId], + result: TestStepResult.from_h(hash[:result]), + timestamp: Timestamp.from_h(hash[:timestamp]) + ) + end + end + end +end diff --git a/ruby/lib/cucumber/messages/test_run_hook_started.rb b/ruby/lib/cucumber/messages/test_run_hook_started.rb new file mode 100644 index 00000000..e193030d --- /dev/null +++ b/ruby/lib/cucumber/messages/test_run_hook_started.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +# The code was auto-generated by {this script}[https://github.com/cucumber/messages/blob/main/codegen/codegen.rb] +module Cucumber + module Messages + ## + # Represents the TestRunHookStarted message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. + ## + ## + class TestRunHookStarted < Message + ## + # Unique identifier for this hook execution + ## + attr_reader :id + + ## + # Identifier for the test run that this hook execution belongs to + ## + attr_reader :test_run_started_id + + ## + # Identifier for the hook that will be executed + ## + attr_reader :hook_id + + attr_reader :timestamp + + def initialize( + id: '', + test_run_started_id: '', + hook_id: '', + timestamp: Timestamp.new + ) + @id = id + @test_run_started_id = test_run_started_id + @hook_id = hook_id + @timestamp = timestamp + super() + end + + ## + # Returns a new TestRunHookStarted from the given hash. + # If the hash keys are camelCased, they are properly assigned to the + # corresponding snake_cased attributes. + # + # Cucumber::Messages::TestRunHookStarted.from_h(some_hash) # => # + ## + def self.from_h(hash) + return nil if hash.nil? + + new( + id: hash[:id], + test_run_started_id: hash[:testRunStartedId], + hook_id: hash[:hookId], + timestamp: Timestamp.from_h(hash[:timestamp]) + ) + end + end + end +end diff --git a/ruby/lib/cucumber/messages/test_run_started.rb b/ruby/lib/cucumber/messages/test_run_started.rb index e72731ec..bd501f01 100644 --- a/ruby/lib/cucumber/messages/test_run_started.rb +++ b/ruby/lib/cucumber/messages/test_run_started.rb @@ -10,10 +10,14 @@ module Messages class TestRunStarted < Message attr_reader :timestamp + attr_reader :id + def initialize( - timestamp: Timestamp.new + timestamp: Timestamp.new, + id: nil ) @timestamp = timestamp + @id = id super() end @@ -28,7 +32,8 @@ def self.from_h(hash) return nil if hash.nil? new( - timestamp: Timestamp.from_h(hash[:timestamp]) + timestamp: Timestamp.from_h(hash[:timestamp]), + id: hash[:id] ) end end