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 +4 -4
- data/CHANGELOG.md +65 -9
- data/README.md +2 -2
- data/lib/spec_forge/attribute/transform.rb +1 -1
- data/lib/spec_forge/cli/serve.rb +1 -0
- data/lib/spec_forge/configuration.rb +11 -7
- data/lib/spec_forge/documentation/openapi/v3_0/operation.rb +1 -1
- data/lib/spec_forge/documentation/openapi/v3_0/response.rb +1 -1
- data/lib/spec_forge/http/backend.rb +3 -0
- data/lib/spec_forge/normalizers/_shared.yml +2 -0
- data/lib/spec_forge/normalizers/configuration.yml +1 -1
- data/lib/spec_forge/runner/adapter.rb +0 -2
- data/lib/spec_forge/runner/debug_proxy.rb +41 -39
- data/lib/spec_forge/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9891353d8acd7d64ec4b2690e4e91d68c0d455913b8ca81c7f9e410859f51774
|
4
|
+
data.tar.gz: 7ff9aa712f7d21a75ae8a383175702ed8973b25e2935458bd75dd713f59b6fb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
54
|
-
|
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
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
179
|
-
|
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
|
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.
|
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
|
[](https://badge.fury.io/rb/spec_forge)
|
4
|
-

|
5
5
|
[](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.
|
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
|
|
data/lib/spec_forge/cli/serve.rb
CHANGED
@@ -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, :
|
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[:
|
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
|
@@ -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
|
|
@@ -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
|
-
|
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.
|
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
|
|
data/lib/spec_forge/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2025-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|