spec_forge 0.7.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +139 -9
  3. data/README.md +125 -203
  4. data/bin/spec_forge +1 -1
  5. data/flake.lock +76 -4
  6. data/flake.nix +5 -4
  7. data/lib/spec_forge/attribute/chainable.rb +6 -6
  8. data/lib/spec_forge/attribute/environment.rb +45 -0
  9. data/lib/spec_forge/attribute/factory.rb +26 -17
  10. data/lib/spec_forge/attribute/faker.rb +6 -1
  11. data/lib/spec_forge/attribute/generate.rb +114 -0
  12. data/lib/spec_forge/attribute/literal.rb +1 -14
  13. data/lib/spec_forge/attribute/matcher.rb +6 -2
  14. data/lib/spec_forge/attribute/parameterized.rb +20 -22
  15. data/lib/spec_forge/attribute/resolvable_array.rb +16 -16
  16. data/lib/spec_forge/attribute/resolvable_hash.rb +17 -16
  17. data/lib/spec_forge/attribute/resolvable_struct.rb +67 -0
  18. data/lib/spec_forge/attribute/template.rb +118 -0
  19. data/lib/spec_forge/attribute/transform.rb +14 -19
  20. data/lib/spec_forge/attribute/variable.rb +31 -31
  21. data/lib/spec_forge/attribute.rb +54 -100
  22. data/lib/spec_forge/blueprint.rb +27 -0
  23. data/lib/spec_forge/cli/docs/generate.rb +28 -8
  24. data/lib/spec_forge/cli/docs.rb +5 -2
  25. data/lib/spec_forge/cli/init.rb +4 -4
  26. data/lib/spec_forge/cli/new.rb +78 -27
  27. data/lib/spec_forge/cli/run.rb +84 -52
  28. data/lib/spec_forge/cli/serve.rb +6 -0
  29. data/lib/spec_forge/cli.rb +6 -14
  30. data/lib/spec_forge/configuration.rb +212 -78
  31. data/lib/spec_forge/documentation/{loader → builder}/cache.rb +26 -23
  32. data/lib/spec_forge/documentation/builder/compiler.rb +373 -0
  33. data/lib/spec_forge/documentation/builder/extractor.rb +75 -0
  34. data/lib/spec_forge/documentation/builder.rb +77 -329
  35. data/lib/spec_forge/documentation/document/operation.rb +4 -4
  36. data/lib/spec_forge/documentation/document.rb +0 -6
  37. data/lib/spec_forge/documentation/generator.rb +88 -0
  38. data/lib/spec_forge/documentation/{generators/openapi → openapi/v3_0}/error_formatter.rb +2 -2
  39. data/lib/spec_forge/documentation/openapi/v3_0/example.rb +1 -1
  40. data/lib/spec_forge/documentation/openapi/v3_0/media_type.rb +1 -1
  41. data/lib/spec_forge/documentation/openapi/v3_0/operation.rb +22 -6
  42. data/lib/spec_forge/documentation/openapi/v3_0/response.rb +29 -7
  43. data/lib/spec_forge/documentation/openapi/v3_0/schema.rb +20 -2
  44. data/lib/spec_forge/documentation/openapi/v3_0/tag.rb +1 -1
  45. data/lib/spec_forge/documentation/openapi/v3_0.rb +116 -0
  46. data/lib/spec_forge/documentation/openapi.rb +40 -12
  47. data/lib/spec_forge/documentation.rb +1 -7
  48. data/lib/spec_forge/error.rb +215 -41
  49. data/lib/spec_forge/factory.rb +38 -18
  50. data/lib/spec_forge/forge/action.rb +41 -0
  51. data/lib/spec_forge/forge/actions/call.rb +33 -0
  52. data/lib/spec_forge/forge/actions/debug.rb +47 -0
  53. data/lib/spec_forge/forge/actions/expect.rb +44 -0
  54. data/lib/spec_forge/forge/actions/request.rb +65 -0
  55. data/lib/spec_forge/forge/actions/store.rb +31 -0
  56. data/lib/spec_forge/forge/callbacks.rb +80 -0
  57. data/lib/spec_forge/forge/context.rb +41 -0
  58. data/lib/spec_forge/forge/display.rb +503 -0
  59. data/lib/spec_forge/forge/hooks.rb +131 -0
  60. data/lib/spec_forge/forge/runner/array_io.rb +81 -0
  61. data/lib/spec_forge/forge/runner/content_validator.rb +92 -0
  62. data/lib/spec_forge/forge/runner/header_validator.rb +66 -0
  63. data/lib/spec_forge/forge/runner/reporter.rb +56 -0
  64. data/lib/spec_forge/forge/runner/schema_validator.rb +113 -0
  65. data/lib/spec_forge/forge/runner.rb +118 -0
  66. data/lib/spec_forge/forge/timer.rb +94 -0
  67. data/lib/spec_forge/forge/variables.rb +38 -0
  68. data/lib/spec_forge/forge.rb +207 -133
  69. data/lib/spec_forge/http/backend.rb +49 -143
  70. data/lib/spec_forge/http/client.rb +14 -17
  71. data/lib/spec_forge/http/request.rb +37 -84
  72. data/lib/spec_forge/http/verb.rb +4 -0
  73. data/lib/spec_forge/http.rb +0 -5
  74. data/lib/spec_forge/loader/filter.rb +85 -0
  75. data/lib/spec_forge/loader/step_processor.rb +282 -0
  76. data/lib/spec_forge/loader.rb +105 -220
  77. data/lib/spec_forge/normalizer/default.rb +1 -1
  78. data/lib/spec_forge/normalizer/structure.rb +140 -0
  79. data/lib/spec_forge/normalizer/transformers.rb +168 -0
  80. data/lib/spec_forge/normalizer/validators.rb +50 -8
  81. data/lib/spec_forge/normalizer.rb +76 -119
  82. data/lib/spec_forge/normalizers/callback.yml +38 -0
  83. data/lib/spec_forge/normalizers/configuration.yml +59 -9
  84. data/lib/spec_forge/normalizers/factory.yml +53 -2
  85. data/lib/spec_forge/normalizers/factory_reference.yml +63 -2
  86. data/lib/spec_forge/normalizers/json_schema.yml +79 -0
  87. data/lib/spec_forge/normalizers/step.yml +506 -0
  88. data/lib/spec_forge/step/call.rb +36 -0
  89. data/lib/spec_forge/step/expect.rb +110 -0
  90. data/lib/spec_forge/step/source.rb +22 -0
  91. data/lib/spec_forge/step.rb +129 -0
  92. data/lib/spec_forge/type.rb +115 -66
  93. data/lib/spec_forge/version.rb +1 -1
  94. data/lib/spec_forge.rb +44 -106
  95. data/lib/templates/forge_helper.rb.tt +43 -22
  96. data/lib/templates/new_blueprint.yml.tt +54 -0
  97. metadata +75 -44
  98. data/lib/spec_forge/attribute/global.rb +0 -96
  99. data/lib/spec_forge/attribute/store.rb +0 -65
  100. data/lib/spec_forge/backtrace_formatter.rb +0 -50
  101. data/lib/spec_forge/callbacks.rb +0 -88
  102. data/lib/spec_forge/context/callbacks.rb +0 -91
  103. data/lib/spec_forge/context/global.rb +0 -72
  104. data/lib/spec_forge/context/store.rb +0 -131
  105. data/lib/spec_forge/context/variables.rb +0 -91
  106. data/lib/spec_forge/context.rb +0 -36
  107. data/lib/spec_forge/core_ext/rspec.rb +0 -55
  108. data/lib/spec_forge/core_ext.rb +0 -5
  109. data/lib/spec_forge/documentation/generators/base.rb +0 -81
  110. data/lib/spec_forge/documentation/generators/openapi/base.rb +0 -100
  111. data/lib/spec_forge/documentation/generators/openapi/v3_0.rb +0 -65
  112. data/lib/spec_forge/documentation/generators/openapi.rb +0 -59
  113. data/lib/spec_forge/documentation/generators.rb +0 -17
  114. data/lib/spec_forge/documentation/loader.rb +0 -159
  115. data/lib/spec_forge/documentation/openapi/base.rb +0 -33
  116. data/lib/spec_forge/filter.rb +0 -86
  117. data/lib/spec_forge/normalizer/definition.rb +0 -248
  118. data/lib/spec_forge/normalizers/_shared.yml +0 -74
  119. data/lib/spec_forge/normalizers/constraint.yml +0 -8
  120. data/lib/spec_forge/normalizers/expectation.yml +0 -47
  121. data/lib/spec_forge/normalizers/global_context.yml +0 -28
  122. data/lib/spec_forge/normalizers/spec.yml +0 -50
  123. data/lib/spec_forge/runner/adapter.rb +0 -183
  124. data/lib/spec_forge/runner/callbacks.rb +0 -246
  125. data/lib/spec_forge/runner/debug_proxy.rb +0 -213
  126. data/lib/spec_forge/runner/listener.rb +0 -54
  127. data/lib/spec_forge/runner/metadata.rb +0 -58
  128. data/lib/spec_forge/runner/state.rb +0 -98
  129. data/lib/spec_forge/runner.rb +0 -75
  130. data/lib/spec_forge/spec/expectation/constraint.rb +0 -127
  131. data/lib/spec_forge/spec/expectation.rb +0 -68
  132. data/lib/spec_forge/spec.rb +0 -68
  133. data/lib/templates/new_spec.yml.tt +0 -43
