spec_forge 0.7.0 โ†’ 0.7.1

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: 7f8c38cb9ff50cb02ee74171a4d571ac411807b1dcce43edab0f28a757269b2f
4
- data.tar.gz: 1595911a7a84d7712ddcc5bf0e2a08c0c30afce995ac02bb1372c1ae29ca7db0
3
+ metadata.gz: 9891353d8acd7d64ec4b2690e4e91d68c0d455913b8ca81c7f9e410859f51774
4
+ data.tar.gz: 7ff9aa712f7d21a75ae8a383175702ed8973b25e2935458bd75dd713f59b6fb3
5
5
  SHA512:
6
- metadata.gz: 731ff8f0cc847010f38caab823c7d30c0d3d7083d4ea53de6ac46c19929c2c31ce698db787303c706ae6ee517dea396ef5ceb220732dd172050967404dd102af
7
- data.tar.gz: 1a24dd8f84528427e30d105c4e358ca226b699e79a68a9ac2eb5385a974abb2acb27f8c8a3751e8c69a70001ef8d2ef3938ab06f9c81f1f041325b1b038923e1
6
+ metadata.gz: 0637e96a8739579015af17ee0a6c8442b51c9fd189b2a220b7828ae68f0784760aad4d5312eabf450f18ee7e6db2789dad3fb55327cee0aa19f3a8e9b88be243
7
+ data.tar.gz: 3d10cc2cafb76d2d14b42e104fba62a5e8ec35d70cb92f6769e3fcde9611d9949d707fdc287caae52454e04d6542c507274e357bb38f41090792efa40e5d6436
data/CHANGELOG.md CHANGED
@@ -15,14 +15,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
15
  ### Removed
16
16
  -->
17
17
 
18
+ ## [0.7.1] - 12025-10-08
19
+
20
+ ### Added
21
+
22
+ - **Configuration alias**: `base_path` can now be used as an alias for `base_url` in spec definitions
23
+ - **Improved debug configuration**: New `config.on_debug { }` block syntax for cleaner configuration
24
+
25
+ ```ruby
26
+ # New cleaner syntax (recommended)
27
+ config.on_debug { binding.pry }
28
+
29
+ # Old syntax still works with deprecation warning
30
+ config.on_debug = -> { binding.pry }
31
+ ```
32
+
33
+ ### Changed
34
+
35
+ - **Fixed path handling in HTTP requests**: Paths with leading slashes (e.g., `/users`) now properly append to base URLs instead of replacing the entire path
36
+ - Previously, a base URL like `http://api.example.com/v1` with path `/users` would incorrectly resolve to `http://api.example.com/users`
37
+ - Now correctly resolves to `http://api.example.com/v1/users`
38
+ - This matches user expectations and common API patterns
39
+ - **Note**: If you need to replace the entire path, use absolute URLs like `https://api.example.com/users`
40
+ - **CI/CD improvements**: Updated to GitHub Actions checkout v5 and streamlined Ruby version testing
41
+
42
+ ### Fixed
43
+
44
+ - **Transform.join resolution**: Now properly generates fresh values instead of using cached results
45
+ - **Test adapter optimization**: Removed JSON class validation check to allow matchers to be used
46
+
47
+ ### Deprecated
48
+
49
+ - `config.on_debug = proc` syntax - use `config.on_debug { }` block syntax instead
50
+
18
51
  ## [0.7.0] - 12025-06-22
19
52
 
20
53
  ### Added
21
54
 
22
55
  #### ๐Ÿš€ Documentation-First Architecture
56
+
23
57
  **The Big Picture**: SpecForge now generates OpenAPI documentation from your tests automatically!
24
58
 
25
59
  - **Primary Documentation Workflow**: New `docs` command (now the default!) generates OpenAPI specs from test execution
60
+
26
61
  - Smart caching system with `--fresh` flag for forced regeneration
27
62
  - Multiple output formats: YAML (default) or JSON via `--format`
28
63
  - Custom output paths with `--output` option
@@ -30,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
30
65
  - Optional validation skip with `--skip-validation` for faster iterations
31
66
 
