spec_forge 0.5.0 → 0.6.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +3 -3
  3. data/CHANGELOG.md +106 -1
  4. data/README.md +34 -22
  5. data/flake.lock +3 -3
  6. data/flake.nix +8 -2
  7. data/lib/spec_forge/attribute/chainable.rb +208 -20
  8. data/lib/spec_forge/attribute/factory.rb +91 -14
  9. data/lib/spec_forge/attribute/faker.rb +62 -13
  10. data/lib/spec_forge/attribute/global.rb +96 -0
  11. data/lib/spec_forge/attribute/literal.rb +15 -2
  12. data/lib/spec_forge/attribute/matcher.rb +186 -11
  13. data/lib/spec_forge/attribute/parameterized.rb +45 -12
  14. data/lib/spec_forge/attribute/regex.rb +55 -5
  15. data/lib/spec_forge/attribute/resolvable.rb +48 -5
  16. data/lib/spec_forge/attribute/resolvable_array.rb +62 -4
  17. data/lib/spec_forge/attribute/resolvable_hash.rb +62 -4
  18. data/lib/spec_forge/attribute/store.rb +65 -0
  19. data/lib/spec_forge/attribute/transform.rb +33 -5
  20. data/lib/spec_forge/attribute/variable.rb +37 -6
  21. data/lib/spec_forge/attribute.rb +166 -66
  22. data/lib/spec_forge/backtrace_formatter.rb +26 -3
  23. data/lib/spec_forge/callbacks.rb +79 -0
  24. data/lib/spec_forge/cli/actions.rb +27 -0
  25. data/lib/spec_forge/cli/command.rb +78 -24
  26. data/lib/spec_forge/cli/init.rb +11 -1
  27. data/lib/spec_forge/cli/new.rb +54 -3
  28. data/lib/spec_forge/cli/run.rb +20 -0
  29. data/lib/spec_forge/cli.rb +16 -5
  30. data/lib/spec_forge/configuration.rb +94 -22
  31. data/lib/spec_forge/context/callbacks.rb +91 -0
  32. data/lib/spec_forge/context/global.rb +72 -0
  33. data/lib/spec_forge/context/store.rb +148 -0
  34. data/lib/spec_forge/context/variables.rb +91 -0
  35. data/lib/spec_forge/context.rb +36 -0
  36. data/lib/spec_forge/core_ext/rspec.rb +22 -4
  37. data/lib/spec_forge/error.rb +267 -113
  38. data/lib/spec_forge/factory.rb +33 -14
  39. data/lib/spec_forge/filter.rb +87 -0
  40. data/lib/spec_forge/forge.rb +170 -0
  41. data/lib/spec_forge/http/backend.rb +99 -29
  42. data/lib/spec_forge/http/client.rb +23 -13
  43. data/lib/spec_forge/http/request.rb +74 -62
  44. data/lib/spec_forge/http/verb.rb +79 -0
  45. data/lib/spec_forge/http.rb +105 -0
  46. data/lib/spec_forge/loader.rb +254 -0
  47. data/lib/spec_forge/matchers.rb +130 -0
  48. data/lib/spec_forge/normalizer/configuration.rb +24 -11
  49. data/lib/spec_forge/normalizer/constraint.rb +21 -8
  50. data/lib/spec_forge/normalizer/expectation.rb +31 -12
  51. data/lib/spec_forge/normalizer/factory.rb +24 -11
  52. data/lib/spec_forge/normalizer/factory_reference.rb +27 -13
  53. data/lib/spec_forge/normalizer/global_context.rb +88 -0
  54. data/lib/spec_forge/normalizer/spec.rb +39 -16
  55. data/lib/spec_forge/normalizer.rb +255 -41
  56. data/lib/spec_forge/runner/callbacks.rb +246 -0
  57. data/lib/spec_forge/runner/debug_proxy.rb +213 -0
  58. data/lib/spec_forge/runner/listener.rb +54 -0
  59. data/lib/spec_forge/runner/metadata.rb +58 -0
  60. data/lib/spec_forge/runner/state.rb +99 -0
  61. data/lib/spec_forge/runner.rb +132 -123
  62. data/lib/spec_forge/spec/expectation/constraint.rb +91 -20
  63. data/lib/spec_forge/spec/expectation.rb +43 -51
  64. data/lib/spec_forge/spec.rb +83 -96
  65. data/lib/spec_forge/type.rb +36 -4
  66. data/lib/spec_forge/version.rb +4 -1
  67. data/lib/spec_forge.rb +161 -76
  68. metadata +20 -5
  69. data/spec_forge/factories/user.yml +0 -4
  70. data/spec_forge/forge_helper.rb +0 -48
  71. data/spec_forge/specs/users.yml +0 -65
@@ -1,126 +1,113 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "spec/expectation"
4
-
5
3
  module SpecForge
4
+ #
5
+ # Represents a test specification in SpecForge
6
+ #
7
+ # A Spec contains one or more Expectations and defines the base configuration
8
+ # for those expectations. It maps directly to a test defined in YAML.
9
+ #
10
+ # @example YAML representation
11
+ # get_users:
12
+ # path: /users
13
+ # expectations:
14
+ # - expect:
15
+ # status: 200
16
+ #
6
17
  class Spec
7
18
  #
8
- # Loads and defines specs with the runner. Specs can be filtered using the optional parameters
19
+ # @return [Boolean] True if debugging is enabled
9
20
  #
10
- # @param file_name [String, nil] The name of the file without the extension.
11
- # @param spec_name [String, nil] The name of the spec in a yaml file
12
- # @param expectation_name [String, nil] The name of the expectation for a spec.
21
+ attr_predicate :debug
22
+
13
23
  #
14
- # @return [Array<Spec>]
24
+ # Unique identifier for this spec
15
25
  #
16
- def self.load_and_define(file_name: nil, spec_name: nil, expectation_name: nil)
17
- specs = load_from_files
18
-
19
- filter_specs(specs, file_name:, spec_name:, expectation_name:)
20
-
21
- # Announce if we're using a filter
22
- if file_name
23
- filter = {file_name:, spec_name:, expectation_name:}.delete_if { |k, v| v.blank? }
24
- filter.stringify_keys!
25
- puts "Using filter: #{filter}"
26
- end
27
-
28
- specs.each(&:define)
29
- end
26
+ # @return [String] The spec ID
27
+ #
28
+ attr_reader :id
30
29
 
31
30
  #
32
- # Loads any specs defined in the spec files. A single file can contain one or more specs
31
+ # Human-readable name for this spec
33
32
  #
34
- # @return [Array<Spec>] An array of specs that were loaded.
33
+ # @return [String] The spec name
35
34
  #
36
- def self.load_from_files
37
- path = SpecForge.forge.join("specs")
38
- specs = []
39
-
40
- Dir[path.join("**/*.yml")].each do |file_path|
41
- content = File.read(file_path)
42
- hash = YAML.load(content).deep_symbolize_keys
43
-
44
- hash.each do |spec_name, spec_hash|
45
- line_number = content.lines.index { |line| line.start_with?("#{spec_name}:") }
46
-
47
- spec_hash[:name] = spec_name.to_s
48
- spec_hash[:file_path] = file_path
49
- spec_hash[:file_name] = file_path.delete_prefix("#{path}/").delete_suffix(".yml")
50
- spec_hash[:line_number] = line_number ? line_number + 1 : -1
35
+ attr_reader :name
51
36
 
52
- specs << new(**spec_hash)
53
- end
54
- end
55
-
56
- specs
57
- end
58
-
59
- # @private
60
- def self.filter_specs(specs, file_name: nil, spec_name: nil, expectation_name: nil)
61
- # Guard against invalid partial filters
62
- if expectation_name && spec_name.blank?
63
- raise ArgumentError, "The spec's name is required when filtering by an expectation's name"
64
- end
65
-
66
- if spec_name && file_name.blank?
67
- raise ArgumentError, "The spec's filename is required when filtering by a spec's name"
68
- end
69
-
70
- specs.select! { |spec| spec.file_name == file_name } if file_name
71
- specs.select! { |spec| spec.name == spec_name } if spec_name
72
-
73
- if expectation_name
74
- specs.each do |spec|
75
- spec.expectations.select! { |expectation| expectation.name == expectation_name }
76
- end
77
- end
37
+ #
38
+ # Absolute path to the file containing this spec
39
+ #
40
+ # @return [String] The file path
41
+ #
42
+ attr_reader :file_path
78
43
 