@@ -2,129 +2,263 @@
2
2
 
3
3
  module SpecForge
4
4
  #
5
- # Configuration container for SpecForge settings
6
- # Defines default values and validation for all configuration options
5
+ # Holds configuration options for SpecForge
7
6
  #
8
- class Configuration < Struct.new(:base_url, :headers, :query, :factories, :on_debug)
9
- #
10
- # Manages factory configuration settings
11
- # Controls auto-discovery behavior and custom factory paths
7
+ # Configuration is typically set in forge_helper.rb using the configure block.
8
+ # It controls base URL, global variables, factory settings, callbacks, and more.
9
+ #
10
+ # @example Basic configuration
11
+ # SpecForge.configure do |config|
12
+ # config.base_url = "http://localhost:3000"
13
+ # config.global_variables = {api_version: "v1"}
14
+ # end
15
+ #
16
+ class Configuration
12
17
  #
13
- # @example
14
- # config.factories.auto_discover = false
15
- # config.factories.paths += ["lib/factories"]
18
+ # Configuration for FactoryBot factory loading
16
19
  #
17
20
  class Factories < Struct.new(:auto_discover, :paths)
18
- #
19
- # Creates reader methods that return boolean values
20
- # Allows for checking configuration with predicate methods
21
- #
22
- attr_predicate :auto_discover, :paths
23
-
24
- #
25
- # Initializes a new Factories configuration
26
- # Sets default values for auto-discovery and paths
27
- #
28
- # @param auto_discover [Boolean] Whether to auto-discover factories (default: true)
29
- # @param paths [Array<String>] Additional paths to look for factories (default: [])
30
- #
31
- # @return [Factories] A new factories configuration instance
32
- #
21
+ # @return [Boolean] Whether auto-discovery is enabled
22
+ attr_predicate :auto_discover
23
+
24
+ # @return [Array<String>] Factory file paths
25
+ attr_predicate :paths
26
+
33
27
  def initialize(auto_discover: true, paths: []) = super
