Skip to content

Add timestamp to Attachment #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
- Add `Attachment.testRunHookStartedId` for traceability of attachments to test run hooks ([#301](https://github.com/cucumber/messages/pull/301))
- Add `Attachment.timestamp` ([#305](https://github.com/cucumber/messages/pull/305))

### Fixed
- [python] Add a LICENSE file for Python ([#278](https://github.com/cucumber/messages/pull/278))
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# The order is significant - ajv needs referenced schemas to be preceded by referencing schemas
schemas = \
./jsonschema/Source.json \
./jsonschema/Attachment.json \
./jsonschema/Location.json \
./jsonschema/Exception.json \
./jsonschema/SourceReference.json \
Expand All @@ -14,6 +13,7 @@ schemas = \
./jsonschema/StepDefinition.json \
./jsonschema/TestCase.json \
./jsonschema/Timestamp.json \
./jsonschema/Attachment.json \
./jsonschema/TestCaseFinished.json \
./jsonschema/TestCaseStarted.json \
./jsonschema/TestRunFinished.json \
Expand Down
2 changes: 2 additions & 0 deletions cpp/include/messages/cucumber/messages/attachment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <cucumber/messages/attachment_content_encoding.hpp>
#include <cucumber/messages/source.hpp>
#include <cucumber/messages/timestamp.hpp>

namespace cucumber::messages {

Expand Down Expand Up @@ -43,6 +44,7 @@ struct attachment
std::optional<std::string> url;
std::optional<std::string> test_run_started_id;
std::optional<std::string> test_run_hook_started_id;
std::optional<cucumber::messages::timestamp> timestamp;

std::string to_string() const;

Expand Down
2 changes: 2 additions & 0 deletions cpp/src/lib/messages/cucumber/messages/attachment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ attachment::to_string() const
cucumber::messages::to_string(oss, ", url=", url);
cucumber::messages::to_string(oss, ", test_run_started_id=", test_run_started_id);
cucumber::messages::to_string(oss, ", test_run_hook_started_id=", test_run_hook_started_id);
cucumber::messages::to_string(oss, ", timestamp=", timestamp);

return oss.str();
}
Expand All @@ -37,6 +38,7 @@ attachment::to_json(json& j) const
cucumber::messages::to_json(j, camelize("url"), url);
cucumber::messages::to_json(j, camelize("test_run_started_id"), test_run_started_id);
cucumber::messages::to_json(j, camelize("test_run_hook_started_id"), test_run_hook_started_id);
cucumber::messages::to_json(j, camelize("timestamp"), timestamp);
}

std::string
Expand Down
14 changes: 12 additions & 2 deletions dotnet/Cucumber.Messages/generated/Attachment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ public sealed class Attachment
* The identifier of the test run hook execution if the attachment was created during the execution of a test run hook
*/
public string TestRunHookStartedId { get; private set; }
/**
* When the attachment was created
*/
public Timestamp Timestamp { get; private set; }


public Attachment(
Expand All @@ -99,7 +103,8 @@ public Attachment(
string testStepId,
string url,
string testRunStartedId,
string testRunHookStartedId
string testRunHookStartedId,
Timestamp timestamp
)
{
RequireNonNull<string>(body, "Body", "Attachment.Body cannot be null");
Expand All @@ -115,6 +120,7 @@ string testRunHookStartedId
this.Url = url;
this.TestRunStartedId = testRunStartedId;
this.TestRunHookStartedId = testRunHookStartedId;
this.Timestamp = timestamp;
}

public override bool Equals(Object o)
Expand All @@ -132,7 +138,8 @@ public override bool Equals(Object o)
Object.Equals(TestStepId, that.TestStepId) &&
Object.Equals(Url, that.Url) &&
Object.Equals(TestRunStartedId, that.TestRunStartedId) &&
Object.Equals(TestRunHookStartedId, that.TestRunHookStartedId);
Object.Equals(TestRunHookStartedId, that.TestRunHookStartedId) &&
Object.Equals(Timestamp, that.Timestamp);
}

public override int GetHashCode()
Expand All @@ -157,6 +164,8 @@ public override int GetHashCode()
hash = hash * 31 + TestRunStartedId.GetHashCode();
if (TestRunHookStartedId != null)
hash = hash * 31 + TestRunHookStartedId.GetHashCode();
if (Timestamp != null)
hash = hash * 31 + Timestamp.GetHashCode();
return hash;
}

Expand All @@ -173,6 +182,7 @@ public override string ToString()
", url=" + Url +
", testRunStartedId=" + TestRunStartedId +
", testRunHookStartedId=" + TestRunHookStartedId +
", timestamp=" + Timestamp +
'}';
}

Expand Down
1 change: 1 addition & 0 deletions go/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Attachment struct {
Url string `json:"url,omitempty"`
TestRunStartedId string `json:"testRunStartedId,omitempty"`
TestRunHookStartedId string `json:"testRunHookStartedId,omitempty"`
Timestamp *Timestamp `json:"timestamp,omitempty"`
}

type Duration struct {
Expand Down
19 changes: 16 additions & 3 deletions java/src/generated/java/io/cucumber/messages/types/Attachment.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public final class Attachment {
private final String url;
private final String testRunStartedId;
private final String testRunHookStartedId;
private final Timestamp timestamp;

public Attachment(
String body,
Expand All @@ -47,7 +48,8 @@ public Attachment(
String testStepId,
String url,
String testRunStartedId,
String testRunHookStartedId
String testRunHookStartedId,
Timestamp timestamp
) {
this.body = requireNonNull(body, "Attachment.body cannot be null");
this.contentEncoding = requireNonNull(contentEncoding, "Attachment.contentEncoding cannot be null");
Expand All @@ -59,6 +61,7 @@ public Attachment(
this.url = url;
this.testRunStartedId = testRunStartedId;
this.testRunHookStartedId = testRunHookStartedId;
this.timestamp = timestamp;
}

/**
Expand Down Expand Up @@ -150,6 +153,13 @@ public Optional<String> getTestRunHookStartedId() {
return Optional.ofNullable(testRunHookStartedId);
}

/**
* When the attachment was created
*/
public Optional<Timestamp> getTimestamp() {
return Optional.ofNullable(timestamp);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -165,7 +175,8 @@ public boolean equals(Object o) {
Objects.equals(testStepId, that.testStepId) &&
Objects.equals(url, that.url) &&
Objects.equals(testRunStartedId, that.testRunStartedId) &&
Objects.equals(testRunHookStartedId, that.testRunHookStartedId);
Objects.equals(testRunHookStartedId, that.testRunHookStartedId) &&
Objects.equals(timestamp, that.timestamp);
}

@Override
Expand All @@ -180,7 +191,8 @@ public int hashCode() {
testStepId,
url,
testRunStartedId,
testRunHookStartedId
testRunHookStartedId,
timestamp
);
}

Expand All @@ -197,6 +209,7 @@ public String toString() {
", url=" + url +
", testRunStartedId=" + testRunStartedId +
", testRunHookStartedId=" + testRunHookStartedId +
", timestamp=" + timestamp +
'}';
}
}
2 changes: 1 addition & 1 deletion java/src/test/java/io/cucumber/messages/MessagesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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, null, null);
new Attachment(null, null, null, null, null, null, null, null, null, null, null);
}, "Attachment.body cannot be null");
}

Expand Down
3 changes: 3 additions & 0 deletions javascript/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export class Attachment {
testRunStartedId?: string

testRunHookStartedId?: string

@Type(() => Timestamp)
timestamp?: Timestamp
}

export class Duration {
Expand Down
4 changes: 4 additions & 0 deletions jsonschema/Attachment.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
"testRunHookStartedId": {
"description": "The identifier of the test run hook execution if the attachment was created during the execution of a test run hook",
"type": "string"
},
"timestamp": {
"description": "When the attachment was created",
"$ref": "./Timestamp.json"
}
},
"type": "object"
Expand Down
1 change: 1 addition & 0 deletions messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ will only have one of its fields set, which indicates the payload of the message
| `url` | string | no | |
| `testRunStartedId` | string | no | |
| `testRunHookStartedId` | string | no | |
| `timestamp` | [Timestamp](#timestamp) | no | |

## Duration

Expand Down
11 changes: 11 additions & 0 deletions perl/lib/Cucumber/Messages.pm
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ my %types = (
url => 'string',
test_run_started_id => 'string',
test_run_hook_started_id => 'string',
timestamp => 'Cucumber::Messages::Timestamp',
);

# This is a work-around for the fact that Moo doesn't have introspection
Expand Down Expand Up @@ -248,6 +249,16 @@ has test_run_hook_started_id =>
);


=head4 timestamp

When the attachment was created
=cut

has timestamp =>
(is => 'ro',
);


}

package Cucumber::Messages::Duration {
Expand Down
17 changes: 17 additions & 0 deletions php/src-generated/Attachment.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ public function __construct(
* The identifier of the test run hook execution if the attachment was created during the execution of a test run hook
*/
public readonly ?string $testRunHookStartedId = null,

/**
* When the attachment was created
*/
public readonly ?Timestamp $timestamp = null,
) {
}

Expand All @@ -123,6 +128,7 @@ public static function fromArray(array $arr): self
self::ensureUrl($arr);
self::ensureTestRunStartedId($arr);
self::ensureTestRunHookStartedId($arr);
self::ensureTimestamp($arr);

return new self(
(string) $arr['body'],
Expand All @@ -135,6 +141,7 @@ public static function fromArray(array $arr): self
isset($arr['url']) ? (string) $arr['url'] : null,
isset($arr['testRunStartedId']) ? (string) $arr['testRunStartedId'] : null,
isset($arr['testRunHookStartedId']) ? (string) $arr['testRunHookStartedId'] : null,
isset($arr['timestamp']) ? Timestamp::fromArray($arr['timestamp']) : null,
);
}

Expand Down Expand Up @@ -246,4 +253,14 @@ private static function ensureTestRunHookStartedId(array $arr): void
throw new SchemaViolationException('Property \'testRunHookStartedId\' was array');
}
}

