cmdx-rspec 0.2.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5b50ce1284ba0cbca3e8b27f7d69c1eef31d4e11615e30f0d3e2952c640a725
4
- data.tar.gz: 1a22773141cdc0a4ce6e1715b35215dd4c36f44c62b7a79ca79d70d803a55904
3
+ metadata.gz: 6d7e467dfe5e14a9de4e6e0b2f0dc11103b2f7da3950520cd94ffed429b0eef6
4
+ data.tar.gz: 0b6af1c86e14a62c8d3a4244576b5805c667788b81e276ca3e89ab03e9f293a9
5
5
  SHA512:
6
- metadata.gz: 1362711e07183750d989d874e9bf5d5048b0130f213bc6acccb99af45021c5ec814dea6439f6639ec14f0730e0664ede073ee5b5b4861d89bfa512274af1c7c6
7
- data.tar.gz: 2fa8252b7217e3e9ae4acf0542b430aafc2ba7623f4839a3d6d544afa5da7e4f5ffdf95931fc3d15cb6216512f4d46f535668219342231e2cf4e1d98ca8268db
6
+ metadata.gz: 338465ba22c6e888adbf36f973fc56479ec58b8fb2bb3635f3c028fa02783e90fbb408d68d4399a0cb9515e7ad6bbbd6e7e1da549af2ac7258abdf87c4208b31
7
+ data.tar.gz: dd456ab9cb4c907272fc8813e93d18cae68d85f09e2a2f7cc8e019a156d7911a7f99e7a267215d98cec4b0800248d4294ddf5471e1df1832fbb7629875eb38e3
@@ -11,7 +11,7 @@ Reference the guides outlined in https://guides.rubygems.org
11
11
 
12
12
  ## Project Context
13
13
  CMDx::RSpec is a collection of RSpec matchers for the CMDx framework.
14
- Reference the CMDx documentation in https://github.com/drexed/cmdx/blob/main/LLM.md
14
+ Reference the CMDx documentation in https://drexed.github.io/cmdx/llms.txt
15
15
  Reference the CMDx::RSpec documentation in https://github.com/drexed/cmdx-rspec/blob/main/README.md
16
16
 
17
17
  ## Technology Stack
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
1
7
  ## [Unreleased]
2
8
 
9
+ ## [1.1.0] - 2025-11-08
10
+
11
+ ### Added
12
+ - Added unstub helpers
13
+
14
+ ## [1.0.0] - 2025-11-08
15
+
16
+ ### Added
17
+ - Added mock and stub helpers
18
+
19
+ ### Changed
20
+ - Renamed `have_been_success` to `be_successful`
21
+ - Renamed `have_been_failure` to `have_failed`
22
+ - Renamed `have_been_skipped` to `have_skipped`
23
+ - Moved matchers to be within the `lib/rspec/matchers` directory
24
+
3
25
  ## [0.2.0] - 2025-09-13
4
26
 
5
27
  ### Added
