spec_forge 0.1.0 → 0.3.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -2
  3. data/README.md +366 -143
  4. data/flake.nix +2 -2
  5. data/lib/spec_forge/attribute/chainable.rb +19 -16
  6. data/lib/spec_forge/attribute/factory.rb +6 -18
  7. data/lib/spec_forge/attribute/faker.rb +56 -20
  8. data/lib/spec_forge/attribute/literal.rb +4 -0
  9. data/lib/spec_forge/attribute/resolvable.rb +4 -6
  10. data/lib/spec_forge/attribute/resolvable_array.rb +4 -0
  11. data/lib/spec_forge/attribute/resolvable_hash.rb +4 -0
  12. data/lib/spec_forge/attribute/variable.rb +6 -13
  13. data/lib/spec_forge/attribute.rb +3 -12
  14. data/lib/spec_forge/cli/init.rb +2 -9
  15. data/lib/spec_forge/configuration.rb +58 -0
  16. data/lib/spec_forge/factory.rb +4 -4
  17. data/lib/spec_forge/http/backend.rb +42 -8
  18. data/lib/spec_forge/http/client.rb +2 -2
  19. data/lib/spec_forge/http/request.rb +11 -14
  20. data/lib/spec_forge/normalizer/configuration.rb +77 -0
  21. data/lib/spec_forge/normalizer/expectation.rb +1 -0
  22. data/lib/spec_forge/normalizer/spec.rb +1 -0
  23. data/lib/spec_forge/normalizer.rb +14 -11
  24. data/lib/spec_forge/runner.rb +98 -72
  25. data/lib/spec_forge/spec/expectation/constraint.rb +2 -5
  26. data/lib/spec_forge/spec/expectation.rb +32 -13
  27. data/lib/spec_forge/spec.rb +20 -14
  28. data/lib/spec_forge/version.rb +1 -1
  29. data/lib/spec_forge.rb +20 -11
  30. data/lib/templates/forge_helper.tt +48 -0
  31. data/spec_forge/forge_helper.rb +37 -0
  32. data/spec_forge/specs/users.yml +6 -4
  33. metadata +7 -8
  34. data/lib/spec_forge/config.rb +0 -84
  35. data/lib/spec_forge/environment.rb +0 -71
  36. data/lib/spec_forge/normalizer/config.rb +0 -104
  37. data/lib/templates/config.tt +0 -19
  38. data/spec_forge/config.yml +0 -19
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.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2025-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -177,8 +177,7 @@ files:
177
177
  - lib/spec_forge/cli/init.rb
178
178
  - lib/spec_forge/cli/new.rb
179
179
  - lib/spec_forge/cli/run.rb
180
- - lib/spec_forge/config.rb
181
- - lib/spec_forge/environment.rb
180
+ - lib/spec_forge/configuration.rb
182
181
  - lib/spec_forge/error.rb
183
182
  - lib/spec_forge/factory.rb
184
183
  - lib/spec_forge/http.rb
@@ -187,7 +186,7 @@ files:
187
186
  - lib/spec_forge/http/request.rb
188
187
  - lib/spec_forge/http/verb.rb
189
188
  - lib/spec_forge/normalizer.rb
190
- - lib/spec_forge/normalizer/config.rb
189
+ - lib/spec_forge/normalizer/configuration.rb
191
190
  - lib/spec_forge/normalizer/constraint.rb
192
191
  - lib/spec_forge/normalizer/expectation.rb
193
192
  - lib/spec_forge/normalizer/factory.rb
@@ -199,9 +198,9 @@ files:
199
198
  - lib/spec_forge/spec/expectation/constraint.rb
200
199
  - lib/spec_forge/type.rb
201
200
  - lib/spec_forge/version.rb
202
- - lib/templates/config.tt
203
- - spec_forge/config.yml
201
+ - lib/templates/forge_helper.tt
204
202
  - spec_forge/factories/user.yml
203
+ - spec_forge/forge_helper.rb
205
204
  - spec_forge/specs/users.yml
206
205
  homepage: https://github.com/itsthedevman/spec_forge
207
206
  licenses:
@@ -220,7 +219,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
220
219
  requirements:
221
220
  - - ">="
222
221
  - !ruby/object:Gem::Version
223
- version: 3.0.0
222
+ version: '3.2'
224
223
  required_rubygems_version: !ruby/object:Gem::Requirement
225
224
  requirements:
226
225
  - - ">="
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SpecForge
4
- #
5
- # Represents `config.yml`
6
- #
7
- class Config < Struct.new(:base_url, :authorization, :factories, :environment)
8
- #
9
- # authorization: {}
10
- #
11
- class Authorization < Struct.new(:header, :value)
12
- attr_predicate :header, :value
13
- end
14
-
15
- #
16
- # factories: {}
17
- #
18
- class Factories < Struct.new(:paths, :auto_discover)
19
- attr_predicate :paths, :auto_discover
20
- end
21
-
22
- #
23
- # environment: {}
24
- #
25
- class Environment < Struct.new(:use, :preload, :models_path)
26
- attr_predicate :use, :preload, :models_path
27
-
28
- def initialize(string_or_hash)
29
- use, preload, models_path = "", "", ""
30
-
31
- # "rails" or other preset
32
- if string_or_hash.is_a?(String)
33
- use = string_or_hash
34
- else
35
- string_or_hash => {use:, preload:, models_path:}
36
- end
37
-
38
- super(use:, preload:, models_path:)
39
- end
40
- end
41
-
42
- ############################################################################
43
-
44
- #
45
- # Creates a config with the user's config overlaid on the default
46
- #
47
- def initialize
48
- config = Normalizer.default_config.deep_merge(load_from_file)
49
- normalized = Normalizer.normalize_config!(config)
50
-
51
- super(
52
- base_url: normalized.delete(:base_url),
53
- authorization: transform_authorization(normalized),
54
- factories: transform_factories(normalized),
55
- environment: transform_environment(normalized)
56
- )
57
- end
58
-
59
- private
60
-
61
- def load_from_file
62
- path = SpecForge.forge.join("config.yml")
63
- return unless File.exist?(path)
64
-
65
- erb = ERB.new(File.read(path)).result
66
- YAML.safe_load(erb, aliases: true, symbolize_names: true)
67
- end
68
-
69
- def transform_authorization(hash)
70
- # The intention for authorization hash is to support different authorization schemes
71
- # authorization: {default: {}, admin: {}, dev: {}}
72
- # But I won't know exactly what will be defined - `to_struct` will handle that.
73
- hash[:authorization].transform_values { |v| Authorization.new(**v) }.to_struct
74
- end
75
-
76
- def transform_factories(hash)
77
- Factories.new(**hash[:factories])
78
- end
79
-
80
- def transform_environment(hash)
81
- Environment.new(hash[:environment])
82
- end
83
- end
84
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SpecForge
4
- class Environment
5
- attr_reader :environment, :framework
6
-
7
- #
8
- # Creates a new environment loader
9
- #
10
- # @param environment [Config::Environment] The environment to load
11
- #
12
- def initialize(environment = SpecForge.config.environment)
13
- @environment = environment
14
- @framework = environment.use
15
- end
16
-
17
- #
18
- # Loads the environment
19
- #
20
- def load
21
- load_framework
22
- load_preload
23
-
24
- self
25
- end
26
-
27
- private
28
-
29
- def load_framework
30
- case framework
31
- when "rails"
32
- load_rails
33
- else
34
- load_generic
35
- end
36
- end
37
-
38
- def load_rails
39
- path = SpecForge.root.join("config", "environment.rb")
40
-
41
- if File.exist?(path)
42
- require path
43
- else
44
- warn <<~WARNING.chomp
45
- SpecForge warning: Config attribute "environment" set to "rails" but Rails environment (config/environment.rb) does not exist.
46
- Factories or model-dependent features may not function as expected.
47
- - For non-Rails projects, set your environment's 'models_path' or 'preload' in your config.yml
48
- - To disable this warning, set 'environment: ""' in your config.yml.
49
- WARNING
50
- end
51
- end
52
-
53
- def load_generic
54
- return unless environment.models_path? && environment.models_path.present?
55
-
56
- models_path = SpecForge.root.join(environment.models_path)
57
- return if !File.exist?(models_path)
58
-
59
- Dir[models_path.join("**/*.rb")].each { |file| require file }
60
- end
61
-
62
- def load_preload
63
- return unless environment.preload? && environment.preload.present?
64
-
65
- path = SpecForge.root.join(environment.preload)
66
- return if !File.exist?(path)
67
-
68
- require path
69
- end
70
- end
71
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SpecForge
4
- class Normalizer
5
- class Config < Normalizer
6
- STRUCTURE = {
7
- environment: {
8
- # Allows for a shorthand:
9
- # environment: rails
10
- # Long form:
11
- # environment:
12
- # use: rails
13
- type: [String, Hash],
14
- default: "rails",
15
- structure: {
16
- use: {type: String, default: "rails"},
17
- preload: {type: String, default: ""},
18
- models_path: {
19
- type: String,
20
- aliases: %i[models],
21
- default: ""
22
- }
23
- }
24
- },
25
- base_url: {type: String}, # Required
26
- authorization: {
27
- type: Hash,
28
- default: {
29
- # Default is a key on this hash
30
- default: {}
31
- },
32
- structure: {
33
- default: {
34
- type: Hash,
35
- structure: {
36
- header: {type: String, default: ""},
37
- value: {type: String, default: ""}
38
- }
39
- }
40
- }
41
- },
42
- factories: {
43
- type: Hash,
44
- default: {},
45
- structure: {
46
- paths: {
47
- type: Array,
48
- default: []
49
- },
50
- auto_discover: {
51
- type: [TrueClass, FalseClass],
52
- default: true
53
- }
54
- }
55
- }
56
- }.freeze
57
- end
58
-
59
- # On Normalizer
60
- class << self
61
- #
62
- # Generates an empty config hash
63
- #
64
- # @return [Hash]
65
- #
66
- def default_config
67
- Config.default
68
- end
69
-
70
- #
71
- # Normalizes a config hash by standardizing its keys while ensuring the required data
72
- # is provided or defaulted.
73
- # Raises InvalidStructureError if anything is missing/invalid type
74
- #
75
- # @param input [Hash] The hash to normalize
76
- #
77
- # @return [Hash] A normalized hash as a new instance
78
- #
79
- def normalize_config!(input)
80
- raise_errors! do
81
- normalize_config(input)
82
- end
83
- end
84
-
85
- #
86
- # Normalize a config hash
87
- # Used internally by .normalize_config, but is available for utility
88
- #
89
- # @param config [Hash] Config representation as a Hash
90
- #
91
- # @return [Array] Two item array
92
- # First - The normalized hash
93
- # Second - Array of errors, if any
94
- #
95
- # @private
96
- #
97
- def normalize_config(config)
98
- raise InvalidTypeError.new(config, Hash, for: "config") unless Type.hash?(config)
99
-
100
- Normalizer::Config.new("config", config).normalize
101
- end
102
- end
103
- end
104
- end
@@ -1,19 +0,0 @@
1
- # Sets the base URL prefix for all API requests. All test paths will be appended to this URL.
2
- base_url: http://localhost:3000
3
-
4
- # Configures the global authorization header and value for API requests.
5
- authorization:
6
- default:
7
- header: Authorization
8
- value: <%= default_authorization_value %>
9
-
10
- factories:
11
- ## Optional: Overrides default FactoryBot definition paths for discovering factories
12
- ## By default, FactoryBot will look in "spec/factories" and "test/factories"
13
- # paths:
14
- # - custom/factories/path
15
-
16
- ## Optional: Enable/disable automatic factory discovery, default: true
17
- ## Note: Disabling auto discovery will only disable FactoryBot's auto discovery. Any factories
18
- ## defined in "spec_forge/factories" will still be loaded.
19
- # auto_discover: false
@@ -1,19 +0,0 @@
1
- # Sets the base URL prefix for all API requests. All test paths will be appended to this URL.
2
- base_url: http://localhost:3000
3
-
4
- # Configures the global authorization header and value for API requests.
5
- authorization:
6
- default:
7
- header: Authorization
8
- value: Bearer <%= ENV.fetch("API_TOKEN", "") %>
9
-
10
- factories:
11
- ## Optional: Overrides default FactoryBot definition paths for discovering factories
12
- ## By default, FactoryBot will look in "spec/factories" and "test/factories"
13
- # paths:
14
- # - custom/factories/path
15
-
16
- ## Optional: Enable/disable automatic factory discovery, default: true
17
- ## Note: Disabling auto discovery will only disable FactoryBot's auto discovery. Any factories
18
- ## defined in "spec_forge/factories" will still be loaded.
19
- # auto_discover: false