79
- specs
80
- end
44
+ #
45
+ # Base name of the file without path or extension
46
+ #
47
+ # @return [String] The file name
48
+ #
49
+ attr_reader :file_name
81
50
 
82
- ############################################################################
51
+ #
52
+ # Whether to enable debugging for this spec
53
+ #
54
+ # @return [Boolean] Debug flag
55
+ #
56
+ attr_reader :debug
83
57
 
84
- attr_predicate :debug
58
+ #
59
+ # Line number in the source file where this spec is defined
60
+ #
61
+ # @return [Integer] The line number
62
+ #
63
+ attr_reader :line_number
85
64
 
86
- attr_reader :name, :file_path, :file_name, :line_number, :expectations
65
+ #
66
+ # The expectations to test for this spec
67
+ #
68
+ # @return [Array<Expectation>] The expectations
69
+ #
70
+ attr_accessor :expectations
87
71
 
88
72
  #
89
- # Creates a Spec based on the input
73
+ # Creates a new spec instance
74
+ #
75
+ # @param id [String] Unique identifier
76
+ # @param name [String] Human-readable name
77
+ # @param file_path [String] Absolute path to source file
78
+ # @param file_name [String] Base name of file
79
+ # @param debug [Boolean] Whether to enable debugging
80
+ # @param line_number [Integer] Line number in source
81
+ # @param expectations [Array<Hash>] Expectation configurations
90
82
  #
91
- # @param name [String] The identifier for this spec
92
- # @param file_path [String] The path where this spec is defined
93
- # @param **input [Hash] Any attributes related to the spec, including expectations
94
- # See Normalizer::Spec
83
+ # @return [Spec] A new spec instance
95
84
  #
96
- def initialize(name:, file_path:, file_name:, line_number:, **input)
85
+ def initialize(id:, name:, file_path:, file_name:, debug:, line_number:, expectations:)
86
+ @id = id
97
87
  @name = name
98
88
  @file_path = file_path
99
89
  @file_name = file_name
90
+ @debug = debug
100
91
  @line_number = line_number
101
-
102
- input = Normalizer.normalize_spec!(input)
103
-
104
- # Don't pass this down to the expectations
105
- @debug = input.delete(:debug) || false
106
-
107
- global_options = normalize_global_options(input)
108
-
109
- @expectations =
110
- input[:expectations].map.with_index do |expectation_input, index|
111
- Expectation.new(expectation_input, global_options:)
112
- end
113
- end
114
-
115
- def define
116
- Runner.define_spec(self)
92
+ @expectations = expectations.map { |e| Expectation.new(**e) }
117
93
  end
118
94
 
119
- private
120
-
121
- def normalize_global_options(input)
122
- config = SpecForge.configuration.to_h.slice(:base_url, :headers, :query)
123
- Configuration.overlay_options(config, input.except(:expectations))
95
+ #
96
+ # Converts the spec to a hash representation
97
+ #
98
+ # @return [Hash] Hash representation
99
+ #
100
+ def to_h
101
+ {
102
+ name:,
103
+ file_path:,
104
+ file_name:,
105
+ debug:,
106
+ line_number:,
107
+ expectations: expectations.map(&:to_h)
108
+ }
124
109
  end
125
110
  end
126
111
  end
112
+
113
+ require_relative "spec/expectation"
@@ -1,24 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpecForge
4
+ #
5
+ # Provides helper methods for checking types
6
+ # Useful for working with both regular objects and Attribute delegators
7
+ #
4
8
  module Type
5
9
  #
6
- # Checks if the object is a Hash, or a ResolvableHash (delegator)
10
+ # Checks if the object is a Hash or a ResolvableHash delegator
7
11
  #
8
12
  # @param object [Object] The object to check
9
13
  #
10
- # @return [Boolean]
14
+ # @return [Boolean] True if the object is a hash-like structure
11
15
  #
12
16
  def self.hash?(object)
13
17
  object.is_a?(Hash) || object.is_a?(Attribute::ResolvableHash)
