fixturizer 0.1.0 → 0.4.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.debride_whitelist +7 -0
  3. data/.rubocop.yml +80 -0
  4. data/Gemfile +4 -4
  5. data/Rakefile +58 -3
  6. data/VERSION +1 -0
  7. data/bin/console +4 -3
  8. data/bom.xml +802 -0
  9. data/fixturizer.gemspec +34 -16
  10. data/lib/dependencies.rb +9 -0
  11. data/lib/fixturizer/adapters/init.rb +3 -0
  12. data/lib/fixturizer/adapters/mongoid.rb +52 -0
  13. data/lib/fixturizer/configuration.rb +22 -0
  14. data/lib/fixturizer/engines/datasets.rb +46 -0
  15. data/lib/fixturizer/engines/init.rb +3 -0
  16. data/lib/fixturizer/engines/models.rb +73 -0
  17. data/lib/fixturizer/engines/records.rb +23 -0
  18. data/lib/fixturizer/rake/manage.rb +3 -1
  19. data/lib/fixturizer/rake/rules/database.rake +12 -9
  20. data/lib/fixturizer/rspec/helpers/database.rb +27 -0
  21. data/lib/fixturizer/rspec/helpers/datasets.rb +19 -0
  22. data/lib/fixturizer/rspec/helpers/records.rb +19 -0
  23. data/lib/fixturizer/rspec/helpers/serializer.rb +25 -0
  24. data/lib/fixturizer/rspec/matchers/database_be_correctly_dropped.rb +16 -0
  25. data/lib/fixturizer/rspec/matchers/database_be_correctly_populated.rb +16 -0
  26. data/lib/fixturizer/rspec/prepare.rb +6 -0
  27. data/lib/fixturizer/serializers/init.rb +30 -0
  28. data/lib/fixturizer/serializers/json.rb +18 -0
  29. data/lib/fixturizer/serializers/yaml.rb +15 -0
  30. data/lib/fixturizer/services.rb +47 -0
  31. data/lib/fixturizer/settings.rb +12 -0
  32. data/lib/fixturizer/version.rb +5 -1
  33. data/lib/fixturizer.rb +9 -109
  34. data/samples/.rspec +3 -0
  35. data/samples/Gemfile +17 -0
  36. data/samples/Rakefile +21 -0
  37. data/samples/app.rb +43 -0
  38. data/samples/config/rules.yml +52 -0
  39. data/samples/config.ru +10 -0
  40. data/samples/spec/app_spec.rb +134 -0
  41. data/samples/spec/spec_helper.rb +17 -0
  42. metadata +212 -8
data/fixturizer.gemspec CHANGED
@@ -1,27 +1,45 @@
1
- require_relative 'lib/fixturizer/version'
1
+ # frozen_string_literal: true
2
2
 
3
3
  Gem::Specification.new do |spec|
4
- spec.name = "fixturizer"
5
- spec.version = Fixturizer::VERSION
6
- spec.authors = ["Pierre Alphonse"]
7
- spec.email = ["pierre.alphonse@orange.com"]
4
+ spec.name = 'fixturizer'
5
+ spec.version = `cat VERSION`.chomp
6
+ spec.authors = ['Pierre ALPHONSE', 'Romain GEORGES']
7
+ spec.email = ['pierre.alphonse@orange.com', 'romain@ultragreen.net']
8
8
 
9
- spec.summary = "Ruby fixturizer for databases models"
10
- spec.description = "Ruby fixturizer for databases models"
11
- spec.homepage = "https://github.com/Ultragreen/fixturizer"
12
- spec.license = "MIT"
13
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
9
+ spec.summary = 'Ruby fixturizer tools for applications testing'
10
+ spec.description = 'Ruby fixturizer tools for applications testing'
11
+ spec.homepage = 'https://github.com/Ultragreen/fixturizer'
12
+ spec.license = 'MIT'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.2.3')
14
14
 
15
- spec.metadata["homepage_uri"] = spec.homepage
16
- spec.metadata["source_code_uri"] = spec.homepage
17
- spec.metadata["changelog_uri"] = spec.homepage
15
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = spec.homepage
19
+ spec.metadata['changelog_uri'] = spec.homepage
18
20
 
19
21
  # Specify which files should be added to the gem when it is released.
20
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
25
  end
