spec_forge 0.6.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 +174 -8
- data/README.md +135 -10
- data/flake.lock +3 -3
- data/flake.nix +3 -3
- data/lib/spec_forge/attribute/factory.rb +1 -1
- data/lib/spec_forge/attribute/transform.rb +1 -1
- data/lib/spec_forge/callbacks.rb +9 -0
- data/lib/spec_forge/cli/docs/generate.rb +72 -0
- data/lib/spec_forge/cli/docs.rb +92 -0
- data/lib/spec_forge/cli/init.rb +39 -7
- data/lib/spec_forge/cli/new.rb +13 -3
- data/lib/spec_forge/cli/run.rb +12 -4
- data/lib/spec_forge/cli/serve.rb +156 -0
- data/lib/spec_forge/cli.rb +14 -6
- data/lib/spec_forge/configuration.rb +13 -9
- data/lib/spec_forge/context/store.rb +23 -40
- data/lib/spec_forge/core_ext/array.rb +27 -0
- data/lib/spec_forge/documentation/builder.rb +383 -0
- data/lib/spec_forge/documentation/document/operation.rb +47 -0
- data/lib/spec_forge/documentation/document/parameter.rb +22 -0
- data/lib/spec_forge/documentation/document/request_body.rb +24 -0
- data/lib/spec_forge/documentation/document/response.rb +39 -0
- data/lib/spec_forge/documentation/document/response_body.rb +27 -0
- data/lib/spec_forge/documentation/document.rb +48 -0
- data/lib/spec_forge/documentation/generators/base.rb +81 -0
- data/lib/spec_forge/documentation/generators/openapi/base.rb +100 -0
- data/lib/spec_forge/documentation/generators/openapi/error_formatter.rb +149 -0
- data/lib/spec_forge/documentation/generators/openapi/v3_0.rb +65 -0
- data/lib/spec_forge/documentation/generators/openapi.rb +59 -0
- data/lib/spec_forge/documentation/generators.rb +17 -0
- data/lib/spec_forge/documentation/loader/cache.rb +138 -0
- data/lib/spec_forge/documentation/loader.rb +159 -0
- data/lib/spec_forge/documentation/openapi/base.rb +33 -0
- data/lib/spec_forge/documentation/openapi/v3_0/example.rb +44 -0
- data/lib/spec_forge/documentation/openapi/v3_0/media_type.rb +42 -0
- data/lib/spec_forge/documentation/openapi/v3_0/operation.rb +175 -0
- data/lib/spec_forge/documentation/openapi/v3_0/response.rb +65 -0
- data/lib/spec_forge/documentation/openapi/v3_0/schema.rb +80 -0
- data/lib/spec_forge/documentation/openapi/v3_0/tag.rb +71 -0
- data/lib/spec_forge/documentation/openapi.rb +23 -0
- data/lib/spec_forge/documentation.rb +27 -0
- data/lib/spec_forge/error.rb +17 -0
- data/lib/spec_forge/factory.rb +2 -2
- data/lib/spec_forge/filter.rb +3 -4
- data/lib/spec_forge/forge.rb +5 -4
- data/lib/spec_forge/http/backend.rb +5 -0
- data/lib/spec_forge/http/request.rb +14 -3
- data/lib/spec_forge/loader.rb +14 -24
- data/lib/spec_forge/normalizer/default.rb +51 -0
- data/lib/spec_forge/normalizer/definition.rb +248 -0
- data/lib/spec_forge/normalizer/validators.rb +99 -0
- data/lib/spec_forge/normalizer.rb +356 -199
- data/lib/spec_forge/normalizers/_shared.yml +76 -0
- data/lib/spec_forge/normalizers/configuration.yml +23 -0
- data/lib/spec_forge/normalizers/constraint.yml +8 -0
- data/lib/spec_forge/normalizers/expectation.yml +47 -0
- data/lib/spec_forge/normalizers/factory.yml +12 -0
- data/lib/spec_forge/normalizers/factory_reference.yml +15 -0
- data/lib/spec_forge/normalizers/global_context.yml +28 -0
- data/lib/spec_forge/normalizers/spec.yml +50 -0
- data/lib/spec_forge/runner/adapter.rb +181 -0
- data/lib/spec_forge/runner/debug_proxy.rb +44 -42
- data/lib/spec_forge/runner/state.rb +4 -5
- data/lib/spec_forge/runner.rb +40 -124
- data/lib/spec_forge/spec/expectation/constraint.rb +13 -5
- data/lib/spec_forge/spec/expectation.rb +7 -3
- data/lib/spec_forge/spec.rb +13 -58
- data/lib/spec_forge/version.rb +1 -1
- data/lib/spec_forge.rb +30 -23
- data/lib/templates/openapi.yml.tt +22 -0
- data/lib/templates/redoc.html.tt +28 -0
- data/lib/templates/swagger.html.tt +59 -0
- metadata +92 -14
- data/lib/spec_forge/normalizer/configuration.rb +0 -90
- data/lib/spec_forge/normalizer/constraint.rb +0 -60
- data/lib/spec_forge/normalizer/expectation.rb +0 -105
- data/lib/spec_forge/normalizer/factory.rb +0 -78
- data/lib/spec_forge/normalizer/factory_reference.rb +0 -85
- data/lib/spec_forge/normalizer/global_context.rb +0 -88
- data/lib/spec_forge/normalizer/spec.rb +0 -97
- /data/lib/templates/{forge_helper.tt → forge_helper.rb.tt} +0 -0
- /data/lib/templates/{new_factory.tt → new_factory.yml.tt} +0 -0
- /data/lib/templates/{new_spec.tt → new_spec.yml.tt} +0 -0
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,7 +15,159 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
15
15
|
### Removed
|
16
16
|
-->
|
17
17
|
|
18
|
-
## [
|
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
|
+
|
51
|
+
## [0.7.0] - 12025-06-22
|
52
|
+
|
53
|
+
### Added
|
54
|
+
|
55
|
+
#### 🚀 Documentation-First Architecture
|
56
|
+
|
57
|
+
**The Big Picture**: SpecForge now generates OpenAPI documentation from your tests automatically!
|
58
|
+
|
59
|
+
- **Primary Documentation Workflow**: New `docs` command (now the default!) generates OpenAPI specs from test execution
|
60
|
+
|
61
|
+
- Smart caching system with `--fresh` flag for forced regeneration
|
62
|
+
- Multiple output formats: YAML (default) or JSON via `--format`
|
63
|
+
- Custom output paths with `--output` option
|
64
|
+
- Built-in OpenAPI 3.0.4 validation with detailed, helpful error messages
|
65
|
+
- Optional validation skip with `--skip-validation` for faster iterations
|
66
|
+
|
67
|
+
- **Live Documentation Server**: `spec_forge serve` command for immediate feedback
|
68
|
+
|
69
|
+
- Local web server with Swagger UI (default) or Redoc (`--ui redoc`)
|
70
|
+
- Configurable port with `--port` (defaults to 8080)
|
71
|
+
- Auto-generated HTML templates for both UI options
|
72
|
+
- Perfect for development and API review workflows
|
73
|
+
|
74
|
+
- **Flexible Configuration System**:
|
75
|
+
- Directory-based config: `config/components/`, `config/paths/`, etc.
|
76
|
+
- Template-based initialization with sensible defaults
|
77
|
+
- Enhanced YAML merging with `$ref` support
|
78
|
+
- Full OpenAPI customization through configuration files
|
79
|
+
|
80
|
+
#### 🧪 Enhanced Testing Capabilities
|
81
|
+
|
82
|
+
- **HTTP Header Testing**: Comprehensive header validation
|
83
|
+
|
84
|
+
```yaml
|
85
|
+
headers:
|
86
|
+
Content-Type: "application/json"
|
87
|
+
X-Request-ID: /^[0-9a-f-]{36}$/
|
88
|
+
Cache-Control:
|
89
|
+
matcher.and:
|
90
|
+
- matcher.include: "max-age="
|
91
|
+
- matcher.include: "private"
|
92
|
+
```
|
93
|
+
|
94
|
+
- **Flexible Store System**: Store anything, access everything
|
95
|
+
|
96
|
+
- OpenStruct-based entries for maximum flexibility
|
97
|
+
- Custom data via callbacks (config, metadata, computed values)
|
98
|
+
- Same familiar `store.id.attribute` syntax
|
99
|
+
- Perfect for complex test scenarios and feature flags
|
100
|
+
|
101
|
+
- **Documentation Control**: Fine-grained control over what gets documented
|
102
|
+
- New `documentation: true/false` attribute for specs and expectations
|
103
|
+
- Exclude test-only scenarios from API docs while keeping functionality
|
104
|
+
|
105
|
+
#### ⚙️ Architecture Improvements
|
106
|
+
|
107
|
+
- **YAML-Driven Normalizers**: Configuration over code
|
108
|
+
|
109
|
+
- Structure definitions in `lib/spec_forge/normalizers/*.yml`
|
110
|
+
- Powerful `reference:` system for reusable components
|
111
|
+
- Wildcard support (`*`) for catch-all schemas
|
112
|
+
- Centralized validation logic in dedicated module
|
113
|
+
|
114
|
+
- **Enhanced CLI Experience**:
|
115
|
+
|
116
|
+
- Improved `init` command with `--skip-openapi` and `--skip-factories` flags
|
117
|
+
- Better help text and examples throughout
|
118
|
+
- Clearer error messages with actionable context
|
119
|
+
|
120
|
+
- **Developer Utilities**:
|
121
|
+
- `Array#to_merged_h` for cleaner hash merging
|
122
|
+
- Unified `.normalize!(input, using:)` API across normalizers
|
123
|
+
- Separated test preparation (`Runner.prepare`) from execution
|
124
|
+
|
125
|
+
### Changed
|
126
|
+
|
127
|
+
#### 🎯 User Experience Overhaul
|
128
|
+
|
129
|
+
- **New Default Behavior**: `spec_forge` without arguments now shows help instead of running tests
|
130
|
+
|
131
|
+
- **Breaking Change**: Use `spec_forge docs` for documentation or `spec_forge run` for test-only execution
|
132
|
+
- Safer default that guides users to the right command for their needs
|
133
|
+
|
134
|
+
- **Streamlined Commands**:
|
135
|
+
- Better command organization and help text
|
136
|
+
- Consistent flag naming across commands
|
137
|
+
- Enhanced error handling with helpful suggestions
|
138
|
+
|
139
|
+
#### 🏗️ Internal Refactoring
|
140
|
+
|
141
|
+
- **Normalizer Architecture**: YAML-based instead of class-heavy approach
|
142
|
+
|
143
|
+
- Consolidated shared definitions in `_shared.yml`
|
144
|
+
- Easier maintenance and extension
|
145
|
+
- Better error context with attribute path tracking
|
146
|
+
|
147
|
+
- **Test Execution Pipeline**:
|
148
|
+
|
149
|
+
- Clean separation between test preparation and execution
|
150
|
+
- Enhanced RSpec adapter pattern
|
151
|
+
- Better reusability for documentation generation
|
152
|
+
|
153
|
+
- **HTTP & Store Improvements**:
|
154
|
+
- Automatic header value string conversion
|
155
|
+
- Simplified store entry structure with OpenStruct flexibility
|
156
|
+
- Enhanced request/response handling
|
157
|
+
|
158
|
+
### Removed
|
159
|
+
|
160
|
+
- **Legacy Architecture**: Individual normalizer class files (replaced with YAML config)
|
161
|
+
|
162
|
+
---
|
163
|
+
|
164
|
+
**Migration Notes**:
|
165
|
+
|
166
|
+
- Update any scripts using bare `spec_forge` - now shows help instead of running tests
|
167
|
+
- Use `spec_forge docs` for documentation generation or `spec_forge run` for testing
|
168
|
+
- Store access patterns remain the same, but internal structure is more flexible
|
169
|
+
|
170
|
+
## [0.6.0] - 12025-03-25
|
19
171
|
|
20
172
|
### Added
|
21
173
|
|
@@ -26,6 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
26
178
|
- `Context::Variables` for managing variables with overlay support
|
27
179
|
- `Context::Store` for storing the results of the tests
|
28
180
|
- Added support for defining and referencing global variables
|
181
|
+
|
29
182
|
```yaml
|
30
183
|
global:
|
31
184
|
variables:
|
@@ -37,13 +190,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
37
190
|
query:
|
38
191
|
api_version: "global.variables.api_version"
|
39
192
|
```
|
193
|
+
|
40
194
|
- Added compound matcher support via `matcher.and` for combining multiple matchers
|
41
195
|
```yaml
|
42
196
|
email:
|
43
197
|
matcher.and:
|
44
|
-
|
45
|
-
|
46
|
-
|
198
|
+
- kind_of.string
|
199
|
+
- /@/
|
200
|
+
- matcher.end_with: ".com"
|
47
201
|
```
|
48
202
|
- Added custom RSpec matcher `have_size` for checking an object's size via `matcher.have_size`
|
49
203
|
- Added new `Loader` class for improved spec file processing
|
@@ -51,6 +205,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
51
205
|
- Added normalizer for global context validation
|
52
206
|
- Added line number tracking for specs and expectations
|
53
207
|
- Added support for defining and referencing callbacks
|
208
|
+
|
54
209
|
```ruby
|
55
210
|
# Configuration level
|
56
211
|
SpecForge.configure do |config|
|
@@ -63,14 +218,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
63
218
|
# Module level (no aliases)
|
64
219
|
SpecForge.register_callback("callback_name") { |context| }
|
65
220
|
```
|
221
|
+
|
66
222
|
Once defined, callbacks can be referenced in spec files via the global context
|
223
|
+
|
67
224
|
```yaml
|
68
225
|
global:
|
69
226
|
callbacks:
|
70
|
-
|
71
|
-
|
227
|
+
- before: callback_name
|
228
|
+
after: cleanup_database_state
|
72
229
|
```
|
230
|
+
|
73
231
|
- Added support for storing and retrieving test data via the `store_as` directive and `store` attribute
|
232
|
+
|
74
233
|
```yaml
|
75
234
|
create_user:
|
76
235
|
path: "/users"
|
@@ -90,6 +249,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
90
249
|
- expect:
|
91
250
|
status: 200
|
92
251
|
```
|
252
|
+
|
93
253
|
- Added `UndefinedMatcherError` for clearer error messaging when invalid matchers are used
|
94
254
|
- Enhanced debugging capabilities with improved DebugProxy methods and store access
|
95
255
|
- Added HTTP status descriptions for better error messages
|
@@ -140,7 +300,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
140
300
|
variables:
|
141
301
|
users:
|
142
302
|
factory.user:
|
143
|
-
size: 10
|
303
|
+
size: 10 # Creates 10 user records
|
144
304
|
```
|
145
305
|
- All FactoryBot list methods now supported:
|
146
306
|
- `create_list` (default)
|
@@ -199,6 +359,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
199
359
|
### Added
|
200
360
|
|
201
361
|
- Core Infrastructure
|
362
|
+
|
202
363
|
- Configuration management
|
203
364
|
- User input validation and normalization
|
204
365
|
- Factory registration
|
@@ -208,11 +369,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
208
369
|
- Debugging tooling
|
209
370
|
|
210
371
|
- CLI
|
372
|
+
|
211
373
|
- Project initialization (`init`)
|
212
374
|
- Spec/factory generation (`new`)
|
213
375
|
- Test execution (`run`)
|
214
376
|
|
215
377
|
- Attributes
|
378
|
+
|
216
379
|
- Chainable attribute handling (through `Chainable`)
|
217
380
|
- Expanded attribute handling (through `Parameterized`)
|
218
381
|
- Factory (with chainable support) - `factories.`
|
@@ -231,7 +394,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
231
394
|
|
232
395
|
- Initial commit
|
233
396
|
|
234
|
-
[unreleased]: https://github.com/itsthedevman/spec_forge/compare/v0.
|
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
|
399
|
+
[0.7.0]: https://github.com/itsthedevman/spec_forge/compare/v0.6.0...v0.7.0
|
400
|
+
[0.6.0]: https://github.com/itsthedevman/spec_forge/compare/v0.5.0...v0.6.0
|
235
401
|
[0.5.0]: https://github.com/itsthedevman/spec_forge/compare/v0.4.0...v0.5.0
|
236
402
|
[0.4.0]: https://github.com/itsthedevman/spec_forge/compare/v0.3.2...v0.4.0
|
237
403
|
[0.3.2]: https://github.com/itsthedevman/spec_forge/compare/v0.3.0...v0.3.2
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
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
|
-
Write API tests in YAML that read like documentation:
|
9
|
+
Write API tests in YAML that read like documentation and generate OpenAPI specifications:
|
10
10
|
|
11
11
|
```yaml
|
12
12
|
show_user:
|
@@ -25,22 +25,39 @@ show_user:
|
|
25
25
|
matcher.and:
|
26
26
|
- kind_of.string
|
27
27
|
- /@/
|
28
|
+
headers:
|
29
|
+
Content-Type: "application/json"
|
30
|
+
X-Request-ID: /^[0-9a-f-]{36}$/
|
28
31
|
```
|
29
32
|
|
30
|
-
That's a complete test. No Ruby code, no configuration files, no HTTP client setup - just
|
33
|
+
That's a complete test that validates your API and creates OpenAPI documentation. No Ruby code, no configuration files, no HTTP client setup - just clear, executable specifications.
|
31
34
|
|
32
35
|
## Why SpecForge?
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
**For Testing:**
|
38
|
+
|
39
|
+
- **Reduce Boilerplate**: Write tests without repetitive setup code and HTTP configuration
|
40
|
+
- **Quick Setup**: Start testing APIs in minutes instead of spending hours on test infrastructure
|
41
|
+
- **Clear Syntax**: Tests that everyone can read and understand, regardless of Ruby expertise
|
42
|
+
|
43
|
+
**For Documentation:**
|
44
|
+
|
45
|
+
- **OpenAPI Generation**: Generate OpenAPI specifications from your test structure, with full customization through configuration files
|
46
|
+
- **Living Documentation**: Your tests ensure the documentation always matches your actual API behavior
|
47
|
+
- **Professional Output**: View your API docs in Swagger UI or Redoc with minimal setup
|
48
|
+
|
49
|
+
**For Teams:**
|
50
|
+
|
51
|
+
- **Developer & QA Collaboration**: Create specifications that both developers and QA can maintain
|
52
|
+
- **Gradual Adoption**: Use alongside your existing test suite, introducing it incrementally where it makes sense
|
39
53
|
|
40
54
|
## Key Features
|
41
55
|
|
56
|
+
- **Automatic Documentation Generation**: Transform tests into OpenAPI specifications with customizable configuration
|
57
|
+
- **Live Documentation Server**: Local development server for viewing generated documentation
|
42
58
|
- **YAML-Based Tests**: Write clear, declarative tests that read like documentation
|
43
59
|
- **RSpec Integration**: Leverage all the power of RSpec matchers and expectations
|
60
|
+
- **Header Testing**: Comprehensive HTTP header validation with compound matchers
|
44
61
|
- **FactoryBot Integration**: Generate test data with FactoryBot integration
|
45
62
|
- **Faker Integration**: Create realistic test data with Faker
|
46
63
|
- **Variable System**: Define and reference variables for dynamic test data
|
@@ -49,6 +66,23 @@ That's a complete test. No Ruby code, no configuration files, no HTTP client set
|
|
49
66
|
- **Global Variables**: Define shared configuration at the file level
|
50
67
|
- **Callback System**: Hook into the test lifecycle using Ruby for setup, teardown, and much more!
|
51
68
|
|
69
|
+
## Quick Start
|
70
|
+
|
71
|
+
Get started with SpecForge in 3 commands:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
# 1. Initialize SpecForge
|
75
|
+
spec_forge init
|
76
|
+
|
77
|
+
# 2. Create your first test
|
78
|
+
spec_forge new spec users
|
79
|
+
|
80
|
+
# 3. View your documentation
|
81
|
+
spec_forge serve
|
82
|
+
```
|
83
|
+
|
84
|
+
Then visit `http://localhost:8080` to see your API documentation!
|
85
|
+
|
52
86
|
## When Not to Use SpecForge
|
53
87
|
|
54
88
|
Consider alternatives when you need:
|
@@ -92,12 +126,103 @@ Create your first test:
|
|
92
126
|
spec_forge new spec users
|
93
127
|
```
|
94
128
|
|
95
|
-
|
129
|
+
Generate documentation (default command):
|
130
|
+
|
131
|
+
```bash
|
132
|
+
spec_forge
|
133
|
+
```
|
134
|
+
|
135
|
+
Or start the live documentation server:
|
136
|
+
|
137
|
+
```bash
|
138
|
+
spec_forge serve
|
139
|
+
```
|
140
|
+
|
141
|
+
Run tests only (no documentation):
|
96
142
|
|
97
143
|
```bash
|
98
144
|
spec_forge run
|
99
145
|
```
|
100
146
|
|
147
|
+
## Documentation Workflow
|
148
|
+
|
149
|
+
SpecForge provides multiple ways to work with your API documentation:
|
150
|
+
|
151
|
+
```bash
|
152
|
+
# Generate OpenAPI specifications
|
153
|
+
spec_forge docs # Smart caching
|
154
|
+
spec_forge docs --fresh # Force regeneration
|
155
|
+
spec_forge docs --format json # Output as JSON instead of YAML
|
156
|
+
|
157
|
+
# View documentation in browser
|
158
|
+
spec_forge serve # Generate if needed + serve
|
159
|
+
spec_forge serve --fresh # Force regeneration + serve
|
160
|
+
spec_forge serve --ui redoc # Use Redoc instead
|
161
|
+
spec_forge serve --port 3001 # Custom port
|
162
|
+
|
163
|
+
# Traditional testing
|
164
|
+
spec_forge run # Pure testing mode
|
165
|
+
spec_forge run users:show_user # Run specific tests
|
166
|
+
```
|
167
|
+
|
168
|
+
## Example: Complete User API
|
169
|
+
|
170
|
+
```yaml
|
171
|
+
# spec_forge/specs/users.yml
|
172
|
+
global:
|
173
|
+
variables:
|
174
|
+
admin_role: "admin"
|
175
|
+
|
176
|
+
list_users:
|
177
|
+
path: /users
|
178
|
+
expectations:
|
179
|
+
- expect:
|
180
|
+
status: 200
|
181
|
+
headers:
|
182
|
+
Content-Type: "application/json"
|
183
|
+
json:
|
184
|
+
users:
|
185
|
+
matcher.have_size:
|
186
|
+
be.greater_than: 0
|
187
|
+
|
188
|
+
create_user:
|
189
|
+
path: /users
|
190
|
+
method: POST
|
191
|
+
variables:
|
192
|
+
username: faker.internet.username
|
193
|
+
email: faker.internet.email
|
194
|
+
body:
|
195
|
+
name: variables.username
|
196
|
+
email: variables.email
|
197
|
+
role: global.variables.admin_role
|
198
|
+
store_as: new_user
|
199
|
+
expectations:
|
200
|
+
- expect:
|
201
|
+
status: 201
|
202
|
+
headers:
|
203
|
+
Location: /\/users\/\d+/
|
204
|
+
json:
|
205
|
+
id: kind_of.integer
|
206
|
+
name: variables.username
|
207
|
+
email: variables.email
|
208
|
+
role: global.variables.admin_role
|
209
|
+
|
210
|
+
show_user:
|
211
|
+
path: /users/{id}
|
212
|
+
query:
|
213
|
+
id: store.new_user.body.id
|
214
|
+
expectations:
|
215
|
+
- expect:
|
216
|
+
status: 200
|
217
|
+
json:
|
218
|
+
id: store.new_user.body.id
|
219
|
+
name: store.new_user.body.name
|
220
|
+
email: store.new_user.body.email
|
221
|
+
role: global.variables.admin_role
|
222
|
+
```
|
223
|
+
|
224
|
+
This automatically generates a complete OpenAPI specification with all endpoints, request/response schemas, and examples!
|
225
|
+
|
101
226
|
## Documentation
|
102
227
|
|
103
228
|
For comprehensive documentation, visit the [SpecForge Wiki](https://github.com/itsthedevman/spec_forge/wiki) which includes:
|
data/flake.lock
CHANGED
@@ -20,11 +20,11 @@
|
|
20
20
|
},
|
21
21
|
"nixpkgs": {
|
22
22
|
"locked": {
|
23
|
-
"lastModified":
|
24
|
-
"narHash": "sha256-
|
23
|
+
"lastModified": 1750365781,
|
24
|
+
"narHash": "sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50=",
|
25
25
|
"owner": "NixOS",
|
26
26
|
"repo": "nixpkgs",
|
27
|
-
"rev": "
|
27
|
+
"rev": "08f22084e6085d19bcfb4be30d1ca76ecb96fe54",
|
28
28
|
"type": "github"
|
29
29
|
},
|
30
30
|
"original": {
|
data/flake.nix
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
description = "Ruby 3.
|
2
|
+
description = "Ruby 3.2 development environment";
|
3
3
|
|
4
4
|
inputs = {
|
5
5
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
@@ -20,8 +20,8 @@
|
|
20
20
|
{
|
21
21
|
devShells.default = pkgs.mkShell {
|
22
22
|
buildInputs = with pkgs; [
|
23
|
-
(
|
24
|
-
jemallocSupport =
|
23
|
+
(ruby_3_2.override {
|
24
|
+
jemallocSupport = false;
|
25
25
|
docSupport = false;
|
26
26
|
})
|
27
27
|
|
@@ -80,7 +80,7 @@ module SpecForge
|
|
80
80
|
super
|
81
81
|
|
82
82
|
# Check the arguments before preparing them
|
83
|
-
arguments[:keyword] = Normalizer.
|
83
|
+
arguments[:keyword] = Normalizer.normalize!(arguments[:keyword], using: :factory_reference)
|
84
84
|
|
85
85
|
prepare_arguments!
|
86
86
|
end
|
data/lib/spec_forge/callbacks.rb
CHANGED
@@ -36,6 +36,15 @@ module SpecForge
|
|
36
36
|
instance[name.to_s] = block
|
37
37
|
end
|
38
38
|
|
39
|
+
#
|
40
|
+
# Deregisters a callback
|
41
|
+
#
|
42
|
+
# @param name [String, Symbol] The name of the callback
|
43
|
+
#
|
44
|
+
def deregister(name)
|
45
|
+
instance.delete(name.to_s)
|
46
|
+
end
|
47
|
+
|
39
48
|
#
|
40
49
|
# Checks if a callback is registered for the given event
|
41
50
|
#
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SpecForge
|
4
|
+
class CLI
|
5
|
+
class Docs < Command
|
6
|
+
#
|
7
|
+
# Shared functionality for generating OpenAPI documentation
|
8
|
+
#
|
9
|
+
# This module contains the core logic for running tests, extracting endpoint
|
10
|
+
# data, and generating OpenAPI specifications. It's used by both the Docs
|
11
|
+
# and Serve commands to avoid duplication.
|
12
|
+
#
|
13
|
+
module Generate
|
14
|
+
#
|
15
|
+
# Generates OpenAPI documentation and writes it to disk
|
16
|
+
#
|
17
|
+
# Runs the documentation generation pipeline: executes tests, extracts
|
18
|
+
# endpoint data, generates OpenAPI spec, validates it, and writes the
|
19
|
+
# output file in the specified format.
|
20
|
+
#
|
21
|
+
# @return [Pathname] The path to the generated documentation file
|
22
|
+
#
|
23
|
+
def generate_documentation
|
24
|
+
generator = Documentation::Generators::OpenAPI["3.0"]
|
25
|
+
output = generator.generate(use_cache: !options.fresh)
|
26
|
+
|
27
|
+
generator.validate!(output) unless options.skip_validation
|
28
|
+
|
29
|
+
# Determine output format and path
|
30
|
+
file_format = determine_file_format
|
31
|
+
file_path = determine_output_path(file_format)
|
32
|
+
|
33
|
+
content =
|
34
|
+
if file_format == "json"
|
35
|
+
JSON.pretty_generate(output)
|
36
|
+
else
|
37
|
+
output.to_yaml(stringify_names: true)
|
38
|
+
end
|
39
|
+
|
40
|
+
::File.write(file_path, content)
|
41
|
+
|
42
|
+
file_path
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def determine_file_format
|
48
|
+
file_format = options.format&.downcase || "yml"
|
49
|
+
validate_format!(file_format)
|
50
|
+
|
51
|
+
file_format
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_format!(format)
|
55
|
+
return if VALID_FORMATS.include?(format)
|
56
|
+
|
57
|
+
raise ArgumentError,
|
58
|
+
"Invalid format #{format.in_quotes}. Valid formats: #{VALID_FORMATS.join_map(", ", &:in_quotes)}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def determine_output_path(format)
|
62
|
+
if options.output
|
63
|
+
Pathname.new(options.output)
|
64
|
+
else
|
65
|
+
extension = (format == "json") ? "json" : "yml"
|
66
|
+
SpecForge.openapi_path.join("generated", "openapi.#{extension}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|