14
18
  end
15
19
 
16
20
  #
17
- # Checks if the object is an Array, or a ResolvableArray (delegator)
21
+ # Checks if the object is an Array or a ResolvableArray delegator
18
22
  #
19
23
  # @param object [Object] The object to check
20
24
  #
21
- # @return [Boolean]
25
+ # @return [Boolean] True if the object is an array-like structure
22
26
  #
23
27
  def self.array?(object)
24
28
  object.is_a?(Array) || object.is_a?(Attribute::ResolvableArray)
@@ -28,8 +32,22 @@ end
28
32
 
29
33
  #
30
34
  # Represents Hash/ResolvableHash in a form that can be used in a case statement
35
+ # Allows for type switching on hash-like objects
36
+ #
37
+ # @example
38
+ # case value
39
+ # when HashLike
40
+ # # Handle hash-like objects
41
+ # end
31
42
  #
32
43
  class HashLike
44
+ #
45
+ # Provides custom type matching for use in case statements
46
+ #
47
+ # @param object [Object] The object to check against the type
48
+ #
49
+ # @return [Boolean] Whether the object matches the type
50
+ #
33
51
  def self.===(object)
34
52
  SpecForge::Type.hash?(object)
35
53
  end
@@ -37,8 +55,22 @@ end
37
55
 
38
56
  #
39
57
  # Represents Array/ResolvableArray in a form that can be used in a case statement
58
+ # Allows for type switching on array-like objects
59
+ #
60
+ # @example
61
+ # case value
62
+ # when ArrayLike
63
+ # # Handle array-like objects
64
+ # end
40
65
  #
41
66
  class ArrayLike
67
+ #
68
+ # Provides custom type matching for use in case statements
69
+ #
70
+ # @param object [Object] The object to check against the type
71
+ #
72
+ # @return [Boolean] Whether the object matches the type
73
+ #
42
74
  def self.===(object)
43
75
  SpecForge::Type.array?(object)
44
76
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpecForge
4
- VERSION = "0.5.0"
4
+ #
5
+ # Current version of SpecForge
6
+ #
7
+ VERSION = "0.6.0"
5
8
  end
data/lib/spec_forge.rb CHANGED
@@ -16,92 +16,177 @@ require "singleton"
16
16
  require "thor"
17
17
  require "yaml"
18
18
 