32
67
  - **Live Documentation Server**: `spec_forge serve` command for immediate feedback
68
+
33
69
  - Local web server with Swagger UI (default) or Redoc (`--ui redoc`)
34
70
  - Configurable port with `--port` (defaults to 8080)
35
71
  - Auto-generated HTML templates for both UI options
@@ -44,17 +80,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
44
80
  #### ๐Ÿงช Enhanced Testing Capabilities
45
81
 
46
82
  - **HTTP Header Testing**: Comprehensive header validation
83
+
47
84
  ```yaml
48
85
  headers:
49
86
  Content-Type: "application/json"
50
87
  X-Request-ID: /^[0-9a-f-]{36}$/
51
88
  Cache-Control:
52
89
  matcher.and:
53
- - matcher.include: "max-age="
54
- - matcher.include: "private"
90
+ - matcher.include: "max-age="
91
+ - matcher.include: "private"
55
92
  ```
56
93
 
57
94
  - **Flexible Store System**: Store anything, access everything
95
+
58
96
  - OpenStruct-based entries for maximum flexibility
59
97
  - Custom data via callbacks (config, metadata, computed values)
60
98
  - Same familiar `store.id.attribute` syntax
@@ -67,12 +105,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
67
105
  #### โš™๏ธ Architecture Improvements
68
106
 
69
107
  - **YAML-Driven Normalizers**: Configuration over code
108
+
70
109
  - Structure definitions in `lib/spec_forge/normalizers/*.yml`
71
110
  - Powerful `reference:` system for reusable components
72
111
  - Wildcard support (`*`) for catch-all schemas
73
112
  - Centralized validation logic in dedicated module
74
113
 
75
114
  - **Enhanced CLI Experience**:
115
+
76
116
  - Improved `init` command with `--skip-openapi` and `--skip-factories` flags
77
117
  - Better help text and examples throughout
78
118
  - Clearer error messages with actionable context
@@ -87,6 +127,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
87
127
  #### ๐ŸŽฏ User Experience Overhaul
88
128
 
89
129
  - **New Default Behavior**: `spec_forge` without arguments now shows help instead of running tests
130
+
90
131
  - **Breaking Change**: Use `spec_forge docs` for documentation or `spec_forge run` for test-only execution
91
132
  - Safer default that guides users to the right command for their needs
92
133
 
@@ -98,11 +139,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
98
139
  #### ๐Ÿ—๏ธ Internal Refactoring
99
140
 
100
141
  - **Normalizer Architecture**: YAML-based instead of class-heavy approach
142
+
101
143
  - Consolidated shared definitions in `_shared.yml`
102
144
  - Easier maintenance and extension
103
145
  - Better error context with attribute path tracking
104
146
 
105
147
  - **Test Execution Pipeline**:
148
+
106
149
  - Clean separation between test preparation and execution
107
150
  - Enhanced RSpec adapter pattern
108
151
  - Better reusability for documentation generation
@@ -119,6 +162,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
119
162
  ---
120
163
 
121
164
  **Migration Notes**:
165
+
122
166
  - Update any scripts using bare `spec_forge` - now shows help instead of running tests
123
167
  - Use `spec_forge docs` for documentation generation or `spec_forge run` for testing
124
168
  - Store access patterns remain the same, but internal structure is more flexible
@@ -134,6 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
134
178
  - `Context::Variables` for managing variables with overlay support
135
179
  - `Context::Store` for storing the results of the tests
136
180
  - Added support for defining and referencing global variables
181
+
137
182
  ```yaml
138
183
  global:
139
184
  variables:
@@ -145,13 +190,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
145
190
  query:
146
191
  api_version: "global.variables.api_version"
147
192
  ```
193
+
148
194
  - Added compound matcher support via `matcher.and` for combining multiple matchers
149
195
  ```yaml
150
196
  email:
151
197
  matcher.and:
152
- - kind_of.string
153
- - /@/
154
- - matcher.end_with: ".com"
198
+ - kind_of.string
199
+ - /@/
200
+ - matcher.end_with: ".com"
155
201
  ```
156
202
  - Added custom RSpec matcher `have_size` for checking an object's size via `matcher.have_size`
