fixturizer 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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