19
+ #
20
+ # SpecForge: Write expressive API tests in YAML with the power of RSpec matchers
21
+ #
22
+ # SpecForge is a testing framework that allows writing API tests in a YAML format
23
+ # that reads like documentation. It combines the readability of YAML with the
24
+ # power of RSpec matchers, Faker data generation, and FactoryBot test objects.
25
+ #
26
+ # @example Basic spec in YAML
27
+ # get_user:
28
+ # path: /users/1
29
+ # expectations:
30
+ # - expect:
31
+ # status: 200
32
+ # json:
33
+ # name: kind_of.string
34
+ # email: /@/
35
+ #
36
+ # @example Running specs
37
+ # # Run all specs
38
+ # SpecForge.run
39
+ #
40
+ # # Run specific file
41
+ # SpecForge.run(file_name: "users")
42
+ #
43
+ # # Run specific spec
44
+ # SpecForge.run(file_name: "users", spec_name: "create_user")
45
+ #
46
+ module SpecForge
47
+ class << self
48
+ #
49
+ # Loads all factories and specs and runs the tests with optional filtering
50
+ #
51
+ # This is the main entry point for running SpecForge tests. It loads the
52
+ # forge_helper.rb file if it exists, configures the environment, loads
53
+ # factories and specs, and runs the tests through RSpec.
54
+ #
55
+ # @param file_name [String, nil] Optional name of spec file to run
56
+ # @param spec_name [String, nil] Optional name of spec to run
57
+ # @param expectation_name [String, nil] Optional name of expectation to run
58
+ #
59
+ def run(file_name: nil, spec_name: nil, expectation_name: nil)
60
+ # Load spec_helper.rb
61
+ forge_helper = SpecForge.forge_path.join("forge_helper.rb")
62
+ require_relative forge_helper if File.exist?(forge_helper)
63
+
64
+ # Validate in case anything was changed
65
+ configuration.validate
66
+
67
+ # Load factories
68
+ Factory.load_and_register
69
+
70
+ # Load the specs from their files and create forges from them
71
+ forges = Loader.load_from_files.map { |f| Forge.new(*f) }
72
+
73
+ # Filter out the specs and expectations
74
+ forges = Filter.apply(forges, file_name:, spec_name:, expectation_name:)
75
+
76
+ # Tell the user that we filtered if we did
77
+ Filter.announce(forges, file_name:, spec_name:, expectation_name:)
78
+
79
+ # Define and run everything
80
+ Runner.define(forges)
81
+ Runner.run
82
+ end
83
+
84
+ #
85
+ # Returns the directory root for the working directory
86
+ #
87
+ # @return [Pathname] The root directory path
88
+ #
89
+ def root
90
+ @root ||= Pathname.pwd
91
+ end
92
+
93
+ #
94
+ # Returns SpecForge's working directory
95
+ #
96
+ # @return [Pathname] The spec_forge directory path
97
+ #
98
+ def forge_path
99
+ @forge_path ||= root.join("spec_forge")
100
+ end
101
+
102
+ #
103
+ # Returns SpecForge's configuration
104
+ #
105
+ # @return [Configuration] The current configuration
106
+ #
107
+ def configuration
108
+ @configuration ||= Configuration.new
109
+ end
110
+
111
+ #
112
+ # Yields SpecForge's configuration to a block for modification
113
+ #
114
+ # @yield [config] Block that receives the configuration object
115
+ # @yieldparam config [Configuration] The configuration to modify
116
+ #
117
+ # @return [Configuration] The updated configuration
118
+ #
119
+ def configure(&block)
120
+ block&.call(configuration)
121
+ configuration
122
+ end
123
+
124
+ #
125
+ # Returns a backtrace cleaner configured for SpecForge
126
+ #
127
+ # Creates and configures an ActiveSupport::BacktraceCleaner to improve
128
+ # error messages by removing unnecessary lines and root paths.
129
+ #
130
+ # @return [ActiveSupport::BacktraceCleaner] The configured backtrace cleaner
131
+ #
132
+ def backtrace_cleaner
133
+ @backtrace_cleaner ||= begin
134
+ root = "#{SpecForge.root}/"
135
+
136
+ cleaner = ActiveSupport::BacktraceCleaner.new
137
+ cleaner.add_filter { |line| line.delete_prefix(root) }
138
+ cleaner.add_silencer { |line| /rubygems|backtrace_cleaner/.match?(line) }
139
+ cleaner
140
+ end
141
+ end
142
+
143
+ #
144
+ # Returns the current execution context
145
+ #
146
+ # @return [Context] The current context object
147
+ #
148
+ def context
149
+ @context ||= Context.new
150
+ end
151
+
152
+ #
153
+ # Registers a callback for a specific test lifecycle event
154
+ # Allows custom code execution at specific points during test execution
155
+ #
156
+ # @param name [Symbol, String] A unique identifier for this callback
157
+ # @yield A block to execute when the callback is triggered
158
+ # @yieldparam context [Object] An object containing context-specific state data, depending
159
+ # on which hook the callback is triggered from.
160
+ #
161
+ # @return [Proc] The registered callback
162
+ #
163
+ # @example Registering a custom debug handler
164
+ # SpecForge.register_callback(:clean_database) do |context|
165
+ # DatabaseCleaner.clean
166
+ # end
167
+ #
168
+ def register_callback(name, &)
169
+ Callbacks.register(name, &)
170
+ end
171
+ end
172
+ end
173
+
19
174
  require_relative "spec_forge/attribute"
20
175
  require_relative "spec_forge/backtrace_formatter"
176
+ require_relative "spec_forge/callbacks"
21
177
  require_relative "spec_forge/cli"
22
178
  require_relative "spec_forge/configuration"
179
+ require_relative "spec_forge/context"
23
180
  require_relative "spec_forge/core_ext"
24
181
  require_relative "spec_forge/error"
25
182
  require_relative "spec_forge/factory"
183
+ require_relative "spec_forge/filter"
184
+ require_relative "spec_forge/forge"
26
185
  require_relative "spec_forge/http"
186
+ require_relative "spec_forge/loader"
187
+ require_relative "spec_forge/matchers"
27
188
  require_relative "spec_forge/normalizer"
28
189
  require_relative "spec_forge/runner"
29
190
  require_relative "spec_forge/spec"
30
191
  require_relative "spec_forge/type"
31
192
  require_relative "spec_forge/version"
32
-
33
- module SpecForge
34
- #
35
- # Loads all factories and specs located in "path", then runs all of the specs
36
- #
37
- # @param path [String] The file path that contains factories and specs
38
- #
39
- def self.run(file_name: nil, spec_name: nil, expectation_name: nil)
40
- path = SpecForge.forge
41
-
42
- # Initialize
43
- forge_helper = path.join("forge_helper.rb")
44
- require_relative forge_helper if File.exist?(forge_helper)
45
-
46
- # Validate
47
- configuration.validate
48
-
49
- # Prepare
50
- Factory.load_and_register
51
- Spec.load_and_define(file_name:, spec_name:, expectation_name:)
52
-
53
- # Run
54
- Runner.run
55
- end
56
-
57
- #
58
- # Returns the directory root for the working directory
59
- #
60
- # @return [Pathname]
61
- #
62
- def self.root
63
- @root ||= Pathname.pwd
64
- end
65
-
66
- #
67
- # Returns SpecForge's working directory
68
- #
69
- # @return [Pathname]
70
- #
71
- def self.forge
72
- @forge ||= root.join("spec_forge")
73
- end
74
-
75
- #
76
- # Returns SpecForge's configuration
77
- #
78
- # @return [Config]
79
- #
80
- def self.configuration
81
- @configuration ||= Configuration.new
82
- end
83
-
84
- #
85
- # Yields SpecForge's configuration to a block
86
- #
87
- def self.configure(&block)
88
- block&.call(configuration)
89
- configuration
90
- end
91
-
92
- #
93
- # Returns a backtrace cleaner configured for SpecForge
94
- #
95
- # @return [ActiveSupport::BacktraceCleaner]
96
- #
97
- def self.backtrace_cleaner
98
- @backtrace_cleaner ||= begin
99
- root = "#{SpecForge.root}/"
100
-
101
- cleaner = ActiveSupport::BacktraceCleaner.new
102
- cleaner.add_filter { |line| line.delete_prefix(root) }
103
- cleaner.add_silencer { |line| /rubygems|backtrace_cleaner/.match?(line) }
104
- cleaner
105
- end
106
- end
107
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spec_forge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.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-02-28 00:00:00.000000000 Z
11
+ date: 2025-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -163,6 +163,7 @@ files:
163
163
  - lib/spec_forge/attribute/chainable.rb
164
164
  - lib/spec_forge/attribute/factory.rb
165
165
  - lib/spec_forge/attribute/faker.rb
166
+ - lib/spec_forge/attribute/global.rb
166
167
  - lib/spec_forge/attribute/literal.rb
167
168
  - lib/spec_forge/attribute/matcher.rb
168
169
  - lib/spec_forge/attribute/parameterized.rb
@@ -170,9 +171,11 @@ files:
170
171
  - lib/spec_forge/attribute/resolvable.rb
171
172
  - lib/spec_forge/attribute/resolvable_array.rb
172
173
  - lib/spec_forge/attribute/resolvable_hash.rb
174
+ - lib/spec_forge/attribute/store.rb
173
175
  - lib/spec_forge/attribute/transform.rb
174
176
  - lib/spec_forge/attribute/variable.rb
175
177
  - lib/spec_forge/backtrace_formatter.rb
178
+ - lib/spec_forge/callbacks.rb
176
179
  - lib/spec_forge/cli.rb
177
180
  - lib/spec_forge/cli/actions.rb
178
181
  - lib/spec_forge/cli/command.rb
@@ -180,23 +183,38 @@ files:
180
183
  - lib/spec_forge/cli/new.rb
181
184
  - lib/spec_forge/cli/run.rb
182
185
  - lib/spec_forge/configuration.rb