24
- spec.bindir = "exe"
26
+ spec.bindir = 'exe'
25
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
- spec.require_paths = ["lib"]
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.metadata['rubygems_mfa_required'] = 'true'
31
+
32
+ spec.add_dependency 'mongoid', '~> 9.0'
33
+ spec.add_dependency 'rake', '~> 13.0'
34
+ spec.add_dependency 'rspec', '~> 3.10.0'
35
+ spec.add_dependency 'version', '~> 1.1'
36
+
37
+ spec.add_development_dependency 'bundle-audit', '~> 0.1.0'
38
+ spec.add_development_dependency 'code_statistics', '~> 0.2.13'
39
+ spec.add_development_dependency 'cyclonedx-ruby', '~> 1.1'
40
+ spec.add_development_dependency 'debride', '~> 1.12'
41
+ spec.add_development_dependency 'diff-lcs', '~> 1.5.1'
42
+ spec.add_development_dependency 'rubocop', '~> 1.32'
43
+ spec.add_development_dependency 'yard', '~> 0.9.27'
44
+ spec.add_development_dependency 'yard-rspec', '~> 0.1'
27
45
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'forwardable'
5
+ require 'logger'
6
+
7
+ require 'mongoid'
8
+ require 'fixturizer/version'
9
+ require 'yaml'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.dirname(__FILE__)}/*.rb"].each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Adapters
5
+ module Mongoid
6
+ def injector(model_infos:, item:)
7
+ model = Object.const_get(model_infos[:class])
8
+ model.create!(item) unless model.where(model_infos[:unicity] => item[model_infos[:unicity]]).exists?
9
+ end
10
+
11
+ def binder(item:)
12
+ result = {}
13
+ item.each do |element|
14
+ model_class = @models[element[:collection]][:class]
15
+ model = Object.const_get(model_class)
16
+ if element[:index].include?(:at)
17
+ result[element[:fkey]] = model.all[element[:index][:at] - 1][element[:pkey]].to_s
18
+ elsif element[:index].include?(:search_key)
19
+ raise 'Links configuration failure' unless element[:index].include?(:for)
20
+
21
+ result[element[:fkey]] =
22
+ model.where({ element[:index][:search_key] => element[:index][:for] }).first[element[:pkey]]
23
+ else
24
+ raise 'Links configuration failure'
25
+ end
26
+ end
27
+ result
28
+ end
29
+
30
+ def drop_database
31
+ ::Mongoid.purge!
32
+ true
33
+ rescue StandardError
34
+ false
35
+ end
36
+
37
+ def check
38
+ res = {}
39
+ begin
40
+ node = ::Mongoid.default_client.cluster.addresses.first.to_s
41
+ dbname = ::Mongoid.default_client.database.name
42
+ client = ::Mongo::Client.new("mongodb://#{node}/#{dbname}")
43
+ client.database_names
44
+ return true
45
+ rescue ::Mongo::Auth::Unauthorized, Mongo::Error
46
+ return false
47
+ end
48
+ res
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ class Configuration
5
+ attr_reader :rules, :models, :datasets, :models_order, :models_type
6
+
7
+ def initialize(filename:)
8
+ @content = read_file(filename:)
9
+ @rules = @content[:fixtures][:rules]
10
+ @models_type = @content[:fixtures].dig(:models, :type)
11
+ @models = @content[:fixtures].dig(:models, :definitions)
12
+ @models_order = @content[:fixtures].dig(:models, :order)
13
+ @datasets = @content[:fixtures][:datasets]
14
+ end
15
+
16
+ private
17
+
18
+ def read_file(filename:)
19
+ YAML.load(File.readlines(filename).join)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Engines
5
+ class Dataset
6
+ attr_reader :name, :dataset
7
+
8
+ def initialize(dataset:)
9
+ @name = dataset
10
+ @configuration = Fixturizer::Services.get.configuration
11
+ @dataset = dataset.is_a?(Symbol) ? @configuration.datasets[@name] : dataset
12
+ @effectives_rules = @dataset[:rules]
13
+ end
14
+
15
+ def generate
16
+ data = @dataset[:definition]
17
+ substitute_values(data)
18
+ end
19
+
20
+ private
21
+
22
+ def apply_rule(key, value, rule)
23
+ if @effectives_rules.key? key
24
+ value = Fixturizer::Services.get.engine(name: :record, parameters: { value:, rule: }).apply
25
+ end
26
+ value
27
+ end
28
+
29
+ def substitute_values(obj)
30
+ return obj.map { |v| substitute_values(v) } if obj.is_a? Array
31
+ return obj unless obj.is_a? Hash
32
+
33
+ obj.each_with_object({}) do |(key, value), result|
34
+ result[key] = case value
35
+ when Hash
36
+ substitute_values(value)
37
+ when Array
38
+ value.map { |v| substitute_values(v) }
39
+ else
40
+ @effectives_rules.nil? ? value : apply_rule(key, value, @effectives_rules[key])
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.dirname(__FILE__)}/*.rb"].each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Engines
5
+ class Models
6
+ ADAPTERS = { mongoid: ::Fixturizer::Adapters::Mongoid }.freeze
7
+
8
+ attr_reader :generated
9
+
10
+ def initialize
11
+ @configuration = Fixturizer::Services.get.configuration
12
+ @rules = @configuration.rules
13
+ @models = @configuration.models
14
+ @order = @configuration.models_order
15
+ @type = @configuration.models_type
16
+ @generated = {}
17
+ extend ADAPTERS[@type]
18
+ end
19
+
20
+ def populate
21
+ generate_data
22
+ inject_data
23
+ true
24
+ end
25
+
26
+ def generate_data
27
+ @generated.clear
28
+ raise 'Order field format missmatch, not an array' unless @order.nil? || @order.is_a?(Array)
29
+
30
+ if @order
31
+ raise 'Order field size missmatch for configurate definitions' unless @order.size == @models.size
32
+
33
+ @order.each do |item|
34
+ raise "Definition #{item} not found in models definitions" unless @models.include?(item)
35
+
36
+ @generated[item] = generate_collection(name: item)
37
+ end
38
+ else
39
+ @models.each_key do |key|
40
+ @generated[key] = generate_collection(name: key)
41
+ end
42
+ end
43
+ end
44
+
45
+ def inject_data
46
+ raise 'Data not generated' if @generated.empty?
47
+
48
+ @generated.each do |key, value|
49
+ model_infos = @models[key].dup
50
+ model_infos.delete(:collection)
51
+ value.each do |item|
52
+ item[:attributes].merge!(binder(item: item[:links])) if item.include?(:links)
53
+ injector model_infos:, item: item[:attributes]
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def generate_collection(name:)
61
+ data = @models[name][:collection].dup
62
+ data.each do |item|
63
+ dataset = {}
64
+ dataset[:definition] = item[:attributes]
65
+ dataset[:rules] = @models[name][:rules]
66
+ item[:attributes] =
67
+ Fixturizer::Services.get.engine(name: :dataset, parameters: { dataset: }).generate
68
+ end
69
+ data
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Engines
5
+ class Record
6
+ def initialize(value:, rule:)
7
+ # @configuration = Fixturizer::Configuration::new filename: './config/rules.yml'
8
+ @configuration = Fixturizer::Services.get.configuration
9
+ @rules = @configuration.rules
10
+ @record = value
11
+ @rule = rule.is_a?(Symbol) ? @rules[rule] : rule
12
+ end
13
+
14
+ def apply
15
+ result = @record
16
+ return result if @rule.nil?
17
+
18
+ result = eval("lambda { #{@rule[:proc]} } ").call unless (@rule[:preserve] == true) && !@record.nil?
19
+ result
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fixturizer'
2
- Dir[File.dirname(__FILE__) + '/rules/*.rake'].each {|file| load file }
4
+ Dir["#{File.dirname(__FILE__)}/rules/*.rake"].each { |file| load file }
@@ -1,18 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :fixturizer do
2
4
  namespace :database do
3
-
4
- desc "Drop database"
5
+ desc 'Drop database'
5
6
  task :drop do
6
- my_fixturer = Fixturizer::Engine::new filename: './config/rules.yml'
7
- my_fixturer.drop_database
7
+ Fixturizer::Services.get.engine(name: :models).drop_database
8
+ # Fixturizer::Engines::Models::new(filename: './config/rules.yml').drop_database
8
9
  end
9
10
 
10
- desc "Populate database"
11
+ desc 'Populate database'
11
12
  task :populate do
12
- my_fixturer = Fixturizer::Engine::new filename: './config/rules.yml'
13
- my_fixturer.generate_data
14
- my_fixturer.inject_data
13
+ Fixturizer::Services.get.engine(name: :models).populate
15
14
  end
16
15
 
16
+ desc 'Check database connection'
17
+ task :check do
18
+ puts Fixturizer::Services.get.engine(name: :models).check ? 'OK' : 'KO'
19
+ end
17
20
  end
18
- end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Rspec
5
+ module Helpers
6
+ class Database
7
+ include Singleton
8
+
9
+ def drop
10
+ Fixturizer::Services.get.engine(name: :models).drop_database
11
+ rescue StandardError
12
+ false
13
+ end
14
+
15
+ def populate
16
+ Fixturizer::Services.get.engine(name: :models).populate
17
+ rescue StandardError
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def database
26
+ Fixturizer::Rspec::Helpers::Database.instance
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Rspec
5
+ module Helpers
6
+ class Datasets
7
+ include Singleton
8
+
9
+ def generate(dataset:)
10
+ Fixturizer::Services.get.engine(name: :dataset, parameters: { dataset: }).generate
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def datasets
18
+ Fixturizer::Rspec::Helpers::Datasets.instance
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Rspec
5
+ module Helpers
6
+ class Records
7
+ include Singleton
8
+
9
+ def apply(value:, rule:)
10
+ Fixturizer::Services.get.engine(name: :record, parameters: { value:, rule: }).apply
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def record
18
+ Fixturizer::Rspec::Helpers::Records.instance
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Rspec
5
+ module Helpers
6
+ class Serializer
7
+ include Singleton
8
+
9
+ def to(format:, data:, raw: false, to_file: nil)
10
+ options = {}
11
+ options[:raw] = raw
12
+ options[:to_file] = to_file
13
+ Fixturizer::Services.get.serializer(name: format,
14
+ parameters: {
15
+ data:, options:
16
+ }).apply
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ def serialize
24
+ Fixturizer::Rspec::Helpers::Serializer.instance
25
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :be_correctly_dropped do
4
+ match do |actual|
5
+ actual.drop == true
6
+ end
7
+ description do
8
+ 'be effectively dropped.'
9
+ end
10
+ failure_message do |_actual|
11
+ "expected database drop response to be true \ngot : false "
12
+ end
13
+ failure_message_when_negated do |_actual|
14
+ "expected database drop response to be false \ngot : true "
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :be_correctly_populated do
4
+ match do |actual|
5
+ actual.populate == true
6
+ end
7
+ description do
8
+ 'be effectively populated.'
9
+ end
10
+ failure_message do |_actual|
11
+ "expected database populate response to be true \ngot : false "
12
+ end
13
+ failure_message_when_negated do |_actual|
14
+ "expected database populate response to be false \ngot : true "
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fixturizer'
4
+
5
+ Dir["#{File.dirname(__FILE__)}/helpers/*.rb"].each { |file| require file }
6
+ Dir["#{File.dirname(__FILE__)}/matchers/*.rb"].each { |file| require file }
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Serializers
5
+ class Template
6
+ attr_reader :data
7
+
8
+ def initialize(data:, options: nil)
9
+ @data = data
10
+ @options = options
11
+ end
12
+
13
+ def apply
14
+ raise "Abstract template, don't use"
15
+ end
16
+
17
+ def write_file(file, data)
18
+ File.write(file, data)
19
+ rescue Errno::EACCES
20
+ puts "Error: Permission denied to write the file #{file}."
21
+ rescue Errno::ENOSPC
22
+ puts 'Error: No space left on the device.'
23
+ rescue StandardError => e
24
+ puts "Error: #{e.message}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ Dir["#{File.dirname(__FILE__)}/*.rb"].each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Serializers
5
+ class Json < Template
6
+ def apply
7
+ result = if @options[:raw]
8
+ @data.to_json
9
+ else
10
+ JSON.pretty_generate(@data).concat("\n")
11
+ end
12
+ return result unless @options[:to_file].is_a?(String)
13
+
14
+ write_file(@options[:to_file], result)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ module Serializers
5
+ class Yaml < Template
6
+ def apply
7
+ result = @data.to_yaml
8
+
9
+ return result unless @options[:to_file].is_a?(String)
10
+
11
+ write_file(@options[:to_file], result)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ class Services
5
+ include Singleton
6
+ @@settings = Fixturizer::Settings.new
7
+ def self.settings
8
+ @@settings
9
+ end
10
+
11
+ def self.configure
12
+ yield(@@settings)
13
+ end
14
+
15
+ attr_reader :configuration, :log
16
+
17
+ def initialize
18
+ @configuration = Fixturizer::Configuration.new filename: @@settings.configuration_filename
19
+ @log = Logger.new(Fixturizer::Services.settings.log_target)
20
+ log.info 'Starting new Fixturing'
21
+ end
22
+
23
+ def service(type:, name:, parameters: nil)
24
+ service = "Fixturizer::#{type.to_s.capitalize}::#{name.to_s.capitalize}"
25
+ log.info "running Service : #{service}"
26
+ if parameters.nil?
27
+ Object.const_get(service).new
28
+ else
29
+ log.info " => params : #{parameters}"
30
+ Object.const_get(service).new(**parameters)
31
+ end
32
+ end
33
+
34
+ def engine(name:, parameters: nil)
35
+ service(type: :engines, name:, parameters:)
36
+ end
37
+
38
+ def serializer(name:, parameters: nil)
39
+ service(type: :serializers, name:, parameters:)
40
+ end
41
+
42
+ class << self
43
+ alias get instance
44
+ alias init instance
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fixturizer
4
+ class Settings
5
+ attr_accessor :configuration_filename, :log_target
6
+
7
+ def initialize
8
+ @configuration_filename = './config/rules.yml'
9
+ @log_target = '/tmp/fixturizer.log'
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'version'
4
+
1
5
  module Fixturizer
2
- VERSION = "0.1.0"
6
+ VERSION = Version.current
3
7
  end