fixtury 0.4.1 → 1.0.0.beta1

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.
@@ -1,159 +1,130 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fixtury/store"
3
+ require "fixtury"
4
4
  require "active_support/core_ext/class/attribute"
5
5
 
6
6
  module Fixtury
7
7
  module TestHooks
8
8
 
9
- extend ::ActiveSupport::Concern
10
-
11
- included do
12
- class_attribute :fixtury_dependencies
13
- self.fixtury_dependencies = Set.new
9
+ def self.prepended(klass)
10
+ klass.class_attribute :fixtury_dependencies
11
+ klass.fixtury_dependencies = Set.new
12
+ klass.extend ClassMethods
13
+ end
14
14
 
15
- class_attribute :local_fixtury_dependencies
16
- self.local_fixtury_dependencies = Set.new
15
+ def self.included(klass)
16
+ raise ArgumentError, "#{name} should be prepended, not included"
17
17
  end
18
18
 
19
19
  module ClassMethods
20
20
 
21
- def fixtury(*names, &definition)
22
- opts = names.extract_options!
23
-
24
- # define fixtures if blocks are given
25
- if block_given?
26
- raise ArgumentError, "A fixture cannot be defined in an anonymous class" if name.nil?
27
-
28
- namespace = fixtury_namespace
29
-
30
- ns = ::Fixtury.schema
31
-
32
- namespace.split("/").each do |ns_name|
33
- ns = ns.namespace(ns_name){}
34
- end
21
+ def fixtury_store
22
+ ::Fixtury.store
23
+ end
35
24
 
36
- names.map! do |fixture_name|
37
- ns.fixture(fixture_name, &definition)
38
- new_name = "/#{namespace}/#{fixture_name}"
39
- self.local_fixtury_dependencies += [new_name]
40
- new_name
41
- end
25
+ def fixtury_schema
26
+ ::Fixtury.schema
27
+ end
42
28
 
43
- # otherwise, just record the dependency
44
- else
45
- self.fixtury_dependencies += names.flatten.compact.map(&:to_s)
29
+ def fixtury(*searches, **opts)
30
+ pathnames = searches.map do |search|
31
+ dfn = fixtury_schema.get!(search)
32
+ dfn.pathname
46
33
  end
47
34
 
35
+ self.fixtury_dependencies += pathnames
36
+
48
37
  accessor_option = opts[:as]
49
38
  accessor_option = opts[:accessor] if accessor_option.nil? # old version, backwards compatability
50
39
  accessor_option = accessor_option.nil? ? true : accessor_option
51
40
 
52
41
  if accessor_option
53
42
 
54
- if accessor_option != true && names.length > 1
43
+ if accessor_option != true && pathnames.length > 1
55
44
  raise ArgumentError, "A named :as option is only available when providing one fixture"
56
45
  end
57
46
 
58
- names.each do |fixture_name|
59
- method_name = accessor_option == true ? fixture_name.split("/").last : accessor_option
60
- ivar = :"@#{method_name}"
47
+ pathnames.each do |pathname|
48
+ method_name = (accessor_option == true ? pathname.split("/").last : accessor_option).to_sym
49
+
50
+ if method_defined?(method_name)
51
+ raise ArgumentError, "A method by the name of #{method_name} already exists in #{self}"
52
+ end
53
+
54
+ ivar = :"@fixtury_#{method_name}"
61
55
 
62
56
  class_eval <<-EV, __FILE__, __LINE__ + 1
63
57
  def #{method_name}
64
58
  return #{ivar} if defined?(#{ivar})
65
59
 
66
- value = fixtury("#{fixture_name}")
67
- #{ivar} = value
60
+ #{ivar} = fixtury("#{pathname}")
68
61
  end
69
62
  EV
70
63
  end
71
64
  end
72
65
  end
73
66
 
74
- def fixtury_namespace
75
- name.underscore
76
- end
67
+ end
77
68
 
69
+ def before_setup(...)
70
+ fixtury_setup if fixtury_dependencies.any?
71
+ super
78
72
  end
79
73
 
80
- def fixtury(name)
81
- return nil unless fixtury_store
74
+ def after_teardown(...)
75
+ super
76
+ fixtury_teardown if fixtury_dependencies.any?
77
+ end
82
78
 
83
- name = name.to_s
84
79
 
85
- # in the case that we're looking for a relative fixture, see if it's registered relative to the test's namespace.
86
- unless name.include?("/")
87
- local_name = "/#{self.class.fixtury_namespace}/#{name}"
88
- if local_fixtury_dependencies.include?(local_name)
89
- return fixtury_store.get(local_name, execution_context: self)
90
- end
91
- end
80
+ def fixtury(name)
81
+ return nil unless self.class.fixtury_store
92
82
 
93
- unless fixtury_dependencies.include?(name) || local_fixtury_dependencies.include?(name)
94
- raise ArgumentError, "Unrecognized fixtury dependency `#{name}` for #{self.class}"
95
- end
83
+ dfn = self.class.fixtury_schema.get!(name)
96
84
 
97
- fixtury_store.get(name, execution_context: self)
98
- end
85
+ unless fixtury_dependencies.include?(dfn.pathname)
86
+ raise Errors::UnknownTestDependencyError, "Unrecognized fixtury dependency `#{dfn.pathname}` for #{self.class}"
87
+ end
99
88
 
100
- def fixtury_store
101
- ::Fixtury::Store.instance
89
+ self.class.fixtury_store.get(dfn.pathname)
102
90
  end
103
91
 
104
92
  def fixtury_loaded?(name)
105
- return false unless fixtury_store
93
+ return false unless self.class.fixtury_store
106
94
 
107
- fixtury_store.loaded?(name)
95
+ self.class.fixtury_store.loaded?(name)
108
96
  end
109
97
 
110
98
  def fixtury_database_connections
111
- ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
112
- end
113
-
114
- # piggybacking activerecord fixture setup for now.
115
- def setup_fixtures(*args)
116
- if fixtury_dependencies.any? || local_fixtury_dependencies.any?
117
- setup_fixtury_fixtures
118
- else
119
- super
120
- end
121
- end
122
-
123
- # piggybacking activerecord fixture setup for now.
124
- def teardown_fixtures(*args)
125
- if fixtury_dependencies.any? || local_fixtury_dependencies.any?
126
- teardown_fixtury_fixtures
127
- else
128
- super
129
- end
99
+ ActiveRecord::Base.connection_handler.connection_pool_list(:writing).map(&:connection)
130
100
  end
131
101
 
132
- def setup_fixtury_fixtures
102
+ def fixtury_setup
103
+ fixtury_clear_stale_fixtures!
104
+ fixtury_load_all_fixtures!
133
105
  return unless fixtury_use_transactions?
134
106
 
135
- clear_expired_fixtury_fixtures!
136
- load_all_fixtury_fixtures!
137
-
138
107
  fixtury_database_connections.each do |conn|
139
108
  conn.begin_transaction joinable: false
140
109
  end
141
110
  end
142
111
 
143
- def teardown_fixtury_fixtures
112
+ def fixtury_teardown
144
113
  return unless fixtury_use_transactions?
145
114
 
146
- fixtury_database_connections.each(&:rollback_transaction)
115
+ fixtury_database_connections.each do |conn|
116
+ conn.rollback_transaction if conn.open_transactions.positive?
117
+ end
147
118
  end
148
119
 
149
- def clear_expired_fixtury_fixtures!
150
- return unless fixtury_store
120
+ def fixtury_clear_stale_fixtures!
121
+ return unless self.class.fixtury_store
151
122
 
152
- fixtury_store.clear_expired_references!
123
+ self.class.fixtury_store.clear_stale_references!
153
124
  end
154
125
 
155
- def load_all_fixtury_fixtures!
156
- (fixtury_dependencies | local_fixtury_dependencies).each do |name|
126
+ def fixtury_load_all_fixtures!
127
+ fixtury_dependencies.each do |name|
157
128
  unless fixtury_loaded?(name)
158
129
  ::Fixtury.log("preloading #{name.inspect}", name: "test", level: ::Fixtury::LOG_LEVEL_INFO)
159
130
  fixtury(name)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fixtury
4
4
 
5
- VERSION = "0.4.1"
5
+ VERSION = "1.0.0.beta1"
6
6
 
7
7
  end
data/lib/fixtury.rb CHANGED
@@ -1,14 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/concern"
4
+ require "active_support/core_ext/array/extract_options"
4
5
  require "active_support/core_ext/module/attribute_accessors"
5
6
  require "active_support/core_ext/module/delegation"
7
+ require "active_support/core_ext/object/acts_like"
8
+ require "active_support/core_ext/object/blank"
9
+
6
10
  require "fixtury/version"
7
- require "fixtury/schema"
11
+
12
+ require "fixtury/definition_executor"
13
+ require "fixtury/dependency"
14
+ require "fixtury/dependency_store"
15
+ require "fixtury/errors"
16
+ require "fixtury/hooks"
8
17
  require "fixtury/locator"
18
+ require "fixtury/path_resolver"
19
+ require "fixtury/reference"
9
20
  require "fixtury/store"
10
21
 
11
- # Top level namespace of the gem
22
+ require "fixtury/schema_node"
23
+ require "fixtury/definition"
24
+ require "fixtury/schema"
25
+
26
+
27
+ # Top level namespace of the gem. The accessors provided on the Fixtury namespace are meant to be shared
28
+ # across the entire application. The Fixtury::Schema instance is the primary interface for defining and
29
+ # accessing fixtures and can be accessed via Fixtury.schema.
12
30
  module Fixtury
13
31
 
14
32
  LOG_LEVELS = {
@@ -26,10 +44,28 @@ module Fixtury
26
44
  schema
27
45
  end
28
46
 
47
+ # Global hooks accessor. Fixtury will call these hooks at various points in the lifecycle of a fixture or setup.
48
+ def self.hooks
49
+ @hooks ||= ::Fixtury::Hooks.new
50
+ end
51
+
29
52
  # The default top level schema. Fixtury::Schema instances can be completely self-contained but most
30
53
  # usage would be through this shared definition.
31
54
  def self.schema
32
- @schema ||= ::Fixtury::Schema.new(parent: nil, name: "")
55
+ @schema ||= ::Fixtury::Schema.new
56
+ end
57
+
58
+ def self.schema=(schema)
59
+ @schema = schema
60
+ end
61
+
62
+ # Default store for fixtures. This is a shared store that can be used across the application.
63
+ def self.store
64
+ @store ||= ::Fixtury::Store.new(schema: schema)
65
+ end
66
+
67
+ def self.store=(store)
68
+ @store = store
33
69
  end
34
70
 
35
71
  def self.log_level
@@ -41,7 +77,7 @@ module Fixtury
41
77
  @log_level
42
78
  end
43
79
 
44
- def self.log(text = nil, level: LOG_LEVEL_DEBUG, name: nil)
80
+ def self.log(text = nil, level: LOG_LEVEL_DEBUG, name: nil, newline: true)
45
81
  desired_level = LOG_LEVELS.fetch(log_level) { DEFAULT_LOG_LEVEL }
46
82
  return if desired_level == LOG_LEVEL_NONE
47
83
 
@@ -53,7 +89,10 @@ module Fixtury
53
89
  msg << "]"
54
90
  msg << " #{text}" if text
55
91
  msg << " #{yield}" if block_given?
56
- puts msg
92
+ msg << "\n" if newline
93
+
94
+ print msg
95
+ msg
57
96
  end
58
97
 
59
98
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fixtury
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-05 00:00:00.000000000 Z
11
+ date: 2024-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: autotest
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,21 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '2.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: byebug
42
+ name: globalid
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: globalid
56
+ name: activerecord
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,21 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: minitest
70
+ name: m
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '5.0'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '5.0'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: minitest-reporters
84
+ name: minitest
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -112,18 +112,18 @@ dependencies:
112
112
  name: rake
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '13.0'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '13.0'
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: sqlite
126
+ name: sqlite3
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description:
139
+ description:
140
140
  email:
141
141
  - mike@guideline.com
142
142
  executables: []
@@ -156,20 +156,20 @@ files:
156
156
  - lib/fixtury.rb
157
157
  - lib/fixtury/definition.rb
158
158
  - lib/fixtury/definition_executor.rb
159
- - lib/fixtury/errors/already_defined_error.rb
160
- - lib/fixtury/errors/circular_dependency_error.rb
161
- - lib/fixtury/errors/fixture_not_defined_error.rb
162
- - lib/fixtury/errors/option_collision_error.rb
163
- - lib/fixtury/errors/schema_frozen_error.rb
164
- - lib/fixtury/errors/unrecognizable_locator_error.rb
159
+ - lib/fixtury/dependency.rb
160
+ - lib/fixtury/dependency_store.rb
161
+ - lib/fixtury/errors.rb
162
+ - lib/fixtury/hooks.rb
165
163
  - lib/fixtury/locator.rb
166
164
  - lib/fixtury/locator_backend/common.rb
167
165
  - lib/fixtury/locator_backend/globalid.rb
168
166
  - lib/fixtury/locator_backend/memory.rb
169
- - lib/fixtury/path.rb
167
+ - lib/fixtury/mutation_observer.rb
168
+ - lib/fixtury/path_resolver.rb
170
169
  - lib/fixtury/railtie.rb
171
170
  - lib/fixtury/reference.rb
172
171
  - lib/fixtury/schema.rb
172
+ - lib/fixtury/schema_node.rb
173
173
  - lib/fixtury/store.rb
174
174
  - lib/fixtury/tasks.rake
175
175
  - lib/fixtury/test_hooks.rb
@@ -181,7 +181,7 @@ metadata:
181
181
  homepage_uri: https://github.com/guideline-tech/fixtury
182
182
  source_code_uri: https://github.com/guideline-tech/fixtury
183
183
  changelog_uri: https://github.com/guideline-tech/fixtury
184
- post_install_message:
184
+ post_install_message:
185
185
  rdoc_options: []
186
186
  require_paths:
187
187
  - lib
@@ -196,8 +196,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
196
  - !ruby/object:Gem::Version
197
197
  version: '0'
198
198
  requirements: []
199
- rubygems_version: 3.0.6
200
- signing_key:
199
+ rubygems_version: 3.5.6
200
+ signing_key:
201
201
  specification_version: 4
202
202
  summary: Treat fixtures like factories and factories like fixtures
203
203
  test_files: []
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- module Errors
5
- class AlreadyDefinedError < ::StandardError
6
-
7
- def initialize(name)
8
- super("An element identified by `#{name}` already exists.")
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- module Errors
5
- class CircularDependencyError < ::StandardError
6
-
7
- def initialize(name)
8
- super("One of the dependencies of #{name} is dependent on #{name}.")
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- module Errors
5
- class FixtureNotDefinedError < ::StandardError
6
-
7
- def initialize(name)
8
- super("A fixture identified by `#{name}` does not exist.")
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- module Errors
5
- class OptionCollisionError < ::StandardError
6
-
7
- def initialize(schema_name, option_key, old_value, new_value)
8
- super("The #{schema_name.inspect} schema #{option_key.inspect} option value of #{old_value.inspect} conflicts with the new value #{new_value.inspect}.")
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- module Errors
5
- class SchemaFrozenError < ::StandardError
6
-
7
- def initialize
8
- super("Schema is frozen. New namespaces, definitions, and enhancements are not allowed.")
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- module Fixtury
2
- module Errors
3
- class UnrecognizableLocatorError < ::StandardError
4
-
5
- def initialize(action, thing)
6
- super("Locator did not reognize #{thing} during #{action}")
7
- end
8
-
9
- end
10
- end
11
- end
data/lib/fixtury/path.rb DELETED
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fixtury
4
- class Path
5
-
6
- def initialize(namespace:, path:)
7
- @namespace = namespace.to_s
8
- @path = path.to_s
9
- @full_path = (
10
- @path.start_with?("/") ?
11
- @path :
12
- File.expand_path(::File.join(@namespace, @path), "/")
13
- )
14
- @segments = @full_path.split("/")
15
- end
16
-
17
- def top_level_namespace
18
- return "" if @segments.size == 1
19
-
20
- @segments.first
21
- end
22
-
23
- def relative?
24
- @path.start_with?(".")
25
- end
26
-
27
- def possible_absolute_paths
28
- @possible_absolute_paths ||= begin
29
- out = [@full_path]
30
- out << @path unless relative?
31
- out
32
- end
33
- end
34
-
35
- end
36
- end