data/README.md CHANGED
@@ -1,12 +1,17 @@
1
- <p align="center">
2
- <img src="./src/cmdx-rspec-logo.png" width="200" alt="CMDx::RSpec Logo">
3
- </p>
1
+ <div align="center">
2
+ <img src="./src/cmdx-light-logo.png#gh-light-mode-only" width="200" alt="CMDx Logo">
3
+ <img src="./src/cmdx-dark-logo.png#gh-dark-mode-only" width="200" alt="CMDx Logo">
4
+
5
+ ---
6
+
7
+ Collection of RSpec matchers for the CMDx framework.
8
+
9
+ [Changelog](./CHANGELOG.md) · [Report Bug](https://github.com/drexed/cmdx-rspec/issues) · [Request Feature](https://github.com/drexed/cmdx-rspec/issues)
4
10
 
5
- <p align="center">
6
11
  <img alt="Version" src="https://img.shields.io/gem/v/cmdx-rspec">
7
12
  <img alt="Build" src="https://github.com/drexed/cmdx-rspec/actions/workflows/ci.yml/badge.svg">
8
13
  <img alt="License" src="https://img.shields.io/github/license/drexed/cmdx-rspec">
9
- </p>
14
+ </div>
10
15
 
11
16
  # CMDx::RSpec
12
17
 
@@ -28,9 +33,9 @@ Or install it yourself as:
28
33
 
29
34
  $ gem install cmdx-rspec
30
35
 
31
- ## Usage
36
+ ## Matchers
32
37
 
33
- ### have_been_success
38
+ ### be_successful
34
39
 
35
40
  Asserts that a CMDx task result indicates successful execution.
36
41
 
@@ -38,11 +43,11 @@ Asserts that a CMDx task result indicates successful execution.
38
43
  it "returns success" do
39
44
  result = SomeTask.execute
40
45
 
41
- expect(result).to have_been_success
46
+ expect(result).to be_successful
42
47
  end
43
48
  ```
44
49
 
45
- ### have_been_skipped
50
+ ### have_skipped
46
51
 
47
52
  Asserts that a CMDx task result indicates the task was skipped during execution.
48
53
 
@@ -50,11 +55,19 @@ Asserts that a CMDx task result indicates the task was skipped during execution.
50
55
  it "returns skipped" do
51
56
  result = SomeTask.execute
52
57
 
53
- expect(result).to have_been_skipped
58
+ # Default result
59
+ expect(result).to have_skipped
60
+
61
+ # Custom result
62
+ expect(result).to have_skipped(
63
+ reason: "Skipping for a custom reason",
64
+ cause: be_a(CMDx::SkipFault)
65
+ # Other members of `result.to_h`...
66
+ )
54
67
  end
55
68
  ```
56
69
 
57
- ### have_been_failure
70
+ ### have_failed
58
71
 
59
72
  Asserts that a CMDx task result indicates execution failure.
60
73
 
@@ -62,7 +75,15 @@ Asserts that a CMDx task result indicates execution failure.
62
75
  it "returns failure" do
63
76
  result = SomeTask.execute
64
77
 
65
- expect(result).to have_been_failure
78
+ # Default result
79
+ expect(result).to have_failed
80
+
81
+ # Custom result
82
+ expect(result).to have_failed(
83
+ reason: "Failed for a custom reason",
84
+ cause: be_a(NoMethodError)
85
+ # Other members of `result.to_h`...
86
+ )
66
87
  end
67
88
  ```
68
89
 
@@ -120,9 +141,125 @@ Asserts that a CMDx task result indicates the task is deprecated.
120
141
 
121
142
  ```ruby
122
143
  it "returns deprecated" do
123
- result = SomeTask.execute
144
+ expect(SomeTask).to be_deprecated
145
+ end
146
+ ```
147
+
148
+ ## Helpers
149
+
150
+ ### Including Helper Modules
151
+
152
+ Include the helper modules in your RSpec configuration or example groups:
153
+
154
+ ```ruby
155
+ RSpec.configure do |config|
156
+ config.include CMDx::RSpec::Helpers
157
+ end
158
+ ```
159
+
160
+ Or include them in specific example groups:
161
+
162
+ ```ruby
163
+ describe MyFeature do
164
+ include CMDx::RSpec::Helpers
165
+
166
+ # Your specs...
167
+ end
168
+ ```
169
+
170
+ ### Stubs
171
+
172
+ Helper methods for stubbing CMDx command execution.
173
+
174
+ #### Types
175
+
176
+ ```ruby
177
+ it "stubs task executions by type" do
178
+ # eg: SomeTask.execute
179
+ stub_task_success(SomeTask)
180
+ stub_task_skip(SomeTask)
181
+ stub_task_fail(SomeTask)
182
+
183
+ # eg: SomeTask.execute!
184
+ stub_task_success!(SomeTask)
185
+ stub_task_skip!(SomeTask)
186
+ stub_task_fail!(SomeTask)
187
+
188
+ # Your specs...
189
+ end
190
+
191
+ it "stubs task with arguments" do
192
+ # eg: SomeTask.execute(some: "value")
193
+ stub_task_success(SomeTask, some: "value")
194
+
195
+ # eg: SomeTask.execute!(some: "value")
196
+ stub_task_skip!(SomeTask, some: "value")
197
+
198
+ # Your specs...
199
+ end
200
+ ```
201
+
202
+ #### Options
203
+
204
+ ```ruby
205
+ it "stubs task with metadata" do
206
+ stub_task_success(SomeTask, metadata: { some: "value" })
207
+
208
+ # Your specs...
209
+ end
210
+
211
+ it "stubs task with a custom reason" do
212
+ stub_task_skip!(SomeTask, reason: "Skipping for a custom reason")
213
+
214
+ # Your specs...
215
+ end
216
+
217
+ it "stubs task with a custom cause" do
218
+ stub_task_fail!(SomeTask, cause: NoMethodError.new("just blow it up"))
219
+
220
+ # Your specs...
221
+ end
222
+ ```
223
+
224
+ #### Reset
225
+
226
+ ```ruby
227
+ it "unstubs task executions by type" do
228
+ # eg: SomeTask.execute
229
+ unstub_task(SomeTask)
230
+
231
+ # eg: SomeTask.execute!
232
+ unstub_task!(SomeTask)
233
+
234
+ # Your specs...
235
+ end
236
+ ```
237
+
238
+ ### Mocks
239
+
240
+ Helper methods for setting expectations on CMDx command execution.
241
+
242
+ #### Types
243
+
244
+ ```ruby
245
+ it "mocks task executions by type" do
246
+ # eg: SomeTask.execute
247
+ expect_task_execution(SomeTask)
248
+
249
+ # eg: SomeTask.execute!
250
+ expect_task_execution!(BangCommand)
251
+
252
+ # Your specs...
253
+ end
254
+
255
+ it "mocks task with arguments" do
256
+ # eg: SomeTask.execute(some: "value")
257
+ expect_task_execution(SomeTask, some: "value")
258
+
259
+ # eg: SomeTask.execute!(some: "value")
260
+ expect_task_execution!(SomeTask, some: "value")
124
261
 
125
- expect(result).to be_deprecated
262
+ # Your specs...
126
263
  end
127
264
  ```
128
265
 
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CMDx
4
+ module RSpec
5
+ # Helper methods for setting up RSpec stubs and expectations on CMDx command execution.
6
+ module Helpers
7
+
8
+ # Sets up a stub that allows a command to receive :execute and return a successful result.
9
+ #
10
+ # @param command [Class] The command class to stub execution on
11
+ # @param metadata [Hash] Optional metadata to pass to the result
12
+ # @param context [Hash] Optional keyword arguments to pass to the command
13
+ #
14
+ # @return [CMDx::Result] The successful result object
15
+ #
16
+ # @example Stubbing successful execution with context
17
+ # stub_task_success(MyCommand, user_id: 123, role: "admin")
18
+ #
19
+ # result = MyCommand.execute(user_id: 123, role: "admin")
20
+ # expect(result).to be_successful
21
+ #
22
+ # @example Stubbing successful execution without context
23
+ # stub_task_success(MyCommand)
24
+ #
25
+ # result = MyCommand.execute
26
+ # expect(result).to be_successful
27
+ def stub_task_success(command, metadata: {}, **context)
28
+ task = command.new(context)
29
+ result = task.result
30
+
31
+ result.metadata.merge!(metadata)
32
+ result.executing!
33
+ result.executed!
34
+
35
+ allow(command).to receive(:execute).and_return(result)
36
+
37
+ result
38
+ end
39
+
40
+ # Sets up a stub that allows a command to receive :execute! and return a successful result.
41
+ #
42
+ # @param command [Class] The command class to stub execution on
43
+ # @param metadata [Hash] Optional metadata to pass to the result
44
+ # @param context [Hash] Optional keyword arguments to pass to the command
45
+ #
46
+ # @return [CMDx::Result] The successful result object
47
+ #
48
+ # @example Stubbing successful execution with context
49
+ # stub_task_success!(MyCommand, user_id: 123, role: "admin")
50
+ #
51
+ # result = MyCommand.execute!(user_id: 123, role: "admin")
52
+ # expect(result).to be_successful
53
+ #
54
+ # @example Stubbing successful execution without context
55
+ # stub_task_success!(MyCommand)
56
+ #
57
+ # result = MyCommand.execute!
58
+ # expect(result).to be_successful
59
+ def stub_task_success!(command, metadata: {}, **context)
60
+ task = command.new(context)
61
+ result = task.result
62
+
63
+ result.metadata.merge!(metadata)
64
+ result.executing!
65
+ result.executed!
66
+
67
+ allow(command).to receive(:execute!).and_return(result)
68
+
69
+ result
70
+ end
71
+
72
+ # Sets up a stub that allows a command to receive :execute and return a skipped result.
73
+ #
74
+ # @param command [Class] The command class to stub execution on
75
+ # @param reason [String, nil] Optional reason for skipping
76
+ # @param cause [CMDx::Fault, nil] Optional cause for skipping
77
+ # @param metadata [Hash] Optional metadata to pass to the result
78
+ # @param context [Hash] Optional keyword arguments to pass to the command
79
+ #
80
+ # @return [CMDx::Result] The skipped result object
81
+ #
82
+ # @example Stubbing skipped execution with context
83
+ # stub_task_skip(MyCommand, foo: "bar")
84
+ #
85
+ # result = MyCommand.execute(foo: "bar")
86
+ # expect(result).to have_skipped
87
+ #
88
+ # @example Stubbing skipped execution with reason
89
+ # stub_task_skip(MyCommand, reason: "Skipped for testing", foo: "bar")
90
+ #
91
+ # result = MyCommand.execute(foo: "bar")
92
+ # expect(result).to have_skipped(reason: "Skipped for testing")
93
+ def stub_task_skip(command, reason: nil, cause: nil, metadata: {}, **context)
94
+ task = command.new(context)
95
+ result = task.result
96
+ cause ||= CMDx::SkipFault.new(result)
97
+
98
+ result.executing!
99
+ result.skip!(reason, halt: false, cause:, **metadata)
100
+
101
+ allow(command).to receive(:execute).and_return(result)
102
+
103
+ result
104
+ end
105
+
106
+ # Sets up a stub that allows a command to receive :execute! and return a skipped result.
107
+ #
108
+ # @param command [Class] The command class to stub execution on
109
+ # @param reason [String, nil] Optional reason for skipping
110
+ # @param cause [CMDx::Fault, nil] Optional cause for skipping
111
+ # @param metadata [Hash] Optional metadata to pass to the result
112
+ # @param context [Hash] Optional keyword arguments to pass to the command
113
+ #
114
+ # @return [CMDx::Result] The skipped result object
115
+ #
116
+ # @example Stubbing skipped execution with context
117
+ # stub_task_skip!(MyCommand, foo: "bar")
118
+ #
119
+ # result = MyCommand.execute!(foo: "bar")
120
+ # expect(result).to have_skipped
121
+ #
122
+ # @example Stubbing skipped execution with reason
123
+ # stub_task_skip!(MyCommand, reason: "Skipped for testing", foo: "bar")
124
+ #
125
+ # result = MyCommand.execute!(foo: "bar")
126
+ # expect(result).to have_skipped(reason: "Skipped for testing")
127
+ def stub_task_skip!(command, reason: nil, cause: nil, metadata: {}, **context)
128
+ task = command.new(context)
129
+ result = task.result
130
+ cause ||= CMDx::SkipFault.new(result)
131
+
132
+ result.executing!
133
+ result.skip!(reason, halt: false, cause:, **metadata)
134
+
135
+ allow(command).to receive(:execute!).and_return(result)
136
+
137
+ result
138
+ end
139
+
140
+ # Sets up a stub that allows a command to receive :execute and return a failed result.
141
+ #
142
+ # @param command [Class] The command class to stub execution on
143
+ # @param reason [String, nil] Optional reason for failure
144
+ # @param cause [CMDx::Fault, nil] Optional cause for failure
145
+ # @param metadata [Hash] Optional metadata to pass to the result
146
+ # @param context [Hash] Optional keyword arguments to pass to the command
147
+ #
148
+ # @return [CMDx::Result] The failed result object
149
+ #
150
+ # @example Stubbing failed execution with context
151
+ # stub_task_fail(MyCommand, foo: "bar")
152
+ #
153
+ # result = MyCommand.execute(foo: "bar")
154
+ # expect(result).to have_failed
155
+ #
156
+ # @example Stubbing failed execution with reason
157
+ # stub_task_fail(MyCommand, reason: "Failed for testing", foo: "bar")
158
+ #
159
+ # result = MyCommand.execute(foo: "bar")
160
+ # expect(result).to have_failed(reason: "Failed for testing")
161
+ def stub_task_fail(command, reason: nil, cause: nil, metadata: {}, **context)
162
+ task = command.new(context)
163
+ result = task.result
164
+ cause ||= CMDx::FailFault.new(result)
165
+
166
+ result.executing!
167
+ result.fail!(reason, halt: false, cause:, **metadata)
168
+
169
+ allow(command).to receive(:execute).and_return(result)
170
+
171
+ result
172
+ end
173
+
174
+ # Sets up a stub that allows a command to receive :execute! and return a failed result.
175
+ #
176
+ # @param command [Class] The command class to stub execution on
177
+ # @param reason [String, nil] Optional reason for failure
178
+ # @param cause [CMDx::Fault, nil] Optional cause for failure
179
+ # @param metadata [Hash] Optional metadata to pass to the result
180
+ # @param context [Hash] Optional keyword arguments to pass to the command
181
+ #
182
+ # @return [CMDx::Result] The failed result object
183
+ #
184
+ # @example Stubbing failed execution with context
185
+ # stub_task_fail!(MyCommand, foo: "bar")
186
+ #
187
+ # result = MyCommand.execute!(foo: "bar")
188
+ # expect(result).to have_failed
189
+ #
190
+ # @example Stubbing failed execution with reason
191
+ # stub_task_fail!(MyCommand, reason: "Failed for testing", foo: "bar")
192
+ #
193
+ # result = MyCommand.execute!(foo: "bar")
194
+ # expect(result).to have_failed(reason: "Failed for testing")
195
+ def stub_task_fail!(command, reason: nil, cause: nil, metadata: {}, **context)
196
+ task = command.new(context)
197
+ result = task.result
198
+ cause ||= CMDx::FailFault.new(result)
199
+
200
+ result.executing!
201
+ result.fail!(reason, halt: false, cause:, **metadata)
202
+
203
+ allow(command).to receive(:execute!).and_return(result)
204
+
205
+ result
206
+ end
207
+
208
+ # Unstubs a command's :execute method.
209
+ #
210
+ # @param command [Class] The command class to unstub execution on
211
+ #
212
+ # @return [void]
213
+ #
214
+ # @example Unstubbing execute
215
+ # unstub_task(MyCommand)
216
+ #
217
+ # MyCommand.execute
218
+ def unstub_task(command)
219
+ allow(command).to receive(:execute).and_call_original
220
+ end
221
+
222
+ # Unstubs a command's :execute! method.
223
+ #
224
+ # @param command [Class] The command class to unstub execution on
225
+ #
226
+ # @return [void]
227
+ #
228
+ # @example Unstubbing execute!
229
+ # unstub_task!(MyCommand)
230
+ #
231
+ # MyCommand.execute!
232
+ def unstub_task!(command)
233
+ allow(command).to receive(:execute!).and_call_original
234
+ end
235
+
236
+ # Sets up an expectation that a command will receive :execute with the given context.
237
+ #
238
+ # @param command [Class] The command class to expect execution on
239
+ # @param context [Hash] Optional keyword arguments to match against
240
+ #
241
+ # @return [RSpec::Mocks::MessageExpectation] The RSpec expectation object
242
+ #
243
+ # @example Expecting execution with context
244
+ # expect_task_execution(MyCommand, user_id: 123, role: "admin")
245
+ #
246
+ # MyCommand.execute(user_id: 123, role: "admin")
247
+ #
248
+ # @example Expecting execution without context
249
+ # expect_task_execution(MyCommand)
250
+ #
251
+ # MyCommand.execute
252
+ def expect_task_execution(command, **context)
253
+ if context.empty?
254
+ expect(command).to receive(:execute)
255
+ else
256
+ expect(command).to receive(:execute).with(**context)
257
+ end
258
+ end
259
+
260
+ # Sets up an expectation that a command will receive :execute! with the given context.
261
+ #
262
+ # @param command [Class] The command class to expect execution on
263
+ # @param context [Hash] Optional keyword arguments to match against
264
+ #
265
+ # @return [RSpec::Mocks::MessageExpectation] The RSpec expectation object
266
+ #
267
+ # @example Expecting execution with context
268
+ # expect_task_execution!(MyCommand, user_id: 123, role: "admin")
269
+ #
270
+ # MyCommand.execute!(user_id: 123, role: "admin")
271
+ #
272
+ # @example Expecting execution without context
273
+ # expect_task_execution!(MyCommand)
274
+ #
275
+ # MyCommand.execute!
276
+ def expect_task_execution!(command, **context)
277
+ if context.empty?
278
+ expect(command).to receive(:execute!)
279
+ else
280
+ expect(command).to receive(:execute!).with(**context)
281
+ end
282
+ end
283
+
284
+ end
285
+ end
286
+ end
@@ -1,5 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Matcher to verify that a command is deprecated.
4
+ #
5
+ # @param expected_behavior [Symbol, String, true, false, nil] Optional behavior to check
6
+ # - `:warn` or `/warn/` - checks if deprecation includes warning
7
+ # - `:log` or `/log/` - checks if deprecation includes logging
8
+ # - `:raise` or `/raise/` or `true` - checks if deprecation raises or is truthy
9
+ # - `:none` or `false` or `nil` - checks if deprecation is false or nil
10
+ # - Any other value - checks for exact match
11
+ #
12
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
13
+ #
14
+ # @example Checking if a command is deprecated
15
+ # expect(MyCommand).to be_deprecated
16
+ #
17
+ # @example Checking deprecated with raise behavior
18
+ # expect(MyCommand).to be_deprecated(:raise)
19
+ # expect(MyCommand).to be_deprecated.with_raise
20
+ #
21
+ # @example Checking deprecated with warning behavior
22
+ # expect(MyCommand).to be_deprecated(:warn)
23
+ # expect(MyCommand).to be_deprecated.with_warning
24
+ #
25
+ # @example Checking deprecated with logging behavior
26
+ # expect(MyCommand).to be_deprecated(:log)
27
+ # expect(MyCommand).to be_deprecated.with_logging
28
+ #
29
+ # @example Using chainable matchers
30
+ # expect(MyCommand).to be_deprecated.with_behavior(:custom)
3
31
  RSpec::Matchers.define :be_deprecated do |expected_behavior = nil|
4
32
  description do
5
33
  if (behavior = @expected_behavior || expected_behavior)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a result represents a successful execution.
4
+ #
5
+ # @param data [Hash] Optional hash of additional attributes to match
6
+ # @option data [Symbol] :state Expected state (defaults to CMDx::Result::COMPLETE)
7
+ # @option data [Symbol] :status Expected status (defaults to CMDx::Result::SUCCESS)
8
+ # @option data [Symbol] :outcome Expected outcome (defaults to CMDx::Result::SUCCESS)
9
+ #
10
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
11
+ #
12
+ # @raise [ArgumentError] if the actual value is not a CMDx::Result
13
+ #
14
+ # @example Checking if a result is successful
15
+ # result = MyCommand.execute
16
+ # expect(result).to be_successful
17
+ #
18
+ # @example Checking success with additional attributes
19
+ # result = MyCommand.execute
20
+ # expect(result).to be_successful(state: CMDx::Result::COMPLETE)
21
+ RSpec::Matchers.define :be_successful do |**data|
22
+ description { "have been a success" }
23
+
24
+ match(notify_expectation_failures: true) do |result|
25
+ raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
26
+
27
+ expect(result.to_h).to include(
28
+ state: CMDx::Result::COMPLETE,
29
+ status: CMDx::Result::SUCCESS,
30
+ outcome: CMDx::Result::SUCCESS,
31
+ **data
32
+ )
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a context is empty.
4
+ #
5
+ # @param context [Hash, CMDx::Context, CMDx::Result] The context to check
6
+ # - If Hash, checks the hash directly
7
+ # - If CMDx::Context, converts to hash and checks
8
+ # - If CMDx::Result, extracts context and checks
9
+ #
10
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
11
+ #
12
+ # @raise [RuntimeError] if the context type is unknown
13
+ #
14
+ # @example Checking empty context from a hash
15
+ # context = {}
16
+ # expect(context).to have_empty_context
17
+ #
18
+ # @example Checking empty context from a result
19
+ # result = MyCommand.execute
20
+ # expect(result).to have_empty_context
21
+ RSpec::Matchers.define :have_empty_context do
22
+ description { "have an empty context" }
23
+
24
+ match(notify_expectation_failures: true) do |context|
25
+ ctx =
26
+ case context
27
+ when Hash then context
28
+ when CMDx::Context then context.to_h
29
+ when CMDx::Result then context.context.to_h
30
+ else raise "unknown context type #{context.class}"
31
+ end
32
+
33
+ expect(ctx).to be_empty
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a result has empty metadata.
4
+ #
5
+ # @param result [CMDx::Result] The result to check
6
+ #
7
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
8
+ #
9
+ # @raise [ArgumentError] if the actual value is not a CMDx::Result
10
+ #
11
+ # @example Checking if a result has empty metadata
12
+ # result = MyCommand.execute
13
+ # expect(result).to have_empty_metadata
14
+ RSpec::Matchers.define :have_empty_metadata do
15
+ description { "have an empty metadata" }
16
+
17
+ match(notify_expectation_failures: true) do |result|
18
+ raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
19
+
20
+ expect(result.to_h[:metadata]).to be_empty
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a result represents a failure.
4
+ #
5
+ # @param data [Hash] Optional hash of additional attributes to match
6
+ # @option data [Symbol] :state Expected state (defaults to CMDx::Result::INTERRUPTED)
7
+ # @option data [Symbol] :status Expected status (defaults to CMDx::Result::FAILED)
8
+ # @option data [Symbol] :outcome Expected outcome (defaults to CMDx::Result::FAILED)
9
+ # @option data [String] :reason Expected reason string
10
+ # @option data [CMDx::FailFault] :cause Expected cause fault
11
+ #
12
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
13
+ #
14
+ # @raise [ArgumentError] if the actual value is not a CMDx::Result
15
+ #
16
+ # @example Checking if a result is a failure
17
+ # result = MyCommand.execute
18
+ # expect(result).to have_failed
19
+ #
20
+ # @example Checking failure with specific reason
21
+ # result = MyCommand.execute
22
+ # expect(result).to have_failed(reason: "Custom error message")
23
+ RSpec::Matchers.define :have_failed do |**data|
24
+ description { "have been a failure" }
25
+
26
+ match(notify_expectation_failures: true) do |result|
27
+ raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
28
+
29
+ expect(result.to_h).to include(
30
+ state: CMDx::Result::INTERRUPTED,
31
+ status: CMDx::Result::FAILED,
32
+ outcome: CMDx::Result::FAILED,
33
+ reason: CMDx::Locale.t("cmdx.faults.unspecified"),
34
+ cause: be_a(CMDx::FailFault),
35
+ **data
36
+ )
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a context matches the given data.
4
+ #
5
+ # @param data [Hash] Optional hash of key-value pairs to match in the context
6
+ # If empty, delegates to {have_empty_context}
7
+ #
8
+ # @param context [Hash, CMDx::Context, CMDx::Result] The context to check
9
+ # - If Hash, checks the hash directly
10
+ # - If CMDx::Context, converts to hash and checks
11
+ # - If CMDx::Result, extracts context and checks
12
+ #
13
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
14
+ #
15
+ # @raise [RuntimeError] if the context type is unknown
16
+ #
17
+ # @example Checking context matches specific values
18
+ # result = MyCommand.execute(user_id: 123, role: "admin")
19
+ # expect(result).to have_matching_context(user_id: 123, role: "admin")
20
+ #
21
+ # @example Checking empty context
22
+ # result = MyCommand.execute
23
+ # expect(result).to have_matching_context
24
+ RSpec::Matchers.define :have_matching_context do |**data|
25
+ description { "have matching context" }
26
+
27
+ match(notify_expectation_failures: true) do |context|
28
+ ctx =
29
+ case context
30
+ when Hash then context
31
+ when CMDx::Context then context.to_h
32
+ when CMDx::Result then context.context.to_h
33
+ else raise "unknown context type #{context.class}"
34
+ end
35
+
36
+ if data.empty?
37
+ expect(ctx).to have_empty_context
38
+ else
39
+ expect(ctx).to include(**data)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a result's metadata matches the given data.
4
+ #
5
+ # @param data [Hash] Optional hash of key-value pairs to match in the metadata
6
+ # If empty, delegates to {have_empty_metadata}
7
+ #
8
+ # @param result [CMDx::Result] The result to check
9
+ #
10
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
11
+ #
12
+ # @raise [ArgumentError] if the actual value is not a CMDx::Result
13
+ #
14
+ # @example Checking metadata matches specific values
15
+ # result = MyCommand.execute
16
+ # expect(result).to have_matching_metadata(key: "value", count: 42)
17
+ #
18
+ # @example Checking empty metadata
19
+ # result = MyCommand.execute
20
+ # expect(result).to have_matching_metadata
21
+ RSpec::Matchers.define :have_matching_metadata do |**data|
22
+ description { "have matching metadata" }
23
+
24
+ match(notify_expectation_failures: true) do |result|
25
+ raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
26
+
27
+ if data.empty?
28
+ expect(result).to have_empty_metadata
29
+ else
30
+ expect(result.to_h[:metadata]).to include(**data)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Matcher to verify that a result represents a skipped execution.
4
+ #
5
+ # @param data [Hash] Optional hash of additional attributes to match
6
+ # @option data [Symbol] :state Expected state (defaults to CMDx::Result::INTERRUPTED)
7
+ # @option data [Symbol] :status Expected status (defaults to CMDx::Result::SKIPPED)
8
+ # @option data [Symbol] :outcome Expected outcome (defaults to CMDx::Result::SKIPPED)
9
+ # @option data [String] :reason Expected reason string
10
+ # @option data [CMDx::SkipFault] :cause Expected cause fault
11
+ #
12
+ # @return [RSpec::Matchers::BuiltIn::BaseMatcher] The matcher instance
13
+ #
14
+ # @raise [ArgumentError] if the actual value is not a CMDx::Result
15
+ #
16
+ # @example Checking if a result is skipped
17
+ # result = MyCommand.execute
18
+ # expect(result).to have_skipped
19
+ #
20
+ # @example Checking skipped with specific reason
21
+ # result = MyCommand.execute
22
+ # expect(result).to have_skipped(reason: "Skipped for testing")
23
+ RSpec::Matchers.define :have_skipped do |**data|
24
+ description { "have been skipped" }
25
+
26
+ match(notify_expectation_failures: true) do |result|
27
+ raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
28
+
29
+ expect(result.to_h).to include(
30
+ state: CMDx::Result::INTERRUPTED,
31
+ status: CMDx::Result::SKIPPED,
32
+ outcome: CMDx::Result::SKIPPED,
33
+ reason: CMDx::Locale.t("cmdx.faults.unspecified"),
34
+ cause: be_a(CMDx::SkipFault),
35
+ **data
36
+ )
37
+ end
38
+ end
@@ -3,7 +3,7 @@
3
3
  module CMDx
4
4
  module RSpec
5
5
 
6
- VERSION = "0.2.0"
6
+ VERSION = "1.1.0"
7
7
 
8
8
  end
9
9
  end
data/lib/cmdx/rspec.rb CHANGED
@@ -3,11 +3,13 @@
3
3
  require "cmdx"
4
4
  require "rspec"
5
5
 
6
- require_relative "rspec/be_deprecated"
7
- require_relative "rspec/have_been_failure"
8
- require_relative "rspec/have_been_skipped"
9
- require_relative "rspec/have_been_success"
10
- require_relative "rspec/have_empty_context"
11
- require_relative "rspec/have_matching_context"
12
- require_relative "rspec/have_empty_metadata"
13
- require_relative "rspec/have_matching_metadata"
6
+ require_relative "rspec/helpers"
7
+
8
+ require_relative "rspec/matchers/be_deprecated"
9
+ require_relative "rspec/matchers/be_successful"
10
+ require_relative "rspec/matchers/have_skipped"
11
+ require_relative "rspec/matchers/have_failed"
12
+ require_relative "rspec/matchers/have_empty_context"
13
+ require_relative "rspec/matchers/have_matching_context"
14
+ require_relative "rspec/matchers/have_empty_metadata"
15
+ require_relative "rspec/matchers/have_matching_metadata"
Binary file
Binary file
data/src/cmdx-logo.svg ADDED
@@ -0,0 +1 @@
1
+ <svg width="352.2" height="112.266" viewBox="0 0 203 64.708" xmlns="http://www.w3.org/2000/svg" xmlSpace="preserve"><path d="M172.908 17.723 169.4 23.17 156.385 3.323h3.507l9.508 14.77 1.938-3.139L161.738 0h-11.446L169.4 29.262 188.046 0h-3.97L173 17.54zm-20.677 43.57h-3.139l18.646-29.447L147.431.093h-3.97l20.308 31.846L143 64.708l10.985-.092 39.138-61.2h3.323L174.57 37.754l13.662 21.415h3.969l-13.754-21.415L202.538.093H191.37zm29.63-23.262 15.047 23.262h-10.523l-13.662-20.77-15.508 24.093h3.97l11.63-18 11.723 18H203l-18.83-29.262-.278-.461z" fill="#fe1817"/><path d="M41.667 14v12.8h-23.42c-3.214.272-5.665 3.05-5.665 6.318s2.45 5.937 5.664 6.318H33.17v4.248H18.246a10.65 10.65 0 0 1-9.858-10.62c0-5.447 4.194-10.077 9.64-10.512h19.39v-4.303H18.246v.054A14.823 14.823 0 0 0 4.248 33.118c0 7.898 6.21 14.38 13.998 14.815h19.172v-8.497h4.249v12.745h-23.42A19.063 19.063 0 0 1 0 33.118a19.033 19.033 0 0 1 18.246-19.063zM75 35.623 87.2 14h13.508v38.181H87.963v-14.27l-8.116 14.27h-9.749L57.734 30.504v-8.007l14.87 25.436h4.792l14.815-25.436v25.436h4.249V18.249H89.65l-14.76 25.49-14.542-25.49H53.54v29.684h4.194v-8.007l4.249 7.299v4.956H49.292v-38.18H62.8zM108.333 14h23.42C141.94 14.436 150 22.824 150 33.064c0 10.294-8.061 18.681-18.246 19.117h-23.42V22.497h23.42a10.65 10.65 0 0 1 9.858 10.621c0 5.447-4.194 10.13-9.64 10.566H116.83V30.286h4.248v9.15l10.676-.054c3.213-.273 5.664-3.05 5.664-6.264 0-2.778-1.743-5.065-4.194-5.991-.926-.382-1.47-.382-2.94-.382h-17.702v21.188h19.172a14.84 14.84 0 0 0 13.998-14.87c0-7.897-6.21-14.379-13.998-14.814h-23.42z"/></svg>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdx-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
@@ -141,16 +141,19 @@ files:
141
141
  - README.md
142
142
  - Rakefile
143
143
  - lib/cmdx/rspec.rb
144
- - lib/cmdx/rspec/be_deprecated.rb
145
- - lib/cmdx/rspec/have_been_failure.rb
146
- - lib/cmdx/rspec/have_been_skipped.rb
147
- - lib/cmdx/rspec/have_been_success.rb
148
- - lib/cmdx/rspec/have_empty_context.rb
149
- - lib/cmdx/rspec/have_empty_metadata.rb
150
- - lib/cmdx/rspec/have_matching_context.rb
151
- - lib/cmdx/rspec/have_matching_metadata.rb
144
+ - lib/cmdx/rspec/helpers.rb
145
+ - lib/cmdx/rspec/matchers/be_deprecated.rb
146
+ - lib/cmdx/rspec/matchers/be_successful.rb
147
+ - lib/cmdx/rspec/matchers/have_empty_context.rb
148
+ - lib/cmdx/rspec/matchers/have_empty_metadata.rb
149
+ - lib/cmdx/rspec/matchers/have_failed.rb
150
+ - lib/cmdx/rspec/matchers/have_matching_context.rb
151
+ - lib/cmdx/rspec/matchers/have_matching_metadata.rb
152
+ - lib/cmdx/rspec/matchers/have_skipped.rb
152
153
  - lib/cmdx/rspec/version.rb
153
- - src/cmdx-rspec-logo.png
154
+ - src/cmdx-dark-logo.png
155
+ - src/cmdx-light-logo.png
156
+ - src/cmdx-logo.svg
154
157
  homepage: https://github.com/drexed/cmdx-rspec
155
158
  licenses:
156
159
  - MIT
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_been_failure do |**data|
4
- description { "have been a failure" }
5
-
6
- match(notify_expectation_failures: true) do |result|
7
- raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
8
-
9
- expect(result.to_h).to include(
10
- state: CMDx::Result::INTERRUPTED,
11
- status: CMDx::Result::FAILED,
12
- outcome: CMDx::Result::FAILED,
13
- reason: CMDx::Locale.t("cmdx.faults.unspecified"),
14
- cause: be_a(CMDx::FailFault),
15
- **data
16
- )
17
- end
18
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_been_skipped do |**data|
4
- description { "have been skipped" }
5
-
6
- match(notify_expectation_failures: true) do |result|
7
- raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
8
-
9
- expect(result.to_h).to include(
10
- state: CMDx::Result::INTERRUPTED,
11
- status: CMDx::Result::SKIPPED,
12
- outcome: CMDx::Result::SKIPPED,
13
- reason: CMDx::Locale.t("cmdx.faults.unspecified"),
14
- cause: be_a(CMDx::SkipFault),
15
- **data
16
- )
17
- end
18
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_been_success do |**data|
4
- description { "have been a success" }
5
-
6
- match(notify_expectation_failures: true) do |result|
7
- raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
8
-
9
- expect(result.to_h).to include(
10
- state: CMDx::Result::COMPLETE,
11
- status: CMDx::Result::SUCCESS,
12
- outcome: CMDx::Result::SUCCESS,
13
- **data
14
- )
15
- end
16
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_empty_context do
4
- description { "have an empty context" }
5
-
6
- match(notify_expectation_failures: true) do |context|
7
- ctx =
8
- case context
9
- when Hash then context
10
- when CMDx::Context then context.to_h
11
- when CMDx::Result then context.context.to_h
12
- else raise "unknown context type #{context.class}"
13
- end
14
-
15
- expect(ctx).to be_empty
16
- end
17
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_empty_metadata do
4
- description { "have an empty metadata" }
5
-
6
- match(notify_expectation_failures: true) do |result|
7
- raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
8
-
9
- expect(result.to_h[:metadata]).to be_empty
10
- end
11
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_matching_context do |**data|
4
- description { "have matching context" }
5
-
6
- match(notify_expectation_failures: true) do |context|
7
- ctx =
8
- case context
9
- when Hash then context
10
- when CMDx::Context then context.to_h
11
- when CMDx::Result then context.context.to_h
12
- else raise "unknown context type #{context.class}"
13
- end
14
-
15
- if data.empty?
16
- expect(ctx).to have_empty_context
17
- else
18
- expect(ctx).to include(**data)
19
- end
20
- end
21
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec::Matchers.define :have_matching_metadata do |**data|
4
- description { "have matching metadata" }
5
-
6
- match(notify_expectation_failures: true) do |result|
7
- raise ArgumentError, "must be a CMDx::Result" unless result.is_a?(CMDx::Result)
8
-
9
- if data.empty?
10
- expect(result).to have_empty_metadata
11
- else
12
- expect(result.to_h[:metadata]).to include(**data)
13
- end
14
- end
15
- end
Binary file