157
203
  - Added new `Loader` class for improved spec file processing
@@ -159,6 +205,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
159
205
  - Added normalizer for global context validation
160
206
  - Added line number tracking for specs and expectations
161
207
  - Added support for defining and referencing callbacks
208
+
162
209
  ```ruby
163
210
  # Configuration level
164
211
  SpecForge.configure do |config|
@@ -171,14 +218,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
171
218
  # Module level (no aliases)
172
219
  SpecForge.register_callback("callback_name") { |context| }
173
220
  ```
221
+
174
222
  Once defined, callbacks can be referenced in spec files via the global context
223
+
175
224
  ```yaml
176
225
  global:
177
226
  callbacks:
178
- - before: callback_name
179
- after: cleanup_database_state
227
+ - before: callback_name
228
+ after: cleanup_database_state
180
229
  ```
230
+
181
231
  - Added support for storing and retrieving test data via the `store_as` directive and `store` attribute
232
+
182
233
  ```yaml
183
234
  create_user:
184
235
  path: "/users"
@@ -198,6 +249,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
198
249
  - expect:
199
250
  status: 200
200
251
  ```
252
+
201
253
  - Added `UndefinedMatcherError` for clearer error messaging when invalid matchers are used
202
254
  - Enhanced debugging capabilities with improved DebugProxy methods and store access
203
255
  - Added HTTP status descriptions for better error messages
@@ -248,7 +300,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
248
300
  variables:
249
301
  users:
250
302
  factory.user:
