cmdx-rspec 0.1.0 → 1.0.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: c71665a9df22d3f4b31837985f80f468cbc8ca745878f596435d86fa78fc6c09
4
- data.tar.gz: 0e89b8a0d57347c00c0b4ebff093945ea9286623f843603c838768b83fcc71d4
3
+ metadata.gz: 1ed75f972481a1a428a86ce5ff19f3a804126f1e305097886f983cd102a00ced
4
+ data.tar.gz: 2bdc655439c8bafb3d865d13018290cd935262edef756596aa73b23dd9f0e85d
5
5
  SHA512:
6
- metadata.gz: f8128839bb2cfddf0fb79947354869512e355259391abb337e5bec462feeb29cc81b6831509d115b7534d6d7b24c9d85cb1b23c6ea26b0b324e3540344260d93
7
- data.tar.gz: 2e4cd45210779381653e3bfbee2c0cf2d5d7da3521169ca75abf43a47be132b9cd02e9b15844e607046718d6972f26b019615bca6505c1fd6987f3c430bbb288
6
+ metadata.gz: 711527fe0d0a79306f45dda1918aeaf656926064e5c7573dabb33785afb52d9b013ca663115340c222b2502900740f235741598b410d5861bc1fb26618d87357
7
+ data.tar.gz: 666bc45fdfb94f09d378c8a8adbee16f15d66e8069e2b324069602274b7ec49aacf79f64e98d8dd6a472137c2937bb9d465f212c7b7d787e6869319968f9ebdf
@@ -11,8 +11,8 @@ 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
15
- Reference the CMDx::I18n documentation in https://github.com/drexed/cmdx-i18n/blob/main/README.md
14
+ Reference the CMDx documentation in https://drexed.github.io/cmdx/llms.txt
15
+ Reference the CMDx::RSpec documentation in https://github.com/drexed/cmdx-rspec/blob/main/README.md
16
16
 
17
17
  ## Technology Stack
18
18
  - Ruby 3.4+
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
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.0.0] - 2025-11-09
10
+
11
+ ### Added
12
+ - Added mock and stub helpers
13
+
14
+ ### Changed
15
+ - Renamed `have_been_success` to `be_successful`
16
+ - Renamed `have_been_failure` to `have_failed`
17
+ - Renamed `have_been_skipped` to `have_skipped`
18
+ - Moved matchers to be within the `lib/rspec/matchers` directory
19
+
20
+ ## [0.2.0] - 2025-09-13
21
+
22
+ ### Added
23
+ - Added `have_empty_metadata` and `have_matching_metadata` matchers
24
+
25
+ ### Changed
26
+ - Metadata matching must be done via the methods above instead of the fault matchers
27
+
3
28
  ## [0.1.0] - 2025-08-24
4
29
 
5
30
  - Initial release
data/README.md CHANGED
@@ -1,14 +1,19 @@
1
- <p align="center">
2
- <img src="./src/cmdx-rspec-logo.png" width="200" alt="CMDx::I18n 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
- # CMDx::I18n
16
+ # CMDx::RSpec
12
17
 
13
18
  Collection of RSpec matchers for [CMDx](https://github.com/drexed/cmdx).
14
19
 
@@ -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,15 @@ 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(reason: "Skipping for a custom reason")
54
63
  end
55
64
  ```
56
65
 
57
- ### have_been_failure
66
+ ### have_failed
58
67
 
59
68
  Asserts that a CMDx task result indicates execution failure.
60
69
 
@@ -62,7 +71,35 @@ Asserts that a CMDx task result indicates execution failure.
62
71
  it "returns failure" do
63
72
  result = SomeTask.execute
64
73
 
65
- expect(result).to have_been_failure
74
+ # Default result
75
+ expect(result).to have_failed
76
+
77
+ # Custom result
78
+ expect(result).to have_failed(reason: "Failed for a custom reason")
79
+ end
80
+ ```
81
+
82
+ ### have_empty_metadata
83
+
84
+ Asserts that a CMDx task result has no metadata.
85
+
86
+ ```ruby
87
+ it "returns empty metadata" do
88
+ result = SomeTask.execute
89
+
90
+ expect(result).to have_empty_metadata
91
+ end
92
+ ```
93
+
94
+ ### have_matching_metadata
95
+
96
+ Asserts that a CMDx task result contains specific metadata.
97
+
98
+ ```ruby
99
+ it "returns matching metadata" do
100
+ result = SomeTask.execute
101
+
102
+ expect(result).to have_matching_metadata(status_code: 500)
66
103
  end
67
104
  ```
68
105
 
@@ -96,9 +133,117 @@ Asserts that a CMDx task result indicates the task is deprecated.
96
133
 
97
134
  ```ruby
98
135
  it "returns deprecated" do
99
- result = SomeTask.execute
136
+ expect(SomeTask).to be_deprecated
137
+ end
138
+ ```
139
+
140
+ ## Helpers
141
+
142
+ ### Including Helper Modules
143
+
144
+ Include the helper modules in your RSpec configuration or example groups:
145
+
146
+ ```ruby
147
+ RSpec.configure do |config|
148
+ config.include CMDx::RSpec::Helpers
149
+ end
150
+ ```
151
+
152
+ Or include them in specific example groups:
153
+
154
+ ```ruby
155
+ describe MyFeature do
156
+ include CMDx::RSpec::Helpers
157
+
158
+ # Your specs...
159
+ end
160
+ ```
161
+
162
+ ### Stubs
163
+
164
+ Helper methods for stubbing CMDx command execution.
165
+
166
+ ### Execution types
167
+
168
+ ```ruby
169
+ it "stubs task executions by type" do
170
+ # eg: SomeTask.execute
171
+ stub_task_success(SomeTask)
172
+ stub_task_skip(SomeTask)
173
+ stub_task_fail(SomeTask)
174
+
175
+ # eg: SomeTask.execute!
176
+ stub_task_success!(SomeTask)
177
+ stub_task_skip!(SomeTask)
178
+ stub_task_fail!(SomeTask)
179
+
180
+ # Your specs...
181
+ end
182
+ ```
183
+
184
+ ### Options
185
+
186
+ ```ruby
187
+ it "stubs task with arguments" do
188
+ # eg: SomeTask.execute(some: "value")
189
+ stub_task_success(SomeTask, some: "value")
190
+
191
+ # eg: SomeTask.execute!(some: "value")
192
+ stub_task_skip!(SomeTask, some: "value")
193
+
194
+ # Your specs...
195
+ end
196
+ ```
197
+
198
+ ```ruby
199
+ it "stubs task with metadata" do
200
+ stub_task_success(SomeTask, metadata: { some: "value" })
201
+
202
+ # Your specs...
203
+ end
204
+
205
+ it "stubs task with a custom reason" do
206
+ stub_task_skip!(SomeTask, reason: "Skipping for a custom reason")
207
+
208
+ # Your specs...
209
+ end
210
+
211
+ it "stubs task with a custom cause" do
212
+ stub_task_fail!(SomeTask, cause: NoMethodError.new("just blow it up"))
213
+
214
+ # Your specs...
215
+ end
216
+ ```
217
+
218
+ ### Mocks
219
+
220
+ Helper methods for setting expectations on CMDx command execution.
221
+
222
+ ### Execution types
223
+
224
+ ```ruby
225
+ it "mocks task executions by type" do
226
+ # eg: SomeTask.execute
227
+ expect_task_execution(SomeTask)
228
+
229
+ # eg: SomeTask.execute!
230
+ expect_task_execution!(BangCommand)
231
+
232
+ # Your specs...
233
+ end
234
+ ```
235
+
236
+ ### Options
237
+
238
+ ```ruby
239
+ it "mocks task with arguments" do
240
+ # eg: SomeTask.execute(some: "value")
241
+ expect_task_execution(SomeTask, some: "value")
242
+
243
+ # eg: SomeTask.execute!(some: "value")
244
+ expect_task_execution!(SomeTask, some: "value")
100
245
 
101
- expect(result).to be_deprecated
246
+ # Your specs...
102
247
  end
103
248
  ```
104
249
 
@@ -0,0 +1,258 @@
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
+ # Sets up an expectation that a command will receive :execute with the given context.
209
+ #
210
+ # @param command [Class] The command class to expect execution on
211
+ # @param context [Hash] Optional keyword arguments to match against
212
+ #
213
+ # @return [RSpec::Mocks::MessageExpectation] The RSpec expectation object
214
+ #
215
+ # @example Expecting execution with context
216
+ # expect_task_execution(MyCommand, user_id: 123, role: "admin")
217
+ #
218
+ # MyCommand.execute(user_id: 123, role: "admin")
219
+ #
220
+ # @example Expecting execution without context
221
+ # expect_task_execution(MyCommand)
222
+ #
223
+ # MyCommand.execute
224
+ def expect_task_execution(command, **context)
225
+ if context.empty?
226
+ expect(command).to receive(:execute)
227
+ else
228
+ expect(command).to receive(:execute).with(**context)
229
+ end
230
+ end
231
+
232
+ # Sets up an expectation that a command will receive :execute! with the given context.
233
+ #
234
+ # @param command [Class] The command class to expect execution on
235
+ # @param context [Hash] Optional keyword arguments to match against
236
+ #
237
+ # @return [RSpec::Mocks::MessageExpectation] The RSpec expectation object
238
+ #
239
+ # @example Expecting execution with context
240
+ # expect_task_execution!(MyCommand, user_id: 123, role: "admin")
241
+ #
242
+ # MyCommand.execute!(user_id: 123, role: "admin")
243
+ #
244
+ # @example Expecting execution without context
245
+ # expect_task_execution!(MyCommand)
246
+ #
247
+ # MyCommand.execute!
248
+ def expect_task_execution!(command, **context)
249
+ if context.empty?
250
+ expect(command).to receive(:execute!)
251
+ else
252
+ expect(command).to receive(:execute!).with(**context)
253
+ end
254
+ end
255
+
256
+ end
257
+ end
258
+ 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.1.0"
6
+ VERSION = "1.0.0"
7
7
 
8
8
  end
9
9
  end
data/lib/cmdx/rspec.rb CHANGED
@@ -3,9 +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"
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.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
@@ -141,23 +141,28 @@ 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_matching_context.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
150
153
  - lib/cmdx/rspec/version.rb
151
- - src/cmdx-rspec-logo.png
154
+ - src/cmdx-dark-logo.png
155
+ - src/cmdx-light-logo.png
156
+ - src/cmdx-logo.svg
152
157
  homepage: https://github.com/drexed/cmdx-rspec
153
158
  licenses:
154
159
  - MIT
155
160
  metadata:
156
161
  homepage_uri: https://github.com/drexed/cmdx-rspec
157
162
  source_code_uri: https://github.com/drexed/cmdx-rspec
158
- changelog_uri: https://github.com/drexed/cmdx-rspec/blob/main/CHANGELOG.md
163
+ changelog_uri: https://github.com/drexed/cmdx-rspec/blob/master/CHANGELOG.md
159
164
  bug_tracker_uri: https://github.com/drexed/cmdx-rspec/issues
160
- documentation_uri: https://github.com/drexed/cmdx-rspec/blob/main/README.md
165
+ documentation_uri: https://github.com/drexed/cmdx-rspec/blob/master/README.md
161
166
  rubygems_mfa_required: 'true'
162
167
  rdoc_options: []
163
168
  require_paths:
@@ -173,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
178
  - !ruby/object:Gem::Version
174
179
  version: '0'
175
180
  requirements: []
176
- rubygems_version: 3.7.1
181
+ rubygems_version: 3.7.2
177
182
  specification_version: 4
178
183
  summary: Simple CMDx task testing via RSpec matchers.
179
184
  test_files: []
@@ -1,19 +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
- metadata: {},
14
- reason: CMDx::Locale.t("cmdx.faults.unspecified"),
15
- cause: be_a(CMDx::FailFault),
16
- **data
17
- )
18
- end
19
- end
@@ -1,19 +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
- metadata: {},
14
- reason: CMDx::Locale.t("cmdx.faults.unspecified"),
15
- cause: be_a(CMDx::SkipFault),
16
- **data
17
- )
18
- end
19
- end
@@ -1,17 +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
- metadata: {},
14
- **data
15
- )
16
- end
17
- 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,17 +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
- expect(ctx).to include(**data)
16
- end
17
- end
Binary file