fixture_kit 0.1.1 → 0.2.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: fb41bba5897198dbdad616b7b1a44c02cb770b8150e9c005051e16a1935f8508
4
- data.tar.gz: 8e5cb1af113f6fd2f56a0aac8727f2a2666a89fe1fe87b9499fc4c6951b94d02
3
+ metadata.gz: 311fd09f37153fae9d8a09e3e41357c38f18e1e343794a758ae943dfdca3c40a
4
+ data.tar.gz: ee4257fc3c840f809a25204f300c766f872688c5c7417dc22155f001ba424882
5
5
  SHA512:
6
- metadata.gz: c67e3477b6f2e4b8fb8f9d2ba480c2b37fd73fba173178662d7d20d6ce3c7737b483d1308faa7f5f9a60ce9f1a5b27076988b8bfdf48949ff5944b5d39d988a9
7
- data.tar.gz: 054d623d8e2418720ff73c08a3699dd30471511060ed1581d977da215872e9eae902a0d84439499c816004ceebfbf624c2ac2e1bc91b3f0491231c9a191c3fbd
6
+ metadata.gz: bd8c58de66c08eeceab67e4f0b83a8a95d25291401272e96b51725db2b7a9f2b2592c24f1d6f6cb7b4f6b4716fa93fc768c4fc81afcf1974b9339e14b1b61fa9
7
+ data.tar.gz: 8d335927771e40d35142a69ee9bf911fcfb6c660af6cde28269a16643e86a468c017cf2f54e362f09d90a78bfeffe6320071d0230f6240969fc495de0e91c8f2
data/README.md CHANGED
@@ -104,6 +104,8 @@ RSpec.describe Book do
104
104
  end
105
105
  ```
106
106
 
107
+ `fixture` returns a `Repository` and exposes records as methods (for example, `fixture.owner`).
108
+
107
109
  ### 3. Configure RSpec
108
110
 
109
111
  ```ruby
@@ -128,14 +130,25 @@ FixtureKit.configure do |config|
128
130
 
129
131
  # Whether to regenerate caches on every run (default: true)
130
132
  config.autogenerate = true
133
+
134
+ # Optional: customize how pregeneration is wrapped.
135
+ # Default is FixtureKit::TestCase::Generator.
136
+ # config.generator = FixtureKit::TestCase::Generator
131
137
  end
132
138
  ```
133
139
 
140
+ Custom generators should subclass `FixtureKit::Generator` and implement `#run`.
141
+ `#run` receives the pregeneration block and should execute it in whatever lifecycle you need.
142
+
134
143
  ### Autogenerate
135
144
 
136
145
  When `autogenerate` is `true` (the default), FixtureKit clears all caches at the start of each test run, then regenerates them on first use. Subsequent tests that use the same fixture reuse the cache from earlier in the run. This ensures your test data always matches your fixture definitions.
137
146
 
138
- When `autogenerate` is `false`, FixtureKit pre-generates all fixture caches at suite start. This happens in rolled-back transactions so no data persists to the database. Any fixtures that already have caches are skipped. This mode is useful for CI where you want consistent, predictable cache generation.
147
+ When `autogenerate` is `false`, FixtureKit pre-generates all fixture caches at suite start. This runs through the configured `generator`, and still rolls back database changes.
148
+
149
+ By default, FixtureKit uses `FixtureKit::TestCase::Generator`, which runs pregeneration inside an internal `ActiveSupport::TestCase` so setup/teardown hooks and transactional fixture behavior run as expected. The internal test case is removed from Minitest runnables, so it does not count toward suite totals.
150
+
151
+ When using `fixture_kit/rspec`, FixtureKit sets `FixtureKit::RSpec::Generator` as the generator. This runs pregeneration inside an internal RSpec example so your normal `before`/`around`/`after` hooks apply. The internal example uses a null reporter, so it does not count toward suite example totals.
139
152
 
140
153
  ### Preserving Cache Locally
141
154
 
@@ -6,7 +6,7 @@ require "active_support/core_ext/array/wrap"
6
6
  require "active_support/inflector"
7
7
 
8
8
  module FixtureKit
9
- class FixtureCache
9
+ class Cache
10
10
  # In-memory cache to avoid re-reading/parsing JSON for every test
11
11
  @memory_cache = {}
12
12
 
@@ -15,7 +15,7 @@ module FixtureKit
15
15
 
16
16
  def clear_memory_cache(fixture_name = nil)
17
17
  if fixture_name
