spec_forge 0.5.0 → 0.7.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 +4 -4
- data/.standard.yml +3 -3
- data/CHANGELOG.md +217 -2
- data/README.md +162 -25
- data/flake.lock +3 -3
- data/flake.nix +11 -5
- data/lib/spec_forge/attribute/chainable.rb +208 -20
- data/lib/spec_forge/attribute/factory.rb +92 -15
- data/lib/spec_forge/attribute/faker.rb +62 -13
- data/lib/spec_forge/attribute/global.rb +96 -0
- data/lib/spec_forge/attribute/literal.rb +15 -2
- data/lib/spec_forge/attribute/matcher.rb +186 -11
- data/lib/spec_forge/attribute/parameterized.rb +45 -12
- data/lib/spec_forge/attribute/regex.rb +55 -5
- data/lib/spec_forge/attribute/resolvable.rb +48 -5
- data/lib/spec_forge/attribute/resolvable_array.rb +62 -4
- data/lib/spec_forge/attribute/resolvable_hash.rb +62 -4
- data/lib/spec_forge/attribute/store.rb +65 -0
- data/lib/spec_forge/attribute/transform.rb +33 -5
- data/lib/spec_forge/attribute/variable.rb +37 -6
- data/lib/spec_forge/attribute.rb +166 -66
- data/lib/spec_forge/backtrace_formatter.rb +26 -3
- data/lib/spec_forge/callbacks.rb +88 -0
- data/lib/spec_forge/cli/actions.rb +27 -0
- data/lib/spec_forge/cli/command.rb +78 -24
- 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 +51 -9
- data/lib/spec_forge/cli/new.rb +67 -6
- data/lib/spec_forge/cli/run.rb +32 -4
- data/lib/spec_forge/cli/serve.rb +155 -0
- data/lib/spec_forge/cli.rb +26 -7
- data/lib/spec_forge/configuration.rb +96 -24
- data/lib/spec_forge/context/callbacks.rb +91 -0
- data/lib/spec_forge/context/global.rb +72 -0
- data/lib/spec_forge/context/store.rb +131 -0
- data/lib/spec_forge/context/variables.rb +91 -0
- data/lib/spec_forge/context.rb +36 -0
- data/lib/spec_forge/core_ext/array.rb +27 -0
- data/lib/spec_forge/core_ext/rspec.rb +22 -4
- 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 +284 -113
- data/lib/spec_forge/factory.rb +35 -16
- data/lib/spec_forge/filter.rb +86 -0
- data/lib/spec_forge/forge.rb +171 -0
- data/lib/spec_forge/http/backend.rb +101 -29
- data/lib/spec_forge/http/client.rb +23 -13
- data/lib/spec_forge/http/request.rb +85 -62
- data/lib/spec_forge/http/verb.rb +79 -0
- data/lib/spec_forge/http.rb +105 -0
- data/lib/spec_forge/loader.rb +244 -0
- data/lib/spec_forge/matchers.rb +130 -0
- 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 +486 -115
- data/lib/spec_forge/normalizers/_shared.yml +74 -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 +183 -0
- data/lib/spec_forge/runner/callbacks.rb +246 -0
- data/lib/spec_forge/runner/debug_proxy.rb +213 -0
- data/lib/spec_forge/runner/listener.rb +54 -0
- data/lib/spec_forge/runner/metadata.rb +58 -0
- data/lib/spec_forge/runner/state.rb +98 -0
- data/lib/spec_forge/runner.rb +50 -125
- data/lib/spec_forge/spec/expectation/constraint.rb +100 -21
- data/lib/spec_forge/spec/expectation.rb +47 -51
- data/lib/spec_forge/spec.rb +50 -108
- data/lib/spec_forge/type.rb +36 -4
- data/lib/spec_forge/version.rb +4 -1
- data/lib/spec_forge.rb +168 -76
- 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 +109 -16
- data/lib/spec_forge/normalizer/configuration.rb +0 -77
- data/lib/spec_forge/normalizer/constraint.rb +0 -47
- data/lib/spec_forge/normalizer/expectation.rb +0 -86
- data/lib/spec_forge/normalizer/factory.rb +0 -65
- data/lib/spec_forge/normalizer/factory_reference.rb +0 -71
- data/lib/spec_forge/normalizer/spec.rb +0 -74
- data/spec_forge/factories/user.yml +0 -4
- data/spec_forge/forge_helper.rb +0 -48
- data/spec_forge/specs/users.yml +0 -65
- /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
data/lib/spec_forge.rb
CHANGED
@@ -5,103 +5,195 @@ require "logger"
|
|
5
5
|
require "active_support"
|
6
6
|
require "active_support/core_ext"
|
7
7
|
require "commander"
|
8
|
-
require "everythingrb"
|
8
|
+
require "everythingrb/prelude"
|
9
|
+
require "everythingrb/all"
|
9
10
|
require "factory_bot"
|
10
11
|
require "faker"
|
11
12
|
require "faraday"
|
12
13
|
require "mime/types"
|
14
|
+
require "openapi3_parser"
|
13
15
|
require "pathname"
|
14
16
|
require "rspec"
|
17
|
+
require "sem_version"
|
15
18
|
require "singleton"
|
16
19
|
require "thor"
|
20
|
+
require "webrick"
|
17
21
|
require "yaml"
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
#
|
24
|
+
# SpecForge: Write expressive API tests in YAML with the power of RSpec matchers
|
25
|
+
#
|
26
|
+
# SpecForge is a testing framework that allows writing API tests in a YAML format
|
27
|
+
# that reads like documentation. It combines the readability of YAML with the
|
28
|
+
# power of RSpec matchers, Faker data generation, and FactoryBot test objects.
|
29
|
+
#
|
30
|
+
# @example Basic spec in YAML
|
31
|
+
# get_user:
|
32
|
+
# path: /users/1
|
33
|
+
# expectations:
|
34
|
+
# - expect:
|
35
|
+
# status: 200
|
36
|
+
# json:
|
37
|
+
# name: kind_of.string
|
38
|
+
# email: /@/
|
39
|
+
#
|
40
|
+
# @example Running specs
|
41
|
+
# # Run all specs
|
42
|
+
# SpecForge.run
|
43
|
+
#
|
44
|
+
# # Run specific file
|
45
|
+
# SpecForge.run(file_name: "users")
|
46
|
+
#
|
47
|
+
# # Run specific spec
|
48
|
+
# SpecForge.run(file_name: "users", spec_name: "create_user")
|
49
|
+
#
|
33
50
|
module SpecForge
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
51
|
+
class << self
|
52
|
+
#
|
53
|
+
# Loads all factories and specs and runs the tests with optional filtering
|
54
|
+
#
|
55
|
+
# This is the main entry point for running SpecForge tests. It loads the
|
56
|
+
# forge_helper.rb file if it exists, configures the environment, loads
|
57
|
+
# factories and specs, and runs the tests through RSpec.
|
58
|
+
#
|
59
|
+
# @param file_name [String, nil] Optional name of spec file to run
|
60
|
+
# @param spec_name [String, nil] Optional name of spec to run
|
61
|
+
# @param expectation_name [String, nil] Optional name of expectation to run
|
62
|
+
#
|
63
|
+
def run(file_name: nil, spec_name: nil, expectation_name: nil)
|
64
|
+
forges = Runner.prepare(file_name:, spec_name:, expectation_name:)
|
65
|
+
Runner.run(forges, exit_on_finish: true)
|
66
|
+
end
|
41
67
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
68
|
+
#
|
69
|
+
# Returns the directory root for the working directory
|
70
|
+
#
|
71
|
+
# @return [Pathname] The root directory path
|
72
|
+
#
|
73
|
+
def root
|
74
|
+
@root ||= Pathname.pwd
|
75
|
+
end
|
45
76
|
|
46
|
-
#
|
47
|
-
|
77
|
+
#
|
78
|
+
# Returns SpecForge's working directory
|
79
|
+
#
|
80
|
+
# @return [Pathname] The spec_forge directory path
|
81
|
+
#
|
82
|
+
def forge_path
|
83
|
+
@forge_path ||= root.join("spec_forge")
|
84
|
+
end
|
48
85
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
86
|
+
#
|
87
|
+
# Returns SpecForge's openapi directory
|
88
|
+
#
|
89
|
+
# @return [Pathname] The spec_forge openapi directory path
|
90
|
+
#
|
91
|
+
def openapi_path
|
92
|
+
@openapi_path ||= forge_path.join("openapi")
|
93
|
+
end
|
52
94
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
95
|
+
#
|
96
|
+
# Returns SpecForge's configuration
|
97
|
+
#
|
98
|
+
# @return [Configuration] The current configuration
|
99
|
+
#
|
100
|
+
def configuration
|
101
|
+
@configuration ||= Configuration.new
|
102
|
+
end
|
56
103
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@
|
64
|
-
|
104
|
+
#
|
105
|
+
# Yields SpecForge's configuration to a block for modification
|
106
|
+
#
|
107
|
+
# @yield [config] Block that receives the configuration object
|
108
|
+
# @yieldparam config [Configuration] The configuration to modify
|
109
|
+
#
|
110
|
+
# @return [Configuration] The updated configuration
|
111
|
+
#
|
112
|
+
def configure(&block)
|
113
|
+
block&.call(configuration)
|
114
|
+
configuration
|
115
|
+
end
|
65
116
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@
|
73
|
-
|
117
|
+
#
|
118
|
+
# Returns a backtrace cleaner configured for SpecForge
|
119
|
+
#
|
120
|
+
# Creates and configures an ActiveSupport::BacktraceCleaner to improve
|
121
|
+
# error messages by removing unnecessary lines and root paths.
|
122
|
+
#
|
123
|
+
# @return [ActiveSupport::BacktraceCleaner] The configured backtrace cleaner
|
124
|
+
#
|
125
|
+
def backtrace_cleaner
|
126
|
+
@backtrace_cleaner ||= begin
|
127
|
+
root = "#{SpecForge.root}/"
|
74
128
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
@configuration ||= Configuration.new
|
82
|
-
end
|
129
|
+
cleaner = ActiveSupport::BacktraceCleaner.new
|
130
|
+
cleaner.add_filter { |line| line.delete_prefix(root) }
|
131
|
+
cleaner.add_silencer { |line| /rubygems|backtrace_cleaner/.match?(line) }
|
132
|
+
cleaner
|
133
|
+
end
|
134
|
+
end
|
83
135
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
136
|
+
#
|
137
|
+
# Returns the current execution context
|
138
|
+
#
|
139
|
+
# @return [Context] The current context object
|
140
|
+
#
|
141
|
+
def context
|
142
|
+
@context ||= Context.new
|
143
|
+
end
|
91
144
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
@
|
99
|
-
|
145
|
+
#
|
146
|
+
# Registers a callback for a specific test lifecycle event
|
147
|
+
# Allows custom code execution at specific points during test execution
|
148
|
+
#
|
149
|
+
# @param name [Symbol, String] A unique identifier for this callback
|
150
|
+
# @yield A block to execute when the callback is triggered
|
151
|
+
# @yieldparam context [Object] An object containing context-specific state data, depending
|
152
|
+
# on which hook the callback is triggered from.
|
153
|
+
#
|
154
|
+
# @return [Proc] The registered callback
|
155
|
+
#
|
156
|
+
# @example Registering a custom debug handler
|
157
|
+
# SpecForge.register_callback(:clean_database) do |context|
|
158
|
+
# DatabaseCleaner.clean
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
def register_callback(name, &)
|
162
|
+
Callbacks.register(name, &)
|
163
|
+
end
|
100
164
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
165
|
+
#
|
166
|
+
# Generates a unique ID for an object based on hash and object_id
|
167
|
+
#
|
168
|
+
# @param object [Object] The object to generate an ID for
|
169
|
+
#
|
170
|
+
# @return [String] A unique ID string
|
171
|
+
#
|
172
|
+
# @private
|
173
|
+
#
|
174
|
+
def generate_id(object)
|
175
|
+
"#{object.hash.abs.to_s(36)}_#{object.object_id.to_s(36)}"
|
105
176
|
end
|
106
177
|
end
|
107
178
|
end
|
179
|
+
|
180
|
+
require_relative "spec_forge/attribute"
|
181
|
+
require_relative "spec_forge/backtrace_formatter"
|
182
|
+
require_relative "spec_forge/callbacks"
|
183
|
+
require_relative "spec_forge/cli"
|
184
|
+
require_relative "spec_forge/configuration"
|
185
|
+
require_relative "spec_forge/context"
|
186
|
+
require_relative "spec_forge/core_ext"
|
187
|
+
require_relative "spec_forge/documentation"
|
188
|
+
require_relative "spec_forge/error"
|
189
|
+
require_relative "spec_forge/factory"
|
190
|
+
require_relative "spec_forge/filter"
|
191
|
+
require_relative "spec_forge/forge"
|
192
|
+
require_relative "spec_forge/http"
|
193
|
+
require_relative "spec_forge/loader"
|
194
|
+
require_relative "spec_forge/matchers"
|
195
|
+
require_relative "spec_forge/normalizer"
|
196
|
+
require_relative "spec_forge/runner"
|
197
|
+
require_relative "spec_forge/spec"
|
198
|
+
require_relative "spec_forge/type"
|
199
|
+
require_relative "spec_forge/version"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
info:
|
2
|
+
title: My API
|
3
|
+
version: 1.0.0
|
4
|
+
description: A description of My API
|
5
|
+
contact:
|
6
|
+
name: My API Team
|
7
|
+
email: api@example.com
|
8
|
+
license:
|
9
|
+
name: MIT
|
10
|
+
url: https://opensource.org/licenses/MIT
|
11
|
+
|
12
|
+
# servers:
|
13
|
+
# - url: https://api.example.com/v1
|
14
|
+
# description: Production
|
15
|
+
# - url: https://staging-api.example.com/v1
|
16
|
+
# description: Staging
|
17
|
+
#
|
18
|
+
# tags:
|
19
|
+
# - name: users
|
20
|
+
# description: User account management
|
21
|
+
# - name: posts
|
22
|
+
# description: Blog post management
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<title>Redoc</title>
|
6
|
+
<!-- needed for adaptive design -->
|
7
|
+
<meta charset="utf-8" />
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
9
|
+
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
10
|
+
|
11
|
+
<!--
|
12
|
+
Redoc doesn't change outer page styles
|
13
|
+
-->
|
14
|
+
<style>
|
15
|
+
body {
|
16
|
+
margin: 0;
|
17
|
+
padding: 0;
|
18
|
+
}
|
19
|
+
</style>
|
20
|
+
</head>
|
21
|
+
|
22
|
+
<body>
|
23
|
+
<redoc spec-url="<%= spec_url %>"></redoc>
|
24
|
+
<script src=" https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js">
|
25
|
+
</script>
|
26
|
+
</body>
|
27
|
+
|
28
|
+
</html>
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Swagger UI</title>
|
7
|
+
<style>
|
8
|
+
html {
|
9
|
+
box-sizing: border-box;
|
10
|
+
overflow: -moz-scrollbars-vertical;
|
11
|
+
overflow-y: scroll;
|
12
|
+
}
|
13
|
+
|
14
|
+
*,
|
15
|
+
*:before,
|
16
|
+
*:after {
|
17
|
+
box-sizing: inherit;
|
18
|
+
}
|
19
|
+
|
20
|
+
body {
|
21
|
+
margin: 0;
|
22
|
+
background: #fafafa;
|
23
|
+
}
|
24
|
+
</style>
|
25
|
+
|
26
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.24.0/swagger-ui.min.css"
|
27
|
+
integrity="sha512-wWpxfn2bFvPwxuqDyiJbVB0WR3ffSqJNMMryNP07frPJ1h5Xg9HIDMV1wRr1rpxT5E+KTxDrKTuWfGb1RcV8SA=="
|
28
|
+
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
29
|
+
</head>
|
30
|
+
|
31
|
+
<body>
|
32
|
+
<div id="swagger-ui"></div>
|
33
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.24.0/swagger-ui-bundle.min.js"
|
34
|
+
integrity="sha512-nEy/zRjIvuFMSr5ljsQUaUW4l7DoSHz8+SRybclmCjCh3MeF9UaooWYdr/SqjGCiyi4RIvBvn9DxCCV0ZDhiNA=="
|
35
|
+
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
36
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.24.0/swagger-ui-standalone-preset.min.js"
|
37
|
+
integrity="sha512-yJlD9FXQ7YaxAKXhviHSt/0KqWDCkLFdCnk0Ti23HXDMEQtHLAAWMHZ+POglC1mx/MOUB//h8kci3U1JYrywpQ=="
|
38
|
+
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
39
|
+
|
40
|
+
<script>
|
41
|
+
window.onload = function () {
|
42
|
+
const ui = SwaggerUIBundle({
|
43
|
+
url: "<%= spec_url %>",
|
44
|
+
dom_id: "#swagger-ui",
|
45
|
+
deepLinking: true,
|
46
|
+
presets: [
|
47
|
+
SwaggerUIBundle.presets.apis,
|
48
|
+
SwaggerUIStandalonePreset
|
49
|
+
],
|
50
|
+
plugins: [
|
51
|
+
SwaggerUIBundle.plugins.DownloadUrl
|
52
|
+
],
|
53
|
+
layout: "StandaloneLayout"
|
54
|
+
});
|
55
|
+
};
|
56
|
+
</script>
|
57
|
+
</body>
|
58
|
+
|
59
|
+
</html>
|
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.
|
4
|
+
version: 0.7.0
|
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-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
47
|
+
version: '0.8'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
54
|
+
version: '0.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: factory_bot
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '3.6'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: openapi3_parser
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.10.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.10.1
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: rspec
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +136,20 @@ dependencies:
|
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '3.13'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sem_version
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2.0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.0'
|
125
153
|
- !ruby/object:Gem::Dependency
|
126
154
|
name: thor
|
127
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +164,20 @@ dependencies:
|
|
136
164
|
- - "~>"
|
137
165
|
- !ruby/object:Gem::Version
|
138
166
|
version: '1.3'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: webrick
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '1.9'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '1.9'
|
139
181
|
description: Write API tests in YAML without sacrificing power. SpecForge combines
|
140
182
|
RSpec's matcher system, Faker's data generation, and factory patterns into a clean,
|
141
183
|
declarative syntax that eliminates boilerplate while preserving control over your
|
@@ -163,6 +205,7 @@ files:
|
|
163
205
|
- lib/spec_forge/attribute/chainable.rb
|
164
206
|
- lib/spec_forge/attribute/factory.rb
|
165
207
|
- lib/spec_forge/attribute/faker.rb
|
208
|
+
- lib/spec_forge/attribute/global.rb
|
166
209
|
- lib/spec_forge/attribute/literal.rb
|
167
210
|
- lib/spec_forge/attribute/matcher.rb
|
168
211
|
- lib/spec_forge/attribute/parameterized.rb
|
@@ -170,44 +213,94 @@ files:
|
|
170
213
|
- lib/spec_forge/attribute/resolvable.rb
|
171
214
|
- lib/spec_forge/attribute/resolvable_array.rb
|
172
215
|
- lib/spec_forge/attribute/resolvable_hash.rb
|
216
|
+
- lib/spec_forge/attribute/store.rb
|
173
217
|
- lib/spec_forge/attribute/transform.rb
|
174
218
|
- lib/spec_forge/attribute/variable.rb
|
175
219
|
- lib/spec_forge/backtrace_formatter.rb
|
220
|
+
- lib/spec_forge/callbacks.rb
|
176
221
|
- lib/spec_forge/cli.rb
|
177
222
|
- lib/spec_forge/cli/actions.rb
|
178
223
|
- lib/spec_forge/cli/command.rb
|
224
|
+
- lib/spec_forge/cli/docs.rb
|
225
|
+
- lib/spec_forge/cli/docs/generate.rb
|
179
226
|
- lib/spec_forge/cli/init.rb
|
180
227
|
- lib/spec_forge/cli/new.rb
|
181
228
|
- lib/spec_forge/cli/run.rb
|
229
|
+
- lib/spec_forge/cli/serve.rb
|
182
230
|
- lib/spec_forge/configuration.rb
|
231
|
+
- lib/spec_forge/context.rb
|
232
|
+
- lib/spec_forge/context/callbacks.rb
|
233
|
+
- lib/spec_forge/context/global.rb
|
234
|
+
- lib/spec_forge/context/store.rb
|
235
|
+
- lib/spec_forge/context/variables.rb
|
183
236
|
- lib/spec_forge/core_ext.rb
|
237
|
+
- lib/spec_forge/core_ext/array.rb
|
184
238
|
- lib/spec_forge/core_ext/rspec.rb
|
239
|
+
- lib/spec_forge/documentation.rb
|
240
|
+
- lib/spec_forge/documentation/builder.rb
|
241
|
+
- lib/spec_forge/documentation/document.rb
|
242
|
+
- lib/spec_forge/documentation/document/operation.rb
|
243
|
+
- lib/spec_forge/documentation/document/parameter.rb
|
244
|
+
- lib/spec_forge/documentation/document/request_body.rb
|
245
|
+
- lib/spec_forge/documentation/document/response.rb
|
246
|
+
- lib/spec_forge/documentation/document/response_body.rb
|
247
|
+
- lib/spec_forge/documentation/generators.rb
|
248
|
+
- lib/spec_forge/documentation/generators/base.rb
|
249
|
+
- lib/spec_forge/documentation/generators/openapi.rb
|
250
|
+
- lib/spec_forge/documentation/generators/openapi/base.rb
|
251
|
+
- lib/spec_forge/documentation/generators/openapi/error_formatter.rb
|
252
|
+
- lib/spec_forge/documentation/generators/openapi/v3_0.rb
|
253
|
+
- lib/spec_forge/documentation/loader.rb
|
254
|
+
- lib/spec_forge/documentation/loader/cache.rb
|
255
|
+
- lib/spec_forge/documentation/openapi.rb
|
256
|
+
- lib/spec_forge/documentation/openapi/base.rb
|
257
|
+
- lib/spec_forge/documentation/openapi/v3_0/example.rb
|
258
|
+
- lib/spec_forge/documentation/openapi/v3_0/media_type.rb
|
259
|
+
- lib/spec_forge/documentation/openapi/v3_0/operation.rb
|
260
|
+
- lib/spec_forge/documentation/openapi/v3_0/response.rb
|
261
|
+
- lib/spec_forge/documentation/openapi/v3_0/schema.rb
|
262
|
+
- lib/spec_forge/documentation/openapi/v3_0/tag.rb
|
185
263
|
- lib/spec_forge/error.rb
|
186
264
|
- lib/spec_forge/factory.rb
|
265
|
+
- lib/spec_forge/filter.rb
|
266
|
+
- lib/spec_forge/forge.rb
|
187
267
|
- lib/spec_forge/http.rb
|
188
268
|
- lib/spec_forge/http/backend.rb
|
189
269
|
- lib/spec_forge/http/client.rb
|
190
270
|
- lib/spec_forge/http/request.rb
|
191
271
|
- lib/spec_forge/http/verb.rb
|
272
|
+
- lib/spec_forge/loader.rb
|
273
|
+
- lib/spec_forge/matchers.rb
|
192
274
|
- lib/spec_forge/normalizer.rb
|
193
|
-
- lib/spec_forge/normalizer/
|
194
|
-
- lib/spec_forge/normalizer/
|
195
|
-
- lib/spec_forge/normalizer/
|
196
|
-
- lib/spec_forge/
|
197
|
-
- lib/spec_forge/
|
198
|
-
- lib/spec_forge/
|
275
|
+
- lib/spec_forge/normalizer/default.rb
|
276
|
+
- lib/spec_forge/normalizer/definition.rb
|
277
|
+
- lib/spec_forge/normalizer/validators.rb
|
278
|
+
- lib/spec_forge/normalizers/_shared.yml
|
279
|
+
- lib/spec_forge/normalizers/configuration.yml
|
280
|
+
- lib/spec_forge/normalizers/constraint.yml
|
281
|
+
- lib/spec_forge/normalizers/expectation.yml
|
282
|
+
- lib/spec_forge/normalizers/factory.yml
|
283
|
+
- lib/spec_forge/normalizers/factory_reference.yml
|
284
|
+
- lib/spec_forge/normalizers/global_context.yml
|
285
|
+
- lib/spec_forge/normalizers/spec.yml
|
199
286
|
- lib/spec_forge/runner.rb
|
287
|
+
- lib/spec_forge/runner/adapter.rb
|
288
|
+
- lib/spec_forge/runner/callbacks.rb
|
289
|
+
- lib/spec_forge/runner/debug_proxy.rb
|
290
|
+
- lib/spec_forge/runner/listener.rb
|
291
|
+
- lib/spec_forge/runner/metadata.rb
|
292
|
+
- lib/spec_forge/runner/state.rb
|
200
293
|
- lib/spec_forge/spec.rb
|
201
294
|
- lib/spec_forge/spec/expectation.rb
|
202
295
|
- lib/spec_forge/spec/expectation/constraint.rb
|
203
296
|
- lib/spec_forge/type.rb
|
204
297
|
- lib/spec_forge/version.rb
|
205
|
-
- lib/templates/forge_helper.tt
|
206
|
-
- lib/templates/new_factory.tt
|
207
|
-
- lib/templates/new_spec.tt
|
208
|
-
-
|
209
|
-
-
|
210
|
-
-
|
298
|
+
- lib/templates/forge_helper.rb.tt
|
299
|
+
- lib/templates/new_factory.yml.tt
|
300
|
+
- lib/templates/new_spec.yml.tt
|
301
|
+
- lib/templates/openapi.yml.tt
|
302
|
+
- lib/templates/redoc.html.tt
|
303
|
+
- lib/templates/swagger.html.tt
|
211
304
|
homepage: https://github.com/itsthedevman/spec_forge
|
212
305
|
licenses:
|
213
306
|
- MIT
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SpecForge
|
4
|
-
class Normalizer
|
5
|
-
class Configuration < Normalizer
|
6
|
-
STRUCTURE = {
|
7
|
-
base_url: SHARED_ATTRIBUTES[:base_url].except(:default), # Make it required
|
8
|
-
headers: SHARED_ATTRIBUTES[:headers],
|
9
|
-
query: SHARED_ATTRIBUTES[:query],
|
10
|
-
factories: {
|
11
|
-
type: Hash,
|
12
|
-
default: {},
|
13
|
-
structure: {
|
14
|
-
auto_discover: {
|
15
|
-
type: [TrueClass, FalseClass],
|
16
|
-
default: true
|
17
|
-
},
|
18
|
-
paths: {
|
19
|
-
type: Array,
|
20
|
-
default: []
|
21
|
-
}
|
22
|
-
}
|
23
|
-
},
|
24
|
-
on_debug: {
|
25
|
-
type: Proc
|
26
|
-
}
|
27
|
-
}.freeze
|
28
|
-
end
|
29
|
-
|
30
|
-
# On Normalizer
|
31
|
-
class << self
|
32
|
-
#
|
33
|
-
# Generates an empty configuration hash
|
34
|
-
#
|
35
|
-
# @return [Hash]
|
36
|
-
#
|
37
|
-
def default_configuration
|
38
|
-
Configuration.default
|
39
|
-
end
|
40
|
-
|
41
|
-
#
|
42
|
-
# Normalizes a configuration hash by standardizing its keys while ensuring the required data
|
43
|
-
# is provided or defaulted.
|
44
|
-
# Raises InvalidStructureError if anything is missing/invalid type
|
45
|
-
#
|
46
|
-
# @param input [Hash] The hash to normalize
|
47
|
-
#
|
48
|
-
# @return [Hash] A normalized hash as a new instance
|
49
|
-
#
|
50
|
-
def normalize_configuration!(input)
|
51
|
-
raise_errors! do
|
52
|
-
normalize_configuration(input)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
#
|
57
|
-
# Normalize a configuration hash
|
58
|
-
# Used internally by .normalize_configuration!, but is available for utility
|
59
|
-
#
|
60
|
-
# @param configuration [Hash] Configuration representation as a Hash
|
61
|
-
#
|
62
|
-
# @return [Array] Two item array
|
63
|
-
# First - The normalized hash
|
64
|
-
# Second - Array of errors, if any
|
65
|
-
#
|
66
|
-
# @private
|
67
|
-
#
|
68
|
-
def normalize_configuration(configuration)
|
69
|
-
if !Type.hash?(configuration)
|
70
|
-
raise InvalidTypeError.new(configuration, Hash, for: "configuration")
|
71
|
-
end
|
72
|
-
|
73
|
-
Normalizer::Configuration.new("configuration", configuration).normalize
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|