diff --git a/CHANGELOG.md b/CHANGELOG.md index b9adf365..ebc0bbc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,18 @@ The format is based on [Keep a Changelog], and this project adheres to [keep a changelog]: https://keepachangelog.com/en/1.0.0/ [semantic versioning]: https://semver.org/spec/v2.0.0.html +## [0.15.4] - 2024-08-16 + +### Added + +- Added `ToExecuteCommandType[T]()` and `ToRecordEventType[T]()` expectations. + +### Deprecated + +- Marked `ToExecuteCommandOfType()` and `ToRecordEventOfType()` as deprecated. + These functions will be removed in a future release; use the new generic + versions instead. + ## [0.15.3] - 2024-08-16 ### Changed @@ -402,6 +414,7 @@ guide][0.11.0 migration guide] for detailed instructions. [0.15.1]: https://github.com/dogmatiq/testkit/releases/tag/v0.15.1 [0.15.2]: https://github.com/dogmatiq/testkit/releases/tag/v0.15.2 [0.15.3]: https://github.com/dogmatiq/testkit/releases/tag/v0.15.3 +[0.15.4]: https://github.com/dogmatiq/testkit/releases/tag/v0.15.4 diff --git a/expectation.message.event_test.go b/expectation.message.event_test.go index 808e77d5..976e488a 100644 --- a/expectation.message.event_test.go +++ b/expectation.message.event_test.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = g.Describe("func ToExecuteCommandOfType()", func() { +var _ = g.Describe("func ToExecuteCommandType()", func() { var ( testingT *testingmock.T app dogma.Application diff --git a/expectation.messagetype.command_test.go b/expectation.messagetype.command_test.go index d9ba977e..4b47a428 100644 --- a/expectation.messagetype.command_test.go +++ b/expectation.messagetype.command_test.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = g.Describe("func ToExecuteCommandOfType()", func() { +var _ = g.Describe("func ToExecuteCommandType()", func() { var ( testingT *testingmock.T app dogma.Application @@ -97,7 +97,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "command type executed as expected", RecordEvent(MessageE1), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectPass, expectReport( `✓ execute any 'fixtures.MessageC' command`, @@ -106,7 +106,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no matching command types executed", RecordEvent(MessageE1), - ToExecuteCommandOfType(MessageX{}), + ToExecuteCommandType[MessageX](), expectFail, expectReport( `✗ execute any 'fixtures.MessageX' command`, @@ -121,7 +121,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no messages produced at all", RecordEvent(MessageN1), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectFail, expectReport( `✗ execute any 'fixtures.MessageC' command`, @@ -136,7 +136,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no commands produced at all", ExecuteCommand(MessageR1), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectFail, expectReport( `✗ execute any 'fixtures.MessageC' command`, @@ -151,7 +151,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no matching command type executed and all relevant handler types disabled", RecordEvent(MessageN1), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectFail, expectReport( `✗ execute any 'fixtures.MessageC' command`, @@ -169,7 +169,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "command of a similar type executed", RecordEvent(MessageE1), - ToExecuteCommandOfType(&MessageC{}), // note: message type is pointer + ToExecuteCommandType[*MessageC](), // note: message type is pointer expectFail, expectReport( `✗ execute any '*fixtures.MessageC' command`, @@ -188,8 +188,8 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { "does not include an explanation when negated and a sibling expectation passes", RecordEvent(MessageE1), NoneOf( - ToExecuteCommandOfType(MessageC{}), - ToExecuteCommandOfType(MessageX{}), + ToExecuteCommandType[MessageC](), + ToExecuteCommandType[MessageX](), ), expectFail, expectReport( @@ -204,7 +204,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToExecuteCommandOfType(MessageU{}), + ToExecuteCommandType[MessageU](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -217,7 +217,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToExecuteCommandOfType(MessageE{}), + ToExecuteCommandType[MessageE](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -230,7 +230,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToExecuteCommandOfType(MessageR{}), + ToExecuteCommandType[MessageR](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -238,10 +238,4 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { "no handlers execute commands of type fixtures.MessageR, it is only ever consumed", )) }) - - g.It("panics if the message is nil", func() { - Expect(func() { - ToExecuteCommandOfType(nil) - }).To(PanicWith("ToExecuteCommandOfType(): message must not be nil")) - }) }) diff --git a/expectation.messagetype.commandcall_test.go b/expectation.messagetype.commandcall_test.go index dfeefdc0..c7215a74 100644 --- a/expectation.messagetype.commandcall_test.go +++ b/expectation.messagetype.commandcall_test.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = g.Describe("func ToExecuteCommandOfType() (when used with the Call() action)", func() { +var _ = g.Describe("func ToExecuteCommandType() (when used with the Call() action)", func() { var ( testingT *testingmock.T app dogma.Application @@ -105,7 +105,7 @@ var _ = g.Describe("func ToExecuteCommandOfType() (when used with the Call() act g.Entry( "command type executed as expected", executeCommandViaExecutor(MessageR1), - ToExecuteCommandOfType(MessageR{}), + ToExecuteCommandType[MessageR](), expectPass, expectReport( `✓ execute any 'fixtures.MessageR' command`, @@ -114,7 +114,7 @@ var _ = g.Describe("func ToExecuteCommandOfType() (when used with the Call() act g.Entry( "no messages produced at all", Call(func() {}), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectFail, expectReport( `✗ execute any 'fixtures.MessageC' command`, @@ -129,7 +129,7 @@ var _ = g.Describe("func ToExecuteCommandOfType() (when used with the Call() act g.Entry( "no matching command type executed and all relevant handler types disabled", executeCommandViaExecutor(MessageR1), - ToExecuteCommandOfType(MessageC{}), + ToExecuteCommandType[MessageC](), expectFail, expectReport( `✗ execute any 'fixtures.MessageC' command`, @@ -148,7 +148,7 @@ var _ = g.Describe("func ToExecuteCommandOfType() (when used with the Call() act g.Entry( "command of a similar type executed", executeCommandViaExecutor(MessageR1), - ToExecuteCommandOfType(&MessageR{}), // note: message type is pointer + ToExecuteCommandType[*MessageR](), // note: message type is pointer expectFail, expectReport( `✗ execute any '*fixtures.MessageR' command`, diff --git a/expectation.messagetype.event_test.go b/expectation.messagetype.event_test.go index fbea289d..8e52c7b9 100644 --- a/expectation.messagetype.event_test.go +++ b/expectation.messagetype.event_test.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = g.Describe("func ToExecuteCommandOfType()", func() { +var _ = g.Describe("func ToRecordEventType()", func() { var ( testingT *testingmock.T app dogma.Application @@ -100,7 +100,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "event type recorded as expected", ExecuteCommand(MessageR1), - ToRecordEventOfType(MessageE{}), + ToRecordEventType[MessageE](), expectPass, expectReport( `✓ record any 'fixtures.MessageE' event`, @@ -109,7 +109,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no matching event type recorded", ExecuteCommand(MessageR1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -125,7 +125,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no matching event type recorded and all relevant handler types disabled", ExecuteCommand(MessageR1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -145,7 +145,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no matching event type recorded and no relevant handler types engaged", ExecuteCommand(MessageR1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -165,7 +165,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no messages produced at all", ExecuteCommand(MessageN1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -181,7 +181,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "no events recorded at all", RecordEvent(MessageE1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -197,7 +197,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { g.Entry( "event of a similar type recorded", ExecuteCommand(MessageR1), - ToRecordEventOfType(&MessageE{}), // note: message type is pointer + ToRecordEventType[*MessageE](), // note: message type is pointer expectFail, expectReport( `✗ record any '*fixtures.MessageE' event`, @@ -216,8 +216,8 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { "does not include an explanation when negated and a sibling expectation passes", ExecuteCommand(MessageR1), NoneOf( - ToRecordEventOfType(MessageE{}), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageE](), + ToRecordEventType[MessageX](), ), expectFail, expectReport( @@ -232,7 +232,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToRecordEventOfType(MessageU{}), + ToRecordEventType[MessageU](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -245,7 +245,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToRecordEventOfType(MessageR{}), + ToRecordEventType[MessageR](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -258,7 +258,7 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { test := Begin(testingT, app) test.Expect( noop, - ToRecordEventOfType(MessageO{}), + ToRecordEventType[MessageO](), ) Expect(testingT.Failed()).To(BeTrue()) @@ -266,10 +266,4 @@ var _ = g.Describe("func ToExecuteCommandOfType()", func() { "no handlers record events of type fixtures.MessageO, it is only ever consumed", )) }) - - g.It("panics if the message is nil", func() { - Expect(func() { - ToRecordEventOfType(nil) - }).To(PanicWith("ToRecordEventOfType(): message must not be nil")) - }) }) diff --git a/expectation.messagetype.eventcall_test.go b/expectation.messagetype.eventcall_test.go index b9ed0843..256595c8 100644 --- a/expectation.messagetype.eventcall_test.go +++ b/expectation.messagetype.eventcall_test.go @@ -11,7 +11,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = g.Describe("func ToRecordEventOfType() (when used with the Call() action)", func() { +var _ = g.Describe("func ToRecordEventType() (when used with the Call() action)", func() { var ( testingT *testingmock.T app dogma.Application @@ -107,7 +107,7 @@ var _ = g.Describe("func ToRecordEventOfType() (when used with the Call() action g.Entry( "no matching event types recorded", executeCommandViaExecutor(MessageR1), - ToRecordEventOfType(MessageX{}), + ToRecordEventType[MessageX](), expectFail, expectReport( `✗ record any 'fixtures.MessageX' event`, @@ -124,7 +124,7 @@ var _ = g.Describe("func ToRecordEventOfType() (when used with the Call() action g.Entry( "no messages produced at all", Call(func() {}), - ToRecordEventOfType(MessageE{}), + ToRecordEventType[MessageE](), expectFail, expectReport( `✗ record any 'fixtures.MessageE' event`, @@ -139,7 +139,7 @@ var _ = g.Describe("func ToRecordEventOfType() (when used with the Call() action g.Entry( "no events produced at all", executeCommandViaExecutor(MessageN1), - ToRecordEventOfType(MessageE{}), + ToRecordEventType[MessageE](), expectFail, expectReport( `✗ record any 'fixtures.MessageE' event`, diff --git a/expectation.messagetype.go b/expectation.messagetype.go index 7bc243b1..df3a0d9d 100644 --- a/expectation.messagetype.go +++ b/expectation.messagetype.go @@ -10,8 +10,19 @@ import ( "github.com/dogmatiq/testkit/internal/typecmp" ) +// ToExecuteCommandType returns an expectation that passes if a command of type +// T is executed. +func ToExecuteCommandType[T dogma.Command]() Expectation { + return &messageTypeExpectation{ + expectedType: message.TypeFor[T](), + expectedRole: message.CommandRole, + } +} + // ToExecuteCommandOfType returns an expectation that passes if a command of the // same type as m is executed. +// +// Deprecated: Use [ToExecuteCommandType] instead. func ToExecuteCommandOfType(m dogma.Command) Expectation { if m == nil { panic("ToExecuteCommandOfType(): message must not be nil") @@ -23,8 +34,19 @@ func ToExecuteCommandOfType(m dogma.Command) Expectation { } } +// ToRecordEventType returns an expectation that passes if an event of type T is +// recorded. +func ToRecordEventType[T dogma.Event]() Expectation { + return &messageTypeExpectation{ + expectedType: message.TypeFor[T](), + expectedRole: message.EventRole, + } +} + // ToRecordEventOfType returns an expectation that passes if an event of the // same type as m is recorded. +// +// Deprecated: Use [ToRecordEventType] instead. func ToRecordEventOfType(m dogma.Command) Expectation { if m == nil { panic("ToRecordEventOfType(): message must not be nil") diff --git a/go.mod b/go.mod index bc1914ec..3dd19de2 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,11 @@ module github.com/dogmatiq/testkit -go 1.21 +go 1.22 + +toolchain go1.22.3 require ( - github.com/dogmatiq/configkit v0.13.3 + github.com/dogmatiq/configkit v0.13.4 github.com/dogmatiq/cosyne v0.2.0 github.com/dogmatiq/dapper v0.5.3 github.com/dogmatiq/dogma v0.13.1 diff --git a/go.sum b/go.sum index 15c80852..8fb14654 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dogmatiq/configkit v0.13.3 h1:2SW2jBuYZ9PWsjjBhv7pd7OLhuBJ+jcYX3PmEbBDd9U= -github.com/dogmatiq/configkit v0.13.3/go.mod h1:qd+QnJSig1NPuBpPuEFKYL1RXH88+XODRT5tz2g1314= +github.com/dogmatiq/configkit v0.13.4 h1:5hfWDMV5fmG1hf1VZFCFicdiLhP7QxW5+O9FNMnkml4= +github.com/dogmatiq/configkit v0.13.4/go.mod h1:lwCG/to/1ZEJJXGyxCxqQvg7HIb8dDrQv4Xc40K32Dw= github.com/dogmatiq/cosyne v0.2.0 h1:tO957BpS4I9kqSw31ds6Ef4CXvV8zPAqWzbXKElsGWg= github.com/dogmatiq/cosyne v0.2.0/go.mod h1:dD8EZjbRX7FFw9t6P7l1nwoZbA7YxtOCfl9ZZAHPucU= github.com/dogmatiq/dapper v0.5.3 h1:DZkitO0TiokaiZt+9J7UNnagW2ezSYmJUlDTXLWGf8g=