18
- @memory_cache.delete(fixture_name.to_s)
18
+ @memory_cache.delete(fixture_name)
19
19
  else
20
20
  @memory_cache.clear
21
21
  end
@@ -34,18 +34,18 @@ module FixtureKit
34
34
  end
35
35
  end
36
36
 
37
- # Pre-generate caches for all fixtures.
37
+ # Generate caches for all fixtures.
38
38
  # Each fixture is generated in a transaction that rolls back, so no data persists.
39
- def pregenerate_all
40
- fixture_path = FixtureKit.configuration.fixture_path
39
+ def generate_all
40
+ Registry.load_definitions
41
+ Registry.fixtures.each { |fixture| generate(fixture.name) }
42
+ end
41
43
 
42
- # First, load all fixture files to register them
43
- FixtureRegistry.load_definitions(fixture_path)
44
+ def generate(fixture_name)
45
+ clear(fixture_name)
44
46
 
45
- # Then iterate over the registry and generate caches
46
- FixtureRegistry.all_names.each do |name|
47
- runner = FixtureRunner.new(name)
48
- runner.generate_cache_only
47
+ FixtureKit.configuration.generator.run do
48
+ Runner.run(fixture_name, force: true)
49
49
  end
50
50
  end
51
51
  end
@@ -53,7 +53,7 @@ module FixtureKit
53
53
  attr_reader :records, :exposed
54
54
 
55
55
  def initialize(fixture_name)
56
- @fixture_name = fixture_name.to_s
56
+ @fixture_name = fixture_name
57
57
  @records = {}
58
58
  @exposed = {}
59
59
  end
@@ -107,15 +107,15 @@ module FixtureKit
107
107
  File.write(cache_file_path, JSON.pretty_generate(data))
108
108
  end
109
109
 
110
- # Query exposed records from the database and return a FixtureSet
111
- def build_fixture_set
110
+ # Query exposed records from the database and return a Repository.
111
+ def build_repository
112
112
  exposed_records = @exposed.each_with_object({}) do |(name, value), hash|
113
113
  was_array = value.is_a?(Array)
114
114
  records = Array.wrap(value).map { |record_info| find_exposed_record(record_info.fetch("model"), record_info.fetch("id"), name) }
115
115
  hash[name.to_sym] = was_array ? records : records.first
116
116
  end
117
117
 
118
- FixtureSet.new(exposed_records)
118
+ Repository.new(exposed_records)
119
119
  end
120
120
 
121
121
  private
@@ -4,11 +4,13 @@ module FixtureKit
4
4
  class Configuration
5
5
  attr_writer :fixture_path
6
6
  attr_writer :cache_path
7
+ attr_accessor :generator
7
8
  attr_accessor :autogenerate
8
9
 
9
10
  def initialize
10
11
  @fixture_path = nil
11
12
  @cache_path = nil
13
+ @generator = FixtureKit::TestCase::Generator
12
14
  @autogenerate = true
13
15
  end
14
16
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FixtureKit
4
- class FixtureContext
4
+ class DefinitionContext
5
5
  attr_reader :exposed
6
6
 
7
7
  def initialize
@@ -5,12 +5,12 @@ module FixtureKit
5
5
  attr_reader :name, :block
6
6
 
7
7
  def initialize(name, &block)
8
- @name = name.to_sym
8
+ @name = name
9
9
  @block = block
10
10
  end
11
11
 
12
12
  def execute
13
- context = FixtureContext.new
13
+ context = DefinitionContext.new
14
14
  context.instance_eval(&block) if block
15
15
  context.exposed