34
28
  end
35
29
 
30
+ # @return [String] Base URL for HTTP requests
31
+ attr_accessor :base_url
32
+
33
+ # @return [Hash] Global variables available to all blueprints
34
+ attr_accessor :global_variables
35
+
36
+ # @return [Factories] Factory configuration
37
+ attr_reader :factories
38
+
39
+ # @return [Proc, nil] Debug handler proc
40
+ attr_reader :on_debug_proc
41
+
42
+ # @return [Hash{Symbol => Proc}] Registered callbacks
43
+ attr_reader :callbacks
44
+
45
+ # @return [Hash{Symbol => Array}] Global lifecycle hooks for forge, blueprint, and step events
46
+ attr_reader :hooks
47
+
36
48
  #
37
- # Initializes a new Configuration with default values
38
- # Sets up the configuration structure including factory settings and debug proxy
49
+ # Creates a new Configuration with default values
39
50
  #
40
- # @return [Configuration] A new configuration instance with defaults
51
+ # @return [Configuration] A new configuration instance
41
52
  #
42
53
  def initialize
43
- config = Normalizer.default(:configuration)
54
+ # Validated
55
+ @base_url = "http://localhost:3000"
56
+ @factories = Factories.new
57
+ @global_variables = {}
44
58
 
45
- config[:base_url] = "http://localhost:3000"
46
- config[:factories] = Factories.new
47
- config[:on_debug] = Runner::DebugProxy.default
48
-
49
- super(**config)
59
+ # Internal
60
+ @on_debug_proc = nil
61
+ @callbacks = {}
62
+ @hooks = {
63
+ before_forge: [],
64
+ before_blueprint: [],
65
+ before_step: [],
66
+ after_step: [],
67
+ after_blueprint: [],
68
+ after_forge: []
69
+ }
50
70
  end