/**
* @psalm-assert array{timestamp?: array} $arr
*/
private static function ensureTimestamp(array $arr): void
{
if (array_key_exists('timestamp', $arr) && !is_array($arr['timestamp'])) {
throw new SchemaViolationException('Property \'timestamp\' was not array');
}
}
}
1 change: 1 addition & 0 deletions python/src/cucumber_messages/_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Attachment:
test_run_hook_started_id: Optional[str] = None # The identifier of the test run hook execution if the attachment was created during the execution of a test run hook
test_run_started_id: Optional[str] = None # Not used; implementers should instead populate `testRunHookStartedId` if an attachment was created during the execution of a test run hook
test_step_id: Optional[str] = None # The identifier of the test step if the attachment was created during the execution of a test step
timestamp: Optional[Timestamp] = None # When the attachment was created
url: Optional[str] = None
"""
*
Expand Down
12 changes: 10 additions & 2 deletions ruby/lib/cucumber/messages/attachment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ class Attachment < Message
##
attr_reader :test_run_hook_started_id

##
# When the attachment was created
##
attr_reader :timestamp

def initialize(
body: '',
content_encoding: AttachmentContentEncoding::IDENTITY,
Expand All @@ -105,7 +110,8 @@ def initialize(
test_step_id: nil,
url: nil,
test_run_started_id: nil,
test_run_hook_started_id: nil
test_run_hook_started_id: nil,
timestamp: nil
)
@body = body
@content_encoding = content_encoding
Expand All @@ -117,6 +123,7 @@ def initialize(
@url = url
@test_run_started_id = test_run_started_id
@test_run_hook_started_id = test_run_hook_started_id
@timestamp = timestamp
super()
end

Expand All @@ -140,7 +147,8 @@ def self.from_h(hash)
test_step_id: hash[:testStepId],
url: hash[:url],
test_run_started_id: hash[:testRunStartedId],
test_run_hook_started_id: hash[:testRunHookStartedId]
test_run_hook_started_id: hash[:testRunHookStartedId],
timestamp: Timestamp.from_h(hash[:timestamp])
)
end
end
Expand Down
Loading