16
16
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FixtureKit
4
+ # Base class for fixture cache generators.
5
+ class Generator
6
+ def self.run(&block)
7
+ new.run(&block)
8
+ end
9
+
10
+ def run
11
+ raise NotImplementedError, "#{self.class} must implement #run"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FixtureKit
4
+ module Registry
5
+ class << self
6
+ def fetch(name)
7
+ fixture = find(name)
8
+ return fixture if fixture
9
+
10
+ file_path = fixture_file_path(name)
11
+ unless File.file?(file_path)
12
+ raise FixtureKit::FixtureDefinitionNotFound,
13
+ "Could not find fixture definition file for '#{name}' at '#{file_path}'"
14
+ end
15
+
16
+ load file_path
17
+ find(name)
18
+ end
19
+
20
+ def find(name)
21
+ registry[name]
22
+ end
23
+
24
+ def fixtures
25
+ registry.values
26
+ end
27
+
28
+ def register(fixture)
29
+ registry[fixture.name] = fixture
30
+ end
31
+
32
+ # Load all fixture definition files.
33
+ # Uses `load` instead of `require` to ensure fixtures are registered
34
+ # even if the files were previously required (e.g., after a reset).
35
+ def load_definitions
36
+ fixture_path = FixtureKit.configuration.fixture_path
37
+ Dir.glob(File.join(fixture_path, "**/*.rb")).each do |file|
38
+ load file
39
+ end
40
+ end
41
+
42
+ def reset
43
+ @registry = nil
44
+ end
45
+
46
+ private
47
+
48
+ def fixture_file_path(name)
49
+ fixture_path = FixtureKit.configuration.fixture_path
50
+ File.expand_path(File.join(fixture_path, "#{name}.rb"))
51
+ end
52
+
53
+ def registry
54
+ @registry ||= {}
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FixtureKit
4
- class FixtureSet
4
+ class Repository
5
5
  def initialize(exposed_records)
6
6
  @records = exposed_records