51
71
 
52
72
  #
53
- # Validates the configuration and applies normalization
54
- # Ensures all required fields have values and applies defaults when needed
73
+ # Validates the configuration and normalizes values
55
74
  #
56
- # @return [self] Returns self for method chaining
75
+ # @return [Configuration] self
57
76
  #
58
- # @api private
77
+ # @raise [Error::InvalidStructureError] If configuration is invalid
59
78
  #
60
79
  def validate
61
- output = Normalizer.normalize!(to_h, using: :configuration)
80
+ output = Normalizer.normalize!(
81
+ {
82
+ base_url: @base_url,
83
+ factories: @factories.to_h,
84
+ global_variables: @global_variables
85
+ },
86
+ using: :configuration
87
+ )
62
88
 
63
89
  # In case any value was set to `nil`
64
- self.base_url = output[:base_url] if base_url.blank?
65
- self.query = output[:query] if query.blank?
66
- self.headers = output[:headers] if headers.blank?
90
+ @global_variables = output[:global_variables] if @global_variables.blank?
91
+ @global_variables.symbolize_keys!
67
92
 
68
93
  self
69
94
  end
70
95
 
71
96
  #
72
- # Recursively converts the configuration to a hash representation
97
+ # Sets a debug handler block to be called when a step has debug: true
98
+ #
99
+ # @yield [context] Block called when debug is triggered
100
+ # @yieldparam context [Forge::Context] The current execution context
73
101
  #
74
- # @return [Hash] Hash representation of the configuration
102
+ # @example
103
+ # config.on_debug { binding.pry }
75
104
  #
76
- def to_h
77
- hash = super
78
- hash[:factories] = hash[:factories].to_h
79
- hash
105
+ def on_debug(&block)
106
+ @on_debug_proc = block
80
107
  end
81
108
 
82
109
  #
83
- # Returns the RSpec configuration object
84
- # Provides access to RSpec's internal configuration for test customization
110
+ # Returns RSpec's configuration for customization
85
111
  #
86
- # @return [RSpec::Core::Configuration] RSpec's configuration object
112
+ # @return [RSpec::Core::Configuration] RSpec configuration
87
113
  #
88
- # @example Setting formatter options
89
- # SpecForge.configure do |config|
90
- # config.specs.formatter = :documentation
91
- # end
92
- #
93
- def specs
114
+ def rspec
94
115
  RSpec.configuration
95
116
  end
96
117
 
97
- alias_method :rspec, :specs
98
-
99
118
  #