251
- size: 10 # Creates 10 user records
303
+ size: 10 # Creates 10 user records
252
304
  ```
253
305
  - All FactoryBot list methods now supported:
254
306
  - `create_list` (default)
@@ -307,6 +359,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
307
359
  ### Added
308
360
 
309
361
  - Core Infrastructure
362
+
310
363
  - Configuration management
311
364
  - User input validation and normalization
312
365
  - Factory registration
@@ -316,11 +369,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
316
369
  - Debugging tooling
317
370
 
318
371
  - CLI
372
+
319
373
  - Project initialization (`init`)
320
374
  - Spec/factory generation (`new`)
321
375
  - Test execution (`run`)
322
376
 
323
377
  - Attributes
378
+
324
379
  - Chainable attribute handling (through `Chainable`)
325
380
  - Expanded attribute handling (through `Parameterized`)
326
381
  - Factory (with chainable support) - `factories.`
@@ -339,7 +394,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
339
394
 
340
395
  - Initial commit
341
396
 
342
- [unreleased]: https://github.com/itsthedevman/spec_forge/compare/v0.7.0...HEAD
397
+ [unreleased]: https://github.com/itsthedevman/spec_forge/compare/v0.7.1...HEAD
398
+ [0.7.1]: https://github.com/itsthedevman/spec_forge/compare/v0.7.0...v0.7.1
343
399
  [0.7.0]: https://github.com/itsthedevman/spec_forge/compare/v0.6.0...v0.7.0
344
400
  [0.6.0]: https://github.com/itsthedevman/spec_forge/compare/v0.5.0...v0.6.0
345
401
  [0.5.0]: https://github.com/itsthedevman/spec_forge/compare/v0.4.0...v0.5.0
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # SpecForge
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/spec_forge.svg)](https://badge.fury.io/rb/spec_forge)
4
- ![Ruby Version](https://img.shields.io/badge/ruby-3.3.7-ruby)
4
+ ![Ruby Version](https://img.shields.io/badge/ruby-3.2+-ruby)
5
5
  [![Tests](https://github.com/itsthedevman/spec_forge/actions/workflows/main.yml/badge.svg)](https://github.com/itsthedevman/spec_forge/actions/workflows/main.yml)
6
6
 
7
- > Note: The code in this repository represents the latest development version with new features and improvements that are being prepared for future releases. For the current stable version, check out [v0.6.0](https://github.com/itsthedevman/spec_forge/releases/tag/v0.6.0) on GitHub releases.
7
+ > Note: The code in this repository represents the latest development version with new features and improvements that are being prepared for future releases. For the current stable version, check out [v0.7.1](https://github.com/itsthedevman/spec_forge/releases/tag/v0.7.1) on GitHub releases.
8
8
 
9
9
  Write API tests in YAML that read like documentation and generate OpenAPI specifications:
10
10
 
@@ -59,7 +59,7 @@ module SpecForge
59
59
  case function
60
60
  when "join"
61
61
  # Technically supports any attribute, but I ain't gonna test all them edge cases
62
- arguments[:positional].resolved.join
62
+ arguments[:positional].resolve.join
63
63
  end
64
64
  end
65
65
  end
@@ -17,6 +17,7 @@ module SpecForge
17
17
  #
18
18
  class Serve < Command
19
19
  include Docs::Generate
20
+
20
21
  #
21
22
  # Valid file formats for documentation output
22
23
  #
@@ -5,7 +5,7 @@ module SpecForge
5
5
  # Configuration container for SpecForge settings
6
6
  # Defines default values and validation for all configuration options
7
7
  #
8
- class Configuration < Struct.new(:base_url, :headers, :query, :factories, :on_debug)
8
+ class Configuration < Struct.new(:base_url, :headers, :query, :factories, :on_debug_proc)
9
9
  #
10
10
  # Manages factory configuration settings
11
11
  # Controls auto-discovery behavior and custom factory paths
@@ -44,7 +44,7 @@ module SpecForge
44
44
 
45
45
  config[:base_url] = "http://localhost:3000"
46
46
  config[:factories] = Factories.new
47
- config[:on_debug] = Runner::DebugProxy.default
47
+ config[:on_debug_proc] = Runner::DebugProxy.default
48
48
 
49
49
  super(**config)
50
50
  end
@@ -68,6 +68,15 @@ module SpecForge
68
68
  self
69
69
  end
70
70
 
71
+ def on_debug(&block)
72
+ self.on_debug_proc = block
73
+ end
74
+
75
+ def on_debug=(block)
76
+ warn("SpecForge::Configuration#on_debug= is deprecated. Use #on_debug instead")
77
+ self.on_debug_proc = block
78
+ end
79
+
71
80
  #
72
81
  # Recursively converts the configuration to a hash representation
73
82
  #
@@ -108,11 +117,6 @@ module SpecForge
108
117
  #
109
118
  # @return [Proc] The registered callback
110
119
  #
111
- # @example Registering a custom debug handler
112
- # SpecForge.configure do |config|
113
- # config.register_callback(:on_debug) { binding.pry }
114
- # end
115
- #
116
120
  # @example Cleaning database after each test
117
121
  # SpecForge.configure do |config|
118
122
  # config.register_callback(:after_expectation) do
@@ -26,7 +26,7 @@ module SpecForge
26
26
  # Required
27
27
  responses:,
28
28
  security:
29
- }.merge_compact(
29
+ }.compact_merge(
30
30
  # All optional
31
31
  tags:,
32
32
  summary:,
@@ -26,7 +26,7 @@ module SpecForge
26
26
  # Required
27
27
  description: "",
28
28
  content:
29
- }.merge_compact(
29
+ }.compact_merge(
30
30
  # Optional
31
31
  headers:
32
32
  )
@@ -166,6 +166,9 @@ module SpecForge
166
166
  # @private
167
167
  #
168
168
  def normalize_url(url, query)
169
+ # Strip leading slash so paths properly append to base URL
170
+ url = url.delete_prefix("/")
171
+
169
172
  # /users/<user_id>
170
173
  url = replace_url_placeholder(url, query, CURLY_PLACEHOLDER)
171
174
 
@@ -8,6 +8,8 @@ base_url:
8
8
  type: string
9
9
  default: null
10
10
  required: false
11
+ aliases:
12
+ - base_path
11
13
 
12
14
  url:
13
15
  type: string
@@ -19,5 +19,5 @@ factories:
19
19
  type: array
20
20
  default: []
21
21
 
22
- on_debug:
22
+ on_debug_proc:
23
23
  type: proc
@@ -152,8 +152,6 @@ module SpecForge
152
152
  ############################################################
153
153
  # JSON check
154
154
  if match_json.present?
155
- expect(response.body).to match_json_class
156
-
157
155
  case match_json
158
156
  when Hash
159
157
  match_json.each do |key, matcher|
@@ -30,7 +30,46 @@ module SpecForge
30
30
  # @return [Proc] The default debugging handler that outputs JSON state information
31
31
  #
32
32
  def self.default
33
- -> { puts inspect }
33
+ lambda do
34
+ puts <<~STRING
35
+
36
+ Debug triggered for:
37
+ > #{example.metadata[:rerun_file_path]} on line #{expectation.line_number}
38
+
39
+ Available debugging contexts:
40
+ - spec: Current spec details
41
+ - expectation: Current expectation being tested
42
+ - variables: Variables defined for this test
43
+ - global: Global context shared across tests
44
+ - store: Stored data from expectations
45
+
46
+ Request & Response:
47
+ - request: HTTP request details (method, url, headers, body)
48
+ - response: HTTP response with headers, status and body
49
+
50
+ Expectations:
51
+ - expected_status: Expected HTTP status code
52
+ - expected_json: Expected response body structure
53
+
54
+ Matchers:
55
+ - match_status: Matcher used to test status
56
+ - match_json: Matcher used to test response body
57
+
58
+ Helper objects:
59
+ - http_client: The HTTP client used for the request
60
+ - request_data: Raw request configuration data
61
+ - example_group: Current RSpec example group
62
+ - example: Current RSpec example
63
+ - forge: Current file being tested
64
+
65
+ ๐Ÿ’ก Pro tips:
66
+ - Type 'self' or 'inspect' for a pretty-printed JSON overview
67
+ - Use 'to_h' for the hash representation
68
+ - Access the shared context with 'SpecForge.context'
69
+ STRING
70
+
71
+ puts inspect
72
+ end
34
73
  end
35
74
 
36
75
  # @return [RSpec::Forge] The current Forge that is being tested
@@ -67,7 +106,7 @@ module SpecForge
67
106
  # @return [SpecForge::Runner::DebugProxy]
68
107
  #
69
108
  def initialize(forge, spec, expectation, example_group)
70
- @callback = SpecForge.configuration.on_debug
109
+ @callback = SpecForge.configuration.on_debug_proc
71
110
 
72
111
  @forge = forge
73
112
  @spec = spec
@@ -90,43 +129,6 @@ module SpecForge
90
129
  # @return [void]
91
130
  #
92
131
  def call
93
- puts <<~STRING
94
-
95
- Debug triggered for:
96
- > #{example.metadata[:rerun_file_path]} on line #{expectation.line_number}
97
-
98
- Available debugging contexts:
99
- - spec: Current spec details
100
- - expectation: Current expectation being tested
101
- - variables: Variables defined for this test
102
- - global: Global context shared across tests
103
- - store: Stored data from expectations
104
-
105
- Request & Response:
106
- - request: HTTP request details (method, url, headers, body)
107
- - response: HTTP response with headers, status and body
108
-
109
- Expectations:
110
- - expected_status: Expected HTTP status code
111
- - expected_json: Expected response body structure
112
-
113
- Matchers:
114
- - match_status: Matcher used to test status
115
- - match_json: Matcher used to test response body
116
-
117
- Helper objects:
118
- - http_client: The HTTP client used for the request
119
- - request_data: Raw request configuration data
120
- - example_group: Current RSpec example group
121
- - example: Current RSpec example
122
- - forge: Current file being tested
123
-
124
- ๐Ÿ’ก Pro tips:
125
- - Type 'self' or 'inspect' for a pretty-printed JSON overview
126
- - Use 'to_h' for the hash representation
127
- - Access the shared context with 'SpecForge.context'
128
- STRING
129
-
130
132
  instance_exec(&@callback)
131
133
  end
132
134
 
@@ -4,5 +4,5 @@ module SpecForge
4
4
  #
5
5
  # Current version of SpecForge
6
6
  #
7
- VERSION = "0.7.0"
7
+ VERSION = "0.7.1"
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spec_forge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-22 00:00:00.000000000 Z
11
+ date: 2025-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport