fixtury 0.1.0.alpha → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73b1b15d6ac9941d265b535f8510cc2896eb4c3fc711af20339b045228e8a888
4
- data.tar.gz: ca6171cdfc7c721a88dc6e4055db600e10897894295b40022e45e7a55c5c5497
3
+ metadata.gz: 7a4447982d6e785c9158850f3d158b07e1226f6a05d85917d41307c5455d41d9
4
+ data.tar.gz: c7fac4726892a1851ca7b7f0d3ff8abfe2bbedf4d2706b2c3ae6443d6be863f1
5
5
  SHA512:
6
- metadata.gz: d892685cc0b8a4f54c09c188d1afc0dcc8928008f072c76bf18f0fed7ace0c49d194070d61b65dc4653c528b321f08e4ba3adb59cd2d33a192b4e3f984c09776
7
- data.tar.gz: cceeab65fe5c416067a7be5ae8fd3c9dc65d73fcf5c812ffc89ba695d60fcae5790414baeea1e43d9c098279e8dddc8a87eede66f275eeb02bfaf11fb1c447f3
6
+ metadata.gz: 6c5858894f02eb54b555df7ee182e81e3741cbd278e37bbd0a3250b9cfea62a00341d3ff95a75adb0d5f56cfd3abcdb036877bee28601b87ff060c3e9bf6f43c
7
+ data.tar.gz: 0e99678f39920cd68026905ddd202ea8b9f9648c3bef9e941e7fd084fb2daa1ed843b5d2839fc10cbf13f1cc27c224ac212d7cd01173b2f3f8692706cadde2cb
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fixtury (0.1.0.alpha)
4
+ fixtury (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -61,4 +61,4 @@ DEPENDENCIES
61
61
  sqlite
62
62
 
63
63
  BUNDLED WITH
64
- 2.0.2
64
+ 2.1.4
@@ -25,6 +25,8 @@ module Fixtury
25
25
  end
26
26
 
27
27
  def call(store: nil, execution_context: nil)
28
+ execution_context ||= ::Fixtury::ExecutionContext.new
29
+
28
30
  maybe_set_store_context(store: store) do
29
31
  value = run_callable(store: store, callable: callable, execution_context: execution_context, value: nil)
30
32
  enhancements.each do |e|
@@ -45,8 +47,6 @@ module Fixtury
45
47
  end
46
48
 
47
49
  def run_callable(store:, callable:, execution_context:, value:)
48
- execution_context ||= self
49
-
50
50
  args = []
51
51
  args << value unless value.nil?
52
52
  if callable.arity > args.length
@@ -55,11 +55,24 @@ module Fixtury
55
55
  args << store
56
56
  end
57
57
 
58
- if args.length.positive?
59
- execution_context.instance_exec(*args, &callable)
58
+ execution_context_hooks(execution_context) do
59
+ if args.length.positive?
60
+ execution_context.instance_exec(*args, &callable)
61
+ else
62
+ execution_context.instance_eval(&callable)
63
+ end
64
+ end
65
+ end
66
+
67
+ def execution_context_hooks(execution_context)
68
+ execution_context.before_fixture(self) if execution_context.respond_to?(:before_fixture)
69
+ value = if execution_context.respond_to?(:around_fixture)
70
+ execution_context.around_fixture(self) { yield }
60
71
  else
61
- execution_context.instance_eval(&callable)
72
+ yield
62
73
  end
74
+ execution_context.after_fixture(self, value) if execution_context.respond_to?(:after_fixture)
75
+ value
63
76
  end
64
77
 
65
78
  end
@@ -5,7 +5,7 @@ module Fixtury
5
5
  class CircularDependencyError < ::StandardError
6
6
 
7
7
  def initialize(name)
8
- super("One of the depdencies of #{name} is dependent on #{name}.")
8
+ super("One of the dependencies of #{name} is dependent on #{name}.")
9
9
  end
10
10
 
11
11
  end
@@ -4,5 +4,13 @@
4
4
  module Fixtury
5
5
  class ExecutionContext
6
6
 
7
+ def before_fixture(_dfn); end
8
+
9
+ def around_fixture(_dfn)
10
+ yield
11
+ end
12
+
13
+ def after_fixture(_dfn, _value); end
14
+
7
15
  end
8
16
  end
@@ -24,6 +24,12 @@ module Fixtury
24
24
  @backend = backend
25
25
  end
26
26
 
27
+ def recognize?(ref)
28
+ raise ArgumentError, "Unable to recognize a nil ref" if ref.nil?
29
+
30
+ backend.recognized_reference?(ref)
31
+ end
32
+
27
33
  def load(ref)
28
34
  raise ArgumentError, "Unable to load a nil ref" if ref.nil?
29
35
 
@@ -1,6 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Fixtury
2
4
  class Reference
3
5
 
6
+ HOLDER_VALUE = "__BUILDING_FIXTURE__"
7
+
8
+ def self.holder(name)
9
+ new(name, HOLDER_VALUE)
10
+ end
11
+
4
12
  attr_reader :name, :value, :created_at
5
13
 
6
14
  def initialize(name, value)
@@ -9,5 +17,13 @@ module Fixtury
9
17
  @created_at = Time.now.to_i
10
18
  end
11
19
 
20
+ def holder?
21
+ value == HOLDER_VALUE
22
+ end
23
+
24
+ def real?
25
+ !holder?
26
+ end
27
+
12
28
  end
13
29
  end
@@ -67,7 +67,7 @@ module Fixtury
67
67
  ensure_no_conflict!(name: name, definitions: true, namespaces: false)
68
68
 
69
69
  child = find_or_create_child_schema(name: name)
70
- child.instance_eval(&block)
70
+ child.instance_eval(&block) if block_given?
71
71
  child
72
72
  end
73
73
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fileutils"
3
4
  require "singleton"
4
5
  require "yaml"
5
6
  require "fixtury/locator"
@@ -10,29 +11,36 @@ require "fixtury/reference"
10
11
  module Fixtury
11
12
  class Store
12
13
 
13
- cattr_accessor :instance
14
+ LOG_LEVELS = {
15
+ (LOG_LEVEL_NONE = :none) => 0,
16
+ (LOG_LEVEL_INFO = :info) => 1,
17
+ (LOG_LEVEL_DEBUG = :debug) => 2,
18
+ }.freeze
14
19
 
15
- HOLDER = "__BUILDING_FIXTURE__"
20
+ cattr_accessor :instance
16
21
 
17
22
  attr_reader :filepath, :references, :ttl, :auto_refresh_expired
18
23
  attr_reader :schema, :locator
19
- attr_reader :verbose
24
+ attr_reader :log_level
20
25
  attr_reader :execution_context
21
26
 
22
27
  def initialize(
23
28
  filepath: nil,
24
29
  locator: ::Fixtury::Locator.instance,
25
- verbose: false,
30
+ log_level: nil,
26
31
  ttl: nil,
27
32
  schema: nil,
33
+ execution_context: nil,
28
34
  auto_refresh_expired: false
29
35
  )
30
36
  @schema = schema || ::Fixtury.schema
31
- @verbose = verbose
37
+ @log_level = log_level.nil? ? ENV["FIXTURY_LOG_LEVEL"] : log_level
38
+ @log_level ||= LOG_LEVEL_NONE
39
+ @log_level = @log_level.to_s.to_sym
32
40
  @locator = locator
33
41
  @filepath = filepath
34
42
  @references = @filepath && ::File.file?(@filepath) ? ::YAML.load_file(@filepath) : {}
35
- @execution_context = ::Fixtury::ExecutionContext.new
43
+ @execution_context = execution_context || ::Fixtury::ExecutionContext.new
36
44
  @ttl = ttl ? ttl.to_i : ttl
37
45
  @auto_refresh_expired = !!auto_refresh_expired
38
46
  self.class.instance ||= self
@@ -41,15 +49,21 @@ module Fixtury
41
49
  def dump_to_file
42
50
  return unless filepath
43
51
 
44
- ::File.open(filepath, "wb") { |io| io.write(references.to_yaml) }
52
+ ::FileUtils.mkdir_p(File.dirname(filepath))
53
+
54
+ writable = references.each_with_object({}) do |(full_name, ref), h|
55
+ h[full_name] = ref if ref.real?
56
+ end
57
+
58
+ ::File.open(filepath, "wb") { |io| io.write(writable.to_yaml) }
45
59
  end
46
60
 
47
61
  def clear_expired_references!
48
62
  return unless ttl
49
63
 
50
64
  references.delete_if do |name, ref|
51
- is_expired = ref_expired?(ref)
52
- log { "expiring #{name}" } if is_expired
65
+ is_expired = ref_invalid?(ref)
66
+ log(level: LOG_LEVEL_INFO) { "expiring #{name}" } if is_expired
53
67
  is_expired
54
68
  end
55
69
  end
@@ -59,7 +73,7 @@ module Fixtury
59
73
  get(dfn.name)
60
74
  end
61
75
 
62
- schema.schemas.each_pair do |_key, ns|
76
+ schema.children.each_pair do |_key, ns|
63
77
  load_all(ns)
64
78
  end
65
79
  end
@@ -71,7 +85,7 @@ module Fixtury
71
85
  pattern = pattern[0...-1] if glob
72
86
  references.delete_if do |key, _value|
73
87
  hit = glob ? key.start_with?(pattern) : key == pattern
74
- log(true) { "clearing #{key}" } if hit
88
+ log(level: LOG_LEVEL_INFO) { "clearing #{key}" } if hit
75
89
  hit
76
90
  end
77
91
  dump_to_file
@@ -89,8 +103,8 @@ module Fixtury
89
103
  dfn = schema.get_definition!(name)
90
104
  full_name = dfn.name
91
105
  ref = references[full_name]
92
- result = ref && ref != HOLDER
93
- log { result ? "hit #{full_name}" : "miss #{full_name}" }
106
+ result = ref&.real?
107
+ log(level: LOG_LEVEL_DEBUG) { result ? "hit #{full_name}" : "miss #{full_name}" }
94
108
  result
95
109
  end
96
110
 
@@ -99,34 +113,34 @@ module Fixtury
99
113
  full_name = dfn.name
100
114
  ref = references[full_name]
101
115
 
102
- if ref == HOLDER
116
+ if ref&.holder?
103
117
  raise ::Fixtury::Errors::CircularDependencyError, full_name
104
118
  end
105
119
 
106
- if ref && auto_refresh_expired && ref_expired?(ref)
107
- log { "refreshing #{full_name}" }
108
- clear_ref(ref)
120
+ if ref && auto_refresh_expired && ref_invalid?(ref)
121
+ log(level: LOG_LEVEL_INFO) { "refreshing #{full_name}" }
122
+ clear_ref(full_name)
109
123
  ref = nil
110
124
  end
111
125
 
112
126
  value = nil
113
127
 
114
128
  if ref
115
- log { "hit #{full_name}" }
129
+ log(level: LOG_LEVEL_DEBUG) { "hit #{full_name}" }
116
130
  value = load_ref(ref.value)
117
- unless value
131
+ if value.nil?
118
132
  clear_ref(full_name)
119
- log { "missing #{full_name}" }
133
+ log(level: LOG_LEVEL_DEBUG) { "missing #{full_name}" }
120
134
  end
121
135
  end
122
136
 
123
137
  if value.nil?
124
- # set the references to HOLDER so any recursive behavior ends up hitting a circular dependency error if the same fixture load is attempted
125
- references[full_name] = HOLDER
138
+ # set the references to a holder value so any recursive behavior ends up hitting a circular dependency error if the same fixture load is attempted
139
+ references[full_name] = ::Fixtury::Reference.holder(full_name)
126
140
 
127
141
  value = dfn.call(store: self, execution_context: execution_context)
128
142
 
129
- log { "store #{full_name}" }
143
+ log(level: LOG_LEVEL_INFO) { "store #{full_name}" }
130
144
 
131
145
  ref = dump_ref(full_name, value)
132
146
  ref = ::Fixtury::Reference.new(full_name, ref)
@@ -149,16 +163,20 @@ module Fixtury
149
163
  references.delete(name)
150
164
  end
151
165
 
152
- def ref_expired?(ref)
153
- return false unless ttl
166
+ def ref_invalid?(ref)
167
+ return true if ttl && ref.created_at < (Time.now.to_i - ttl)
154
168
 
155
- ref.created_at < (Time.now.to_i - ttl)
169
+ !locator.recognize?(ref.value)
156
170
  end
157
171
 
158
- def log(local_verbose = false, &block)
159
- return unless verbose || local_verbose
172
+ def log(level: LOG_LEVEL_DEBUG, name: "store")
173
+ desired_level = LOG_LEVELS.fetch(log_level) { LOG_LEVEL_NONE }
174
+ return if desired_level == LOG_LEVEL_NONE
175
+
176
+ message_level = LOG_LEVELS.fetch(level) { LOG_LEVEL_DEBUG }
177
+ return unless desired_level >= message_level
160
178
 
161
- puts "[fixtury|store] #{block.call}"
179
+ puts "[fixtury|#{name}] #{yield}"
162
180
  end
163
181
 
164
182
  end
@@ -3,7 +3,7 @@
3
3
  require "fixtury/store"
4
4
 
5
5
  module Fixtury
6
- module Hooks
6
+ module TestHooks
7
7
 
8
8
  extend ::ActiveSupport::Concern
9
9
 
@@ -18,15 +18,45 @@ module Fixtury
18
18
  self.fixtury_dependencies += names.flatten.compact.map(&:to_s)
19
19
  end
20
20
 
21
+ def define_fixture(name, &block)
22
+ fixture_name = name
23
+ namespace_names = self.name.underscore.split("/")
24
+
25
+ ns = ::Fixtury.schema
26
+
27
+ namespace_names.each do |ns_name|
28
+ ns = ns.namespace(ns_name){}
29
+ end
30
+
31
+ ns.fixture(fixture_name, &block)
32
+
33
+ fixtury("#{namespace_names.join("/")}/#{fixture_name}")
34
+ end
35
+
21
36
  end
22
37
 
23
38
  def fixtury(name)
24
- raise ArgumentError unless self.fixtury_dependencies.include?(name.to_s)
39
+ return nil unless ::Fixtury::Store.instance
40
+
41
+ name = name.to_s
42
+
43
+ unless name.include?("/")
44
+ local_name = "#{self.class.name.underscore}/#{name}"
45
+ if self.fixtury_dependencies.include?(local_name)
46
+ return ::Fixtury::Store.instance.get(local_name)
47
+ end
48
+ end
49
+
50
+ unless self.fixtury_dependencies.include?(name)
51
+ raise ArgumentError, "Unrecognized fixtury dependency `#{name}` for #{self.class}"
52
+ end
25
53
 
26
54
  ::Fixtury::Store.instance.get(name)
27
55
  end
28
56
 
29
57
  def fixtury_loaded?(name)
58
+ return false unless ::Fixtury::Store.instance
59
+
30
60
  ::Fixtury::Store.instance.loaded?(name)
31
61
  end
32
62
 
@@ -70,6 +100,8 @@ module Fixtury
70
100
  end
71
101
 
72
102
  def clear_expired_fixtury_fixtures!
103
+ return unless ::Fixtury::Store.instance
104
+
73
105
  ::Fixtury::Store.instance.clear_expired_references!
74
106
  end
75
107
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fixtury
4
4
 
5
- VERSION = "0.1.0.alpha"
5
+ VERSION = "0.1.0"
6
6
 
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fixtury
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-07 00:00:00.000000000 Z
11
+ date: 2020-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: autotest
@@ -161,7 +161,6 @@ files:
161
161
  - lib/fixtury/errors/schema_frozen_error.rb
162
162
  - lib/fixtury/errors/unrecognizable_locator_error.rb
163
163
  - lib/fixtury/execution_context.rb
164
- - lib/fixtury/hooks.rb
165
164
  - lib/fixtury/locator.rb
166
165
  - lib/fixtury/locator_backend/common.rb
167
166
  - lib/fixtury/locator_backend/globalid.rb
@@ -172,6 +171,7 @@ files:
172
171
  - lib/fixtury/schema.rb
173
172
  - lib/fixtury/store.rb
174
173
  - lib/fixtury/tasks.rake
174
+ - lib/fixtury/test_hooks.rb
175
175
  - lib/fixtury/version.rb
176
176
  homepage: https://github.com/guideline-tech/fixtury
177
177
  licenses: []
@@ -191,9 +191,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
191
  version: '0'
192
192
  required_rubygems_version: !ruby/object:Gem::Requirement
193
193
  requirements:
194
- - - ">"
194
+ - - ">="
195
195
  - !ruby/object:Gem::Version
196
- version: 1.3.1
196
+ version: '0'
197
197
  requirements: []
198
198
  rubygems_version: 3.0.6
199
199
  signing_key: