Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
9 changes: 9 additions & 0 deletions consumer/http_v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ func (i *V4UnconfiguredInteraction) UponReceiving(description string) *V4Unconfi
return i
}

// AddExternalReference records a reference to an external resource (such as a ticket or
// pull request) against the interaction. References appear under
// comments.references[group][name] in the Pact file. May be called multiple times.
func (i *V4UnconfiguredInteraction) AddExternalReference(group, name, value string) *V4UnconfiguredInteraction {
i.interaction.interaction.AddInteractionReference(group, name, value)

return i
}

// WithRequest provides a builder for the expected request
func (i *V4UnconfiguredInteraction) WithCompleteRequest(request Request) *V4InteractionWithCompleteRequest {
i.interaction.WithCompleteRequest(request)
Expand Down
18 changes: 18 additions & 0 deletions consumer/http_v4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ func TestHttpV4TypeSystem(t *testing.T) {

}

func TestV4HTTPAddExternalReference(t *testing.T) {
p, err := NewV4Pact(MockHTTPProviderConfig{
Consumer: "consumer",
Provider: "provider",
})
assert.NoError(t, err)

err = p.AddInteraction().
UponReceiving("a request with an external reference").
AddExternalReference("Jira", "TICKET-123", "https://jira.example.com/browse/TICKET-123").
WithRequest("GET", "/", func(b *V4RequestBuilder) {}).
WillRespondWith(200, func(b *V4ResponseBuilder) {}).
ExecuteTest(t, func(msc MockServerConfig) error {
return nil
})
assert.NoError(t, err)
}

var Like = matchers.Like
var EachLike = matchers.EachLike
var Term = matchers.Term
Expand Down
2 changes: 1 addition & 1 deletion installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@
var packages = map[string]packageInfo{
FFIPackage: {
libName: "libpact_ffi",
version: "0.4.28",
version: "0.5.4",
semverRange: ">= 0.4.0, < 1.0.0",
},
}
Expand Down Expand Up @@ -417,13 +417,13 @@
if err != nil {
return fmt.Errorf("failed to create output file; %w", err)
}
defer f.Close()

Check failure on line 420 in installer/installer.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `f.Close` is not checked (errcheck)

resp, err := http.Get(src)
if err != nil {
return fmt.Errorf("failed http call to %s; %w", src, err)
}
defer resp.Body.Close()

Check failure on line 426 in installer/installer.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `resp.Body.Close` is not checked (errcheck)

archive, err := gzip.NewReader(resp.Body)
if err != nil {
Expand Down Expand Up @@ -523,7 +523,7 @@
if err != nil {
return "", err
}
defer f.Close()

Check failure on line 526 in installer/installer.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `f.Close` is not checked (errcheck)

h := md5.New()
if _, err := io.Copy(h, f); err != nil {
Expand Down
16 changes: 16 additions & 0 deletions internal/native/message_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,19 @@ func (m *MessageServer) WritePactFileForServer(port int, dir string, overwrite b
return fmt.Errorf("an unknown error ocurred when writing to pact file")
}
}

// AddInteractionReference records an external reference (e.g. a ticket or pull request)
// against the interaction. References are stored under comments.references[group][name]
// in the Pact file. This is a V4-only feature.
func (m *Message) AddInteractionReference(group, name, value string) *Message {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot change this and the mock_server.go function to WithReference for consistency with the other APIs, and update usages

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 3a66bff. Renamed AddInteractionReference to WithReference in both internal/native/mock_server.go and internal/native/message_server.go, and updated all callers in consumer/http_v4.go, message/v4/asynchronous_message.go, and message/v4/synchronous_message.go.

cGroup := C.CString(group)
defer free(cGroup)
cName := C.CString(name)
defer free(cName)
cValue := C.CString(value)
defer free(cValue)

C.pactffi_add_interaction_reference(m.handle, cGroup, cName, cValue)

return m
}
16 changes: 16 additions & 0 deletions internal/native/mock_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,22 @@ func (i *Interaction) WithStatus(status int) *Interaction {
return i
}

// AddInteractionReference records an external reference (e.g. a ticket or pull request)
// against the interaction. References are stored under comments.references[group][name]
// in the Pact file. This is a V4-only feature.
func (i *Interaction) AddInteractionReference(group, name, value string) *Interaction {
cGroup := C.CString(group)
defer free(cGroup)
cName := C.CString(name)
defer free(cName)
cValue := C.CString(value)
defer free(cValue)

C.pactffi_add_interaction_reference(i.handle, cGroup, cName, cValue)

return i
}

type stringLike interface {
String() string
}
Expand Down
10 changes: 10 additions & 0 deletions internal/native/pact.h
Original file line number Diff line number Diff line change
Expand Up @@ -4018,6 +4018,16 @@ bool pactffi_set_comment(InteractionHandle interaction, const char *key, const c
*/
bool pactffi_add_text_comment(InteractionHandle interaction, const char *comment);

/**
* Add an external reference to the interaction.
*
* References are stored under `comments.references[group][name]` in the Pact file.
* The group, name and value parameters must be valid UTF-8 null-terminated strings.
*
* Returns false if the reference could not be added (e.g. invalid handle or NULL strings).
*/
bool pactffi_add_interaction_reference(InteractionHandle interaction, const char *group, const char *name, const char *value);

/**
* Get an iterator over all the messages of the Pact. The returned iterator needs to be
* freed with `pactffi_pact_message_iter_delete`.
Expand Down
9 changes: 9 additions & 0 deletions message/v4/asynchronous_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ func (m *AsynchronousMessageBuilder) GivenWithParameter(state models.ProviderSta
return m
}

// AddExternalReference records a reference to an external resource (such as a ticket or
// pull request) against the interaction. References appear under
// comments.references[group][name] in the Pact file. May be called multiple times.
func (m *AsynchronousMessageBuilder) AddExternalReference(group, name, value string) *AsynchronousMessageBuilder {
m.messageHandle.AddInteractionReference(group, name, value)

return m
}

// ExpectsToReceive specifies the content it is expecting to be
// given from the Provider. The function must be able to handle this
// message for the interaction to succeed.
Expand Down
19 changes: 19 additions & 0 deletions message/v4/asynchronous_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ func TestAsyncTypeSystem(t *testing.T) {

}

func TestAsyncAddExternalReference(t *testing.T) {
p, _ := NewAsynchronousPact(Config{
Consumer: "asyncconsumer",
Provider: "asyncprovider",
PactDir: "/tmp/",
})

err := p.AddAsynchronousMessage().
AddExternalReference("GitHub", "PR-456", "https://github.com/org/repo/pull/456").
ExpectsToReceive("a message with an external reference").
WithJSONContent(map[string]string{"event": "user.created"}).
ConsumedBy(func(mc AsynchronousMessage) error {
return nil
}).
Verify(t)

assert.NoError(t, err)
}

// Sync - with plugin, but no transport
// TODO: ExecuteTest has been disabled for now, because it's not very useful
func TestAsyncTypeSystem_CsvPlugin_Matcher(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions message/v4/synchronous_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ type UnconfiguredSynchronousMessageBuilder struct {
pact *SynchronousPact
}

// AddExternalReference records a reference to an external resource (such as a ticket or
// pull request) against the interaction. References appear under
// comments.references[group][name] in the Pact file. May be called multiple times.
func (m *UnconfiguredSynchronousMessageBuilder) AddExternalReference(group, name, value string) *UnconfiguredSynchronousMessageBuilder {
m.messageHandle.AddInteractionReference(group, name, value)

return m
}

// UsingPlugin enables a plugin for use in the current test case
func (m *UnconfiguredSynchronousMessageBuilder) UsingPlugin(config PluginConfig) *SynchronousMessageWithPlugin {
err := m.pact.mockserver.UsingPlugin(config.Plugin, config.Version)
Expand Down
21 changes: 21 additions & 0 deletions message/v4/synchronous_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ func TestSyncTypeSystem_NoPlugin(t *testing.T) {
assert.NoError(t, err)
}

func TestSyncAddExternalReference(t *testing.T) {
p, _ := NewSynchronousPact(Config{
Consumer: "consumer",
Provider: "provider",
})

err := p.AddSynchronousMessage("a sync message with an external reference").
AddExternalReference("Jira", "TICKET-789", "https://jira.example.com/browse/TICKET-789").
WithRequest(func(r *SynchronousMessageWithRequestBuilder) {
r.WithJSONContent(map[string]string{"request": "ping"})
}).
WithResponse(func(r *SynchronousMessageWithResponseBuilder) {
r.WithJSONContent(map[string]string{"response": "pong"})
}).
ExecuteTest(t, func(m SynchronousMessage) error {
return nil
})

assert.NoError(t, err)
}

// Sync - with plugin, but no transport
func TestSyncTypeSystem_CsvPlugin_Matcher(t *testing.T) {
p, _ := NewSynchronousPact(Config{
Expand Down
Loading