100
- # Registers a callback for a specific test lifecycle event
101
- # Allows custom code execution at specific points during test execution
119
+ # Registers a callback that can be invoked from blueprints using call:
102
120
  #
103
- # @param name [Symbol, String] The callback point to register for
104
- # (:before_file, :after_expectation, etc.)
105
- # @yield A block to execute when the callback is triggered
106
- # @yieldparam context [Object] An object containing context-specific state data, depending
107
- # on which hook the callback is triggered from.
121
+ # @param name [String, Symbol] The callback name to register
108
122
  #
109
- # @return [Proc] The registered callback
123
+ # @yield [context, *args] Block to execute when callback is called
124
+ # @yieldparam context [Forge::Context] The current execution context
110
125
  #
111
- # @example Registering a custom debug handler
112
- # SpecForge.configure do |config|
113
- # config.register_callback(:on_debug) { binding.pry }
126
+ # @example Simple callback
127
+ # config.register_callback("seed_data") do |context|
128
+ # User.create!(name: "Test")
114
129
  # end
115
130
  #
116
- # @example Cleaning database after each test
117
- # SpecForge.configure do |config|
118
- # config.register_callback(:after_expectation) do
119
- # DatabaseCleaner.clean
120
- # end
131
+ # @example Callback with arguments
132
+ # config.register_callback("create_users") do |context, count:|
133
+ # count.times { User.create! }
121
134
  # end
122
135
  #
123
- def register_callback(name, &)
124
- Callbacks.register(name, &)
136
+ def register_callback(name, &block)
137
+ @callbacks[name.to_sym] = block
138
+ end
139
+
140
+ #
141
+ # Removes a registered callback and detaches it from all lifecycle hooks
142
+ #
143
+ # @param name [String, Symbol] The callback name to remove
144
+ #
145
+ # @return [Proc, nil] The removed callback proc, or nil if not found
146
+ #
147
+ # @example Remove a callback
148
+ # config.register_callback(:my_hook) { |context| puts "hook" }
149
+ # config.before(:step, :my_hook)
150
+ # config.deregister_callback(:my_hook) # Removes from callbacks and hooks
151
+ #
152
+ def deregister_callback(name)
153
+ name = name.to_sym
154
+
155
+ callback = @callbacks.delete(name)
156
+ @hooks.each_value { |a| a.delete(name) }
157
+
158
+ callback
159
+ end
160
+
161
+ #
162
+ # Attaches a callback to a before lifecycle event
163
+ #
164
+ # Global hooks run for all blueprints and execute in registration order.
165
+ # Can either reference a pre-registered callback by name, or accept a block
166
+ # to register and attach a callback in one step (like RSpec's before hooks).
167
+ #
168
+ # @param event [Symbol] The lifecycle event (:forge, :blueprint, or :step)
169
+ # @param callback_name [String, Symbol, nil] The name of a registered callback
170
+ # (optional if block is provided)
171
+ #
172
+ # @yield [context] Block to execute (registers callback automatically)
173
+ # @yieldparam context [Forge::Context] The current execution context
174
+ #
175
+ # @return [String, Symbol] The callback name (auto-generated if block provided)
176
+ #
177
+ # @raise [ArgumentError] If the event is invalid
178
+ # @raise [ArgumentError] If the callback is not registered (when using name)
179
+ #
180
+ # @example Attach a pre-registered callback
181
+ # config.register_callback(:setup) { |context| Database.seed }
182
+ # config.before(:forge, :setup)
183
+ #
184
+ # @example Register and attach with a block (like RSpec)
185
+ # config.before(:step) { |context| Logger.info("Starting step") }
186
+ # config.before(:blueprint) { |context| Database.clean }
187
+ #
188
+ # @example Store the callback name for later deregistration
189
+ # callback_name = config.before(:step) { |context| puts "hook" }
190
+ # config.deregister_callback(callback_name)
191
+ #
192
+ def before(event, callback_name = nil, &block)
193
+ if block
194
+ callback_name = "__sf_cb_#{SecureRandom.uuid.tr("-", "")}"
195
+ register_callback(callback_name, &block)
196
+ end
197
+
198
+ register_hook("before", event, callback_name)
199
+
200
+ callback_name
201
+ end
202
+
203
+ #
204
+ # Attaches a callback to an after lifecycle event
205
+ #
206
+ # Global hooks run for all blueprints and execute in registration order.
207
+ # Can either reference a pre-registered callback by name, or accept a block
208
+ # to register and attach a callback in one step (like RSpec's after hooks).
209
+ #
210
+ # @param event [Symbol] The lifecycle event (:forge, :blueprint, or :step)
211
+ # @param callback_name [String, Symbol, nil] The name of a registered callback
212
+ # (optional if block is provided)
213
+ #
214
+ # @yield [context] Block to execute (registers callback automatically)
215
+ # @yieldparam context [Forge::Context] The current execution context
216
+ #
217
+ # @return [String, Symbol] The callback name (auto-generated if block provided)
218
+ #
219
+ # @raise [ArgumentError] If the event is invalid
220
+ # @raise [ArgumentError] If the callback is not registered (when using name)
221
+ #
222
+ # @example Attach a pre-registered callback
223
+ # config.register_callback(:cleanup) { |context| Database.clean }
224
+ # config.after(:forge, :cleanup)
225
+ #
226
+ # @example Register and attach with a block (like RSpec)
227
+ # config.after(:step) { |context| Logger.info("Step complete") }
228
+ # config.after(:blueprint) { |context| Database.rollback }
229
+ #
230
+ # @example Store the callback name for later deregistration
231
+ # callback_name = config.after(:step) { |context| puts "done" }
232
+ # config.deregister_callback(callback_name)
233
+ #
234
+ def after(event, callback_name = nil, &block)
235
+ if block
236
+ callback_name = "__sf_cb_#{SecureRandom.uuid.tr("-", "")}"
237
+ register_callback(callback_name, &block)
238
+ end
239
+
240
+ register_hook("after", event, callback_name)
241
+
242
+ callback_name
125
243
  end