186
+ - lib/spec_forge/context.rb
187
+ - lib/spec_forge/context/callbacks.rb
188
+ - lib/spec_forge/context/global.rb
189
+ - lib/spec_forge/context/store.rb
190
+ - lib/spec_forge/context/variables.rb
183
191
  - lib/spec_forge/core_ext.rb
184
192
  - lib/spec_forge/core_ext/rspec.rb
185
193
  - lib/spec_forge/error.rb
186
194
  - lib/spec_forge/factory.rb
195
+ - lib/spec_forge/filter.rb
196
+ - lib/spec_forge/forge.rb
187
197
  - lib/spec_forge/http.rb
188
198
  - lib/spec_forge/http/backend.rb
189
199
  - lib/spec_forge/http/client.rb
190
200
  - lib/spec_forge/http/request.rb
191
201
  - lib/spec_forge/http/verb.rb
202
+ - lib/spec_forge/loader.rb
203
+ - lib/spec_forge/matchers.rb
192
204
  - lib/spec_forge/normalizer.rb
193
205
  - lib/spec_forge/normalizer/configuration.rb
194
206
  - lib/spec_forge/normalizer/constraint.rb
195
207
  - lib/spec_forge/normalizer/expectation.rb
196
208
  - lib/spec_forge/normalizer/factory.rb
197
209
  - lib/spec_forge/normalizer/factory_reference.rb
210
+ - lib/spec_forge/normalizer/global_context.rb
198
211
  - lib/spec_forge/normalizer/spec.rb
199
212
  - lib/spec_forge/runner.rb
213
+ - lib/spec_forge/runner/callbacks.rb
214
+ - lib/spec_forge/runner/debug_proxy.rb
215
+ - lib/spec_forge/runner/listener.rb
216
+ - lib/spec_forge/runner/metadata.rb
217
+ - lib/spec_forge/runner/state.rb
200
218
  - lib/spec_forge/spec.rb
201
219
  - lib/spec_forge/spec/expectation.rb
202
220
  - lib/spec_forge/spec/expectation/constraint.rb
@@ -205,9 +223,6 @@ files:
205
223
  - lib/templates/forge_helper.tt
206
224
  - lib/templates/new_factory.tt
207
225
  - lib/templates/new_spec.tt
208
- - spec_forge/factories/user.yml
209
- - spec_forge/forge_helper.rb
210
- - spec_forge/specs/users.yml
211
226
  homepage: https://github.com/itsthedevman/spec_forge
212
227
  licenses:
213
228
  - MIT
@@ -1,4 +0,0 @@
1
- user:
2
- class: User
3
- attributes:
4
- attribute: value
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ##########################################
4
- # Framework Integration
5
- ##########################################
6
-
7
- # Rails Integration
8
- # require_relative "../config/environment"
9
-
10
- # RSpec Integration (includes your existing configurations)
11
- # require_relative "../spec/spec_helper"
12
-
13
- # Custom requires (models, libraries, etc)
14
- # Dir[File.join(__dir__, "..", "lib", "**", "*.rb")].sort.each { |f| require f }
15
-
16
- ##########################################
17
- # Configuration
18
- ##########################################
19
-
20
- SpecForge.configure do |config|
21
- # Base configuration
22
- config.base_url = "http://localhost:3000"
23
-
24
- # Default request headers
25
- config.headers = {
26
- "Authorization" => "Bearer #{ENV.fetch("API_TOKEN", "")}"
27
- }
28
-
29
- # Optional: Default query parameters
30
- # config.query = {api_key: ENV['API_KEY']}
31
-
32
- # Factory configuration
33
- # config.factories.auto_discover = false # Default: true
34
- # config.factories.paths += ["lib/factories"] # Adds to default paths
35
-
36
- # Debug configuration
37
- # Available in specs with debug: true (aliases: breakpoint, pry)
38
- # Defaults to printing state overview (-> { puts inspect })
39
- # Available context: expectation, variables, request, response,
40
- # expected_status, expected_json
41
- # config.on_debug { binding.pry }
42
-
43
- # Test Framework Configuration
44
- # Useful for database cleaners, test data setup, etc
45
- # config.specs.before(:suite) { }
46
- # config.specs.around { |example| example.run }
47
- # config.specs.formatter = :documentation
48
- end