7
7
  @records.each_value { |value| value.freeze if value.is_a?(Array) }
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FixtureKit
4
+ module RSpec
5
+ class Declaration
6
+ attr_reader :name
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ end
11
+
12
+ def fixture_set
13
+ FixtureKit::Runner.run(name)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FixtureKit
4
+ module RSpec
5
+ class Generator < FixtureKit::Generator
6
+ def run(&block)
7
+ previous_example = ::RSpec.current_example
8
+ previous_scope = ::RSpec.current_scope
9
+ example_group = build_example_group
10
+ example = build_example(example_group, &block)
11
+ instance = example_group.new(example.inspect_output)
12
+ succeeded =
13
+ begin
14
+ example.run(instance, ::RSpec::Core::NullReporter)
15
+ ensure
16
+ example_group.remove_example(example)
17
+ ::RSpec.current_example = previous_example
18
+ ::RSpec.current_scope = previous_scope
19
+ end
20
+
21
+ unless succeeded
22
+ raise example.exception if example.exception
23
+ raise FixtureKit::PregenerationError, "FixtureKit pregeneration failed"
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def build_example(example_group, &block)
30
+ example_group.example(
31
+ "FixtureKit cache pregeneration"
32
+ ) { block.call }
33
+ end
34
+
35
+ def build_example_group
36
+ ::RSpec::Core::ExampleGroup.subclass(
37
+ ::RSpec::Core::ExampleGroup,
38
+ "FixtureKit::RSpec::Generator",
39
+ [],
40
+ []
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,6 +4,12 @@ require "fixture_kit"
4
4
 
5
5
  module FixtureKit
6
6
  module RSpec
7
+ autoload :Declaration, File.expand_path("rspec/declaration", __dir__)
8
+ autoload :Generator, File.expand_path("rspec/generator", __dir__)
9
+
10
+ DECLARATION_METADATA_KEY = :fixture_kit_declaration
11
+ PRESERVE_CACHE_ENV_KEY = "FIXTURE_KIT_PRESERVE_CACHE"
12
+
7
13
  # Class methods (extended via config.extend)
8
14
  module ClassMethods
9
15
  # Declare which fixture to use for this example group.
@@ -26,40 +32,57 @@ module FixtureKit
26
32
  # end
27
33
  # end
28
34
  def fixture(name)
29
- metadata[:fixture_name] = name.to_s
35
+ metadata[DECLARATION_METADATA_KEY] = Declaration.new(name)
30
36
  end
31
37
  end
32
38
 
33
39
  # Instance methods (included via config.include)
34
40
  module InstanceMethods
35
- # Returns the FixtureSet for the current example's fixture.
41
+ # Returns the Repository for the current example's fixture.
36
42
  # Access exposed records as methods: fixture.alice, fixture.posts
37
43
  def fixture
38
- @_fixture_loaded ||= begin
39
- fixture_name = self.class.metadata[:fixture_name]
40
- raise "No fixture declared for this example group. Use `fixture \"name\"` in your describe/context block." unless fixture_name
44
+ @_fixture_kit_fixture_set || raise("No fixture declared for this example group. Use `fixture \"name\"` in your describe/context block.")
45
+ end
46
+ end
47
+
48
+ def self.configure!(config)
49
+ FixtureKit.configuration.generator = Generator
50
+ config.extend ClassMethods
51
+ config.include InstanceMethods
52
+
53
+ # Load declared fixtures at the beginning of each example.
54
+ # Runs inside transactional fixtures and before user-defined before hooks.
55
+ config.prepend_before(:example, DECLARATION_METADATA_KEY) do |example|
56
+ declaration = example.metadata[DECLARATION_METADATA_KEY]
57
+ @_fixture_kit_fixture_set = declaration.fixture_set
58
+ end
41
59
 
42
- FixtureKit::FixtureRegistry.load_fixture(fixture_name)
60
+ # Setup caches at suite start only when at least one fixture-backed
61
+ # example exists in the loaded suite.
62
+ config.when_first_matching_example_defined(DECLARATION_METADATA_KEY) do
63
+ config.before(:suite) do
64
+ if FixtureKit.configuration.autogenerate
65
+ preserve_cache = ENV[PRESERVE_CACHE_ENV_KEY].to_s.match?(/\A(1|true|yes)\z/i)
66
+ Cache.clear unless preserve_cache
67
+ else
68
+ fixture_names_for_loaded_examples.each do |fixture_name|
69
+ Cache.generate(fixture_name)
70
+ end
71
+ end
43
72
  end
44
73
  end
45
74
  end
46
- end
47
- end
48
-
49
- # Configure RSpec integration
50
- RSpec.configure do |config|
51
- config.extend FixtureKit::RSpec::ClassMethods
52
- config.include FixtureKit::RSpec::InstanceMethods
53
75
 
54
- # Setup caches at suite start based on autogenerate setting
55
- # - autogenerate=true: Clear all caches (unless FIXTURE_KIT_PRESERVE_CACHE is set)
56
- # - autogenerate=false: Pre-generate all caches so tests don't fail
57
- config.before(:suite) do
58
- if FixtureKit.configuration.autogenerate
59
- preserve_cache = ENV["FIXTURE_KIT_PRESERVE_CACHE"].to_s.match?(/\A(1|true|yes)\z/i)
60
- FixtureKit::FixtureCache.clear unless preserve_cache
61
- else
62
- FixtureKit::FixtureCache.pregenerate_all
76
+ def self.fixture_names_for_loaded_examples
77
+ ::RSpec.world.filtered_examples.each_value.with_object(Set.new) do |examples, names|
78
+ examples.each do |example|
79
+ declaration = example.metadata[DECLARATION_METADATA_KEY]
80
+ names << declaration.name if declaration
81
+ end
82
+ end.to_a
63
83
  end
64
84
  end
65
85
  end
86
+
87
+ # Configure RSpec integration
88
+ FixtureKit::RSpec.configure!(RSpec.configuration)
@@ -3,14 +3,20 @@
3
3
  require "active_support/inflector"
4
4
 
5
5
  module FixtureKit
6
- class FixtureRunner
6
+ class Runner
7
+ def self.run(fixture_name, force: false)
8
+ new(fixture_name).run(force: force)
9
+ end
10
+
7
11
  def initialize(fixture_name)
8
- @fixture_name = fixture_name.to_sym
9
- @cache = FixtureCache.new(@fixture_name)
12
+ @fixture_name = fixture_name
13
+ @cache = Cache.new(@fixture_name)
10
14
  end
11
15
 
12
- def run
13
- if @cache.exists?
16
+ def run(force: false)
17
+ if force
18
+ execute_and_cache
19
+ elsif @cache.exists?
14
20
  execute_from_cache
15
21
  elsif FixtureKit.configuration.autogenerate
16
22
  execute_and_cache
@@ -26,26 +32,10 @@ module FixtureKit
26
32
  end
27
33
  end
28
34
 
29
- # Generate cache only (used for pregeneration in before(:suite))
30
- # Wraps execution in ActiveRecord::TestFixtures transactional lifecycle,
31
- # so no data persists across configured writing pools.
32
- # Always regenerates the cache, even if one exists
33
- def generate_cache_only
34
- # Clear any existing cache for this fixture
35
- FixtureCache.clear(@fixture_name.to_s)
36
-
37
- FixtureKit::TransactionalHarness.run do
38
- execute_and_cache
39
- end
40
-
41
- true
42
- end
43
-
44
35
  private
45
36
 
46
37
  def execute_and_cache
47
- fixture = FixtureRegistry.find(@fixture_name)
48
- raise ArgumentError, "Fixture '#{@fixture_name}' not found" unless fixture
38
+ fixture = Registry.fetch(@fixture_name)
49
39
 
50
40
  # Start capturing SQL
51
41
  capture = SqlCapture.new
@@ -63,8 +53,8 @@ module FixtureKit
63
53
  exposed_mapping: build_exposed_mapping(exposed)
64
54
  )
65
55
 
66
- # Return FixtureSet from the exposed records
67
- FixtureSet.new(exposed)
56
+ # Return Repository from the exposed records
57
+ Repository.new(exposed)
68
58
  end
69
59
 
70
60
  def execute_from_cache
@@ -79,8 +69,8 @@ module FixtureKit
79
69
  connection.execute(sql)
80
70
  end
81
71
 
82
- # Query exposed records and build FixtureSet
83
- @cache.build_fixture_set
72
+ # Query exposed records and build Repository.
73
+ @cache.build_repository
84
74
  end
85
75
 
86
76
  def build_exposed_mapping(exposed)
@@ -5,8 +5,7 @@ require "pathname"
5
5
  module FixtureKit
6
6
  module Singleton
7
7
  def configure
8
- @configuration = Configuration.new
9
- yield(@configuration) if block_given?
8
+ yield(configuration) if block_given?
10
9
  self
11
10
  end
12
11
 
@@ -23,14 +22,14 @@ module FixtureKit
23
22
  name = relative_path.to_s.sub(/\.rb$/, "")
24
23
 
25
24
  fixture = Fixture.new(name, &block)
26
- FixtureRegistry.register(fixture)
25
+ Registry.register(fixture)
27
26
  fixture
28
27
  end
29
28
 
30
29
  def reset
31
30
  @configuration = nil
32
- FixtureRegistry.reset
33
- FixtureCache.clear_memory_cache
31
+ Registry.reset
32
+ Cache.clear_memory_cache
34
33
  end
35
34
  end
36
35
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/test_case"
4
+ require "active_record/fixtures"
5
+
6
+ module FixtureKit
7
+ module TestCase
8
+ class Generator < FixtureKit::Generator
9
+ TEST_METHOD_NAME = "test_fixture_kit_cache_pregeneration"
10
+
11
+ def run(&block)
12
+ result = build_test_class(&block).run
13
+ return if result.passed?
14
+
15
+ failure = result.failures.first
16
+ raise failure.error if failure.respond_to?(:error)
17
+ raise failure if failure
18
+
19
+ raise FixtureKit::PregenerationError, "FixtureKit pregeneration failed"
20
+ end
21
+
22
+ private
23
+
24
+ def build_test_class(&block)
25
+ Class.new(ActiveSupport::TestCase) do
26
+ ::Minitest::Runnable.runnables.delete(self)
27
+ include(::ActiveRecord::TestFixtures)
28
+
29
+ define_method(TEST_METHOD_NAME) do
30
+ block.call
31
+ pass
32
+ end
33
+ end.new(TEST_METHOD_NAME)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FixtureKit
4
+ module TestCase
5
+ autoload :Generator, File.expand_path("test_case/generator", __dir__)
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FixtureKit
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/fixture_kit.rb CHANGED
@@ -5,19 +5,22 @@ module FixtureKit
5
5
  class DuplicateFixtureError < Error; end
6
6
  class DuplicateNameError < Error; end
7
7
  class CacheMissingError < Error; end
8
+ class PregenerationError < Error; end
9
+ class FixtureDefinitionNotFound < Error; end
8
10
  class ExposedRecordNotFound < Error; end
9
11
 
10
12
  autoload :VERSION, File.expand_path("fixture_kit/version", __dir__)
11
13
  autoload :Configuration, File.expand_path("fixture_kit/configuration", __dir__)
12
14
  autoload :Singleton, File.expand_path("fixture_kit/singleton", __dir__)
13
15
  autoload :Fixture, File.expand_path("fixture_kit/fixture", __dir__)
14
- autoload :FixtureContext, File.expand_path("fixture_kit/fixture_context", __dir__)
15
- autoload :FixtureRegistry, File.expand_path("fixture_kit/fixture_registry", __dir__)
16
- autoload :FixtureSet, File.expand_path("fixture_kit/fixture_set", __dir__)
16
+ autoload :DefinitionContext, File.expand_path("fixture_kit/definition_context", __dir__)
17
+ autoload :Registry, File.expand_path("fixture_kit/registry", __dir__)
18
+ autoload :Repository, File.expand_path("fixture_kit/repository", __dir__)
17
19
  autoload :SqlCapture, File.expand_path("fixture_kit/sql_capture", __dir__)
18
- autoload :FixtureCache, File.expand_path("fixture_kit/fixture_cache", __dir__)
19
- autoload :FixtureRunner, File.expand_path("fixture_kit/fixture_runner", __dir__)
20
- autoload :TransactionalHarness, File.expand_path("fixture_kit/transactional_harness", __dir__)
20
+ autoload :Cache, File.expand_path("fixture_kit/cache", __dir__)
21
+ autoload :Runner, File.expand_path("fixture_kit/runner", __dir__)
22
+ autoload :Generator, File.expand_path("fixture_kit/generator", __dir__)
23
+ autoload :TestCase, File.expand_path("fixture_kit/test_case", __dir__)
21
24
 
22
25
  extend Singleton
23
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fixture_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ngan Pham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-20 00:00:00.000000000 Z
11
+ date: 2026-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -134,17 +134,21 @@ files:
134
134
  - LICENSE
135
135
  - README.md
136
136
  - lib/fixture_kit.rb
137
+ - lib/fixture_kit/cache.rb
137
138
  - lib/fixture_kit/configuration.rb
139
+ - lib/fixture_kit/definition_context.rb
138
140
  - lib/fixture_kit/fixture.rb
139
- - lib/fixture_kit/fixture_cache.rb
140
- - lib/fixture_kit/fixture_context.rb
141
- - lib/fixture_kit/fixture_registry.rb
142
- - lib/fixture_kit/fixture_runner.rb
143
- - lib/fixture_kit/fixture_set.rb
141
+ - lib/fixture_kit/generator.rb
142
+ - lib/fixture_kit/registry.rb
143
+ - lib/fixture_kit/repository.rb
144
144
  - lib/fixture_kit/rspec.rb
145
+ - lib/fixture_kit/rspec/declaration.rb
146
+ - lib/fixture_kit/rspec/generator.rb
147
+ - lib/fixture_kit/runner.rb
145
148
  - lib/fixture_kit/singleton.rb
146
149
  - lib/fixture_kit/sql_capture.rb
147
- - lib/fixture_kit/transactional_harness.rb
150
+ - lib/fixture_kit/test_case.rb
151
+ - lib/fixture_kit/test_case/generator.rb
148
152
  - lib/fixture_kit/version.rb
149
153
  homepage: https://github.com/Gusto/fixture_kit
150
154
  licenses:
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FixtureKit
4
- module FixtureRegistry
5
- class << self
6
- def register(fixture)
7
- fixtures[fixture.name.to_s] = fixture
8
- end
9
-
10
- def find(name)
11
- fixtures[name.to_s]
12
- end
13
-
14
- def all_names
15
- fixtures.keys
16
- end
17
-
18
- # Load all fixture definition files from the given path.
19
- # Uses `load` instead of `require` to ensure fixtures are registered
20
- # even if the files were previously required (e.g., after a reset).
21
- def load_definitions(fixture_path)
22
- Dir.glob(File.join(fixture_path, "**/*.rb")).each do |file|
23
- load file
24
- end
25
- end
26
-
27
- def reset
28
- @fixtures = nil
29
- end
30
-
31
- # Load a fixture's records into the database and return a FixtureSet.
32
- # Uses cached INSERT statements if available, otherwise executes fixture and caches.
33
- def load_fixture(name)
34
- name = name.to_s
35
-
36
- # Load the file on-demand if fixture not yet registered
37
- unless find(name)
38
- fixture_path = FixtureKit.configuration.fixture_path
39
- file_path = File.expand_path(File.join(fixture_path, "#{name}.rb"))
40
- load file_path
41
- end
42
-
43
- runner = FixtureRunner.new(name)
44
- runner.run
45
- end
46
-
47
- private
48
-
49
- def fixtures
50
- @fixtures ||= {}
51
- end
52
- end
53
- end
54
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_record/fixtures"
4
-
5
- module FixtureKit
6
- # Runs arbitrary code inside ActiveRecord::TestFixtures lifecycle without
7
- # defining a real test example. This gives us Rails' transactional handling
8
- # across all configured writing pools.
9
- class TransactionalHarness
10
- include ActiveRecord::TestFixtures
11
-
12
- def self.run(&block)
13
- new.run(&block)
14
- end
15
-
16
- # ActiveRecord::TestFixtures checks `name` to decide whether the current
17
- # method is marked with `uses_transaction`.
18
- def name
19
- "fixture_kit_transactional_harness"
20
- end
21
-
22
- def run
23
- setup_fixtures
24
- yield
25
- ensure
26
- teardown_fixtures
27
- end
28
- end
29
- end