126
244
 
127
- alias_method :define_callback, :register_callback
128
- alias_method :callback, :register_callback
245
+ private
246
+
247
+ def register_hook(timing, event, callback_name)
248
+ hook = :"#{timing}_#{event}"
249
+ callback_name = callback_name.to_sym
250
+
251
+ if !@hooks.key?(hook)
252
+ keys = @hooks.keys.select { |k| k.to_s.start_with?(timing) }.map(&:in_quotes)
253
+ raise ArgumentError, "Invalid event #{hook.in_quotes}. Expected one of #{keys.to_or_sentence}"
254
+ end
255
+
256
+ if !@callbacks.key?(callback_name)
257
+ keys = @callbacks.keys.map(&:in_quotes)
258
+ raise ArgumentError, "Invalid callback #{callback_name.in_quotes}. Expected one of #{keys.to_or_sentence}"
259
+ end
260
+
261
+ @hooks[hook] << callback_name
262
+ end
129
263
  end
130
264
  end
@@ -2,20 +2,23 @@
2
2
 
3
3
  module SpecForge
4
4
  module Documentation
5
- class Loader
5
+ class Builder
6
6
  #
7
- # Manages caching of test execution data for documentation generation
7
+ # Manages caching of endpoint data to avoid re-running blueprints
8
8
  #
9
- # Provides caching of endpoint data extracted from tests,
10
- # checking file modification times to determine cache validity and
11
- # avoiding unnecessary test re-execution when specs haven't changed.
9
+ # The Cache stores extracted endpoint data and tracks blueprint file
10
+ # modification times. When blueprints haven't changed, cached data
11
+ # can be reused to speed up documentation generation.
12
+ #
13
+ # Cache files are stored in the OpenAPI generated directory under
14
+ # a .cache subdirectory.
12
15
  #
13
16
  # @example Using the cache
14
17
  # cache = Cache.new
15
18
  # if cache.valid?
16
19
  # endpoints = cache.read
17
20
  # else
18
- # endpoints = run_tests_and_extract_data
21
+ # endpoints = extract_from_blueprints
19
22
  # cache.create(endpoints)
20
23
  # end
21
24
  #
@@ -23,41 +26,41 @@ module SpecForge
23
26
  #
24
27
  # Creates a new cache manager
25
28
  #
26
- # Sets up file paths for endpoint and spec caches in the OpenAPI
29
+ # Sets up file paths for endpoint and blueprint caches in the OpenAPI
27
30
  # generated directory structure.
28
31
  #
29
32
  # @return [Cache] A new cache instance
30
33
  #
31
34
  def initialize
32
35
  @endpoint_cache = SpecForge.openapi_path.join("generated", ".cache", "endpoints.yml")
33
- @spec_cache = SpecForge.openapi_path.join("generated", ".cache", "specs.yml")
36
+ @blueprint_cache = SpecForge.openapi_path.join("generated", ".cache", "blueprints.yml")
34
37
  end
35
38
 
36
39
  #
37
40
  # Checks if the cache is valid and can be used
38
41
  #
39
42
  # Determines cache validity by checking if endpoint cache exists
40
- # and whether any spec files have been modified since the cache
43
+ # and whether any blueprint files have been modified since the cache
41
44
  # was created.
42
45
  #
43
46
  # @return [Boolean] true if cache is valid and can be used
44
47
  #
45
48
  def valid?
46
- endpoint_cache? && !specs_updated?
49
+ endpoint_cache? && !blueprints_updated?
47
50
  end
48
51
 
49
52
  #
50
- # Creates a cache entry with endpoint data and spec file metadata
53
+ # Creates a cache entry with endpoint data and blueprint file metadata
51
54
  #
52
- # Writes both the endpoint data and current spec file modification times
53
- # to enable cache invalidation when specs change.
55
+ # Writes both the endpoint data and current blueprint file modification times
56
+ # to enable cache invalidation when blueprints change.
54
57
  #
55
58
  # @param endpoints [Array<Hash>] Endpoint data to cache
56
59
  #
57
60
  # @return [void]
58
61
  #
59
62
  def create(endpoints)
60
- write_spec_cache
63
+ write_blueprint_cache
61
64
  write(endpoints)
62
65
  end
63
66
 
@@ -93,11 +96,11 @@ module SpecForge
93
96
  YAML.safe_load_file(path, symbolize_names: true, permitted_classes: [Symbol, Time])
94
97
  end
95
98
 
96
- def specs_updated?
97
- return true if !File.exist?(@spec_cache)
99
+ def blueprints_updated?
100
+ return true if !File.exist?(@blueprint_cache)
98
101
 
99
- cache = read_from_file(@spec_cache)
100
- new_cache = generate_spec_cache
102
+ cache = read_from_file(@blueprint_cache)
103
+ new_cache = generate_blueprint_cache
101
104
 
102
105
  different?(cache, new_cache)
103
106
  end
@@ -106,17 +109,17 @@ module SpecForge
106
109
  File.exist?(@endpoint_cache)
107
110
  end
108
111
 
109
- def generate_spec_cache
110
- paths = SpecForge.forge_path.join("specs", "**", "*.{yml,yaml}")
112
+ def generate_blueprint_cache
113
+ paths = SpecForge.forge_path.join("blueprints", "**", "*.{yml,yaml}")
111
114
 
112
115
  Dir[paths].each_with_object({}) do |path, hash|
113
116
  hash[path.to_sym] = File.mtime(path)
114
117
  end
115
118
  end
116
119
 
117
- def write_spec_cache
118
- data = generate_spec_cache
119
- write_to_file(data, @spec_cache)
120
+ def write_blueprint_cache
121
+ data = generate_blueprint_cache
122
+ write_to_file(data, @blueprint_cache)
120
123
  end
121
124
 
122
125
  def different?(cache_left, cache_right)