mtk_framework 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 +7 -0
- data/.document +5 -0
- data/.github/workflows/test.yml +21 -0
- data/.rspec +1 -0
- data/Gemfile +22 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/mtk_framework.rb +50 -0
- data/lib/mtk_framework/active_interaction_concerns/i18nable.rb +18 -0
- data/lib/mtk_framework/active_interaction_concerns/interruptable.rb +32 -0
- data/lib/mtk_framework/active_interaction_concerns/loggable.rb +84 -0
- data/lib/mtk_framework/active_interaction_concerns/rescuable.rb +27 -0
- data/lib/mtk_framework/active_interaction_concerns/updatable_object.rb +32 -0
- data/lib/mtk_framework/active_interaction_mocks/interaction_group_mocks_helper.rb +32 -0
- data/lib/mtk_framework/active_interaction_mocks/interaction_mocks_helper.rb +61 -0
- data/lib/mtk_framework/active_interaction_mocks/mocks_loader.rb +53 -0
- data/lib/mtk_framework/active_interaction_params.rb +16 -0
- data/lib/mtk_framework/active_interaction_params/parametrize_filter.rb +108 -0
- data/lib/mtk_framework/core_extensions/array/except.rb +7 -0
- data/lib/mtk_framework/core_extensions/class/virtual_method.rb +11 -0
- data/lib/mtk_framework/core_extensions/hash/rename_keys.rb +11 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/base.rb +20 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/abstract_tz_filter.rb +28 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/hash_filter.rb +38 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_account_filter.rb +23 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_contract_address_filter.rb +23 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_operation_filter.rb +23 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_public_key_filter.rb +23 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_secret_key_filter.rb +23 -0
- data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_signature_filter.rb +23 -0
- data/lib/mtk_framework/locale/active_interaction.fr.yml +8 -0
- data/lib/mtk_framework/locale/fr.yml +219 -0
- data/lib/mtk_framework/railtie.rb +13 -0
- data/mtk_framework.gemspec +114 -0
- data/spec/active_interaction_concerns/interruptable_spec.rb +127 -0
- data/spec/active_interaction_concerns/loggable_spec.rb +195 -0
- data/spec/application_interaction_spec.rb +17 -0
- data/spec/fake_app.rb +14 -0
- data/spec/gem_extensions/active_interaction/filters/tz_account_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters/tz_contract_address_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters/tz_operation_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters/tz_public_key_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters/tz_secret_key_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters/tz_signature_filter_spec.rb +7 -0
- data/spec/gem_extensions/active_interaction/filters_shared.rb +253 -0
- data/spec/gem_extensions/active_interaction/tz_filters_shared.rb +60 -0
- data/spec/spec_helper.rb +24 -0
- metadata +232 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MtkFramework
|
4
|
+
module ActiveInteractionMocks
|
5
|
+
module InteractionMocksHelper
|
6
|
+
def mock_interaction(
|
7
|
+
klass,
|
8
|
+
methods: nil,
|
9
|
+
failing: false,
|
10
|
+
mandatory: true,
|
11
|
+
expected_params: nil,
|
12
|
+
additional_params: nil,
|
13
|
+
return_proc: nil,
|
14
|
+
call_original: false
|
15
|
+
)
|
16
|
+
stubbed_methods = methods || (mandatory ? [:run] : %i[run run!])
|
17
|
+
|
18
|
+
spec_method = mandatory ? :expect : :allow
|
19
|
+
const_name = failing ? 'Fail' : 'Mocked'
|
20
|
+
mocking_klass = klass.const_get(const_name)
|
21
|
+
|
22
|
+
if block_given? || return_proc.present?
|
23
|
+
mocking_klass = Class.new(mocking_klass)
|
24
|
+
test_scope = self
|
25
|
+
|
26
|
+
mocking_klass.define_method :execute do
|
27
|
+
return_value = yield self if block_given?
|
28
|
+
if return_proc.present?
|
29
|
+
return_value = test_scope.instance_exec(&return_proc)
|
30
|
+
end
|
31
|
+
|
32
|
+
return_value
|
33
|
+
end
|
34
|
+
|
35
|
+
mocking_klass.define_singleton_method :name do
|
36
|
+
"#{klass.name}::#{const_name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
stubbed_methods.map do |stubbed_method|
|
41
|
+
block = lambda { |*params|
|
42
|
+
mocking_klass.send(stubbed_method, *params, &block)
|
43
|
+
}
|
44
|
+
|
45
|
+
rspec_sentence = receive(stubbed_method, &block)
|
46
|
+
|
47
|
+
if expected_params
|
48
|
+
with = expected_params.respond_to?(:call) ? instance_eval(&expected_params) : expected_params
|
49
|
+
rspec_sentence.with(with, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
additional_params&.call(rspec_sentence)
|
53
|
+
|
54
|
+
rspec_sentence.and_call_original if call_original
|
55
|
+
|
56
|
+
send(spec_method, klass).to rspec_sentence
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MtkFramework
|
4
|
+
module ActiveInteractionMocks
|
5
|
+
class MocksLoader
|
6
|
+
def run
|
7
|
+
# force require of all interactions
|
8
|
+
Dir['app/interactions/**/*.rb'].each do |x|
|
9
|
+
require Rails.root.join(x)
|
10
|
+
rescue StandardError
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
ApplicationInteraction.descendants.each do |klass|
|
15
|
+
mocked = Class.new(ApplicationInteraction) do
|
16
|
+
import_filters klass
|
17
|
+
|
18
|
+
# delegate i18n translation to mocked class
|
19
|
+
define_singleton_method :human_attribute_name do |*args|
|
20
|
+
klass.human_attribute_name(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
define_singleton_method :model_name do |*args|
|
24
|
+
klass.model_name(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method :to_model do
|
28
|
+
klass.to_s.split('::').first.singularize.safe_constantize&.new
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def execute; end
|
34
|
+
end
|
35
|
+
|
36
|
+
failing = Class.new(mocked) do
|
37
|
+
private
|
38
|
+
|
39
|
+
def execute
|
40
|
+
errors.add(:base, 'shit happens')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
klass.const_set('Mocked', mocked)
|
45
|
+
klass.const_set('Fail', failing)
|
46
|
+
end
|
47
|
+
|
48
|
+
require_relative 'interaction_mocks_helper.rb'
|
49
|
+
require_relative 'interaction_group_mocks_helper.rb'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'active_interaction_params/parametrize_filter.rb'
|
4
|
+
|
5
|
+
module MtkFramework
|
6
|
+
module ActiveInteractionParams
|
7
|
+
def params_from_interaction(klass, except: [])
|
8
|
+
params do
|
9
|
+
klass.filters.except(*except).each do |_, filter|
|
10
|
+
ParametrizeFilter.call(filter, self)
|
11
|
+
yield self if block_given?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MtkFramework
|
4
|
+
module ActiveInteractionParams
|
5
|
+
class ParametrizeFilter
|
6
|
+
TYPES_MAPPING = {
|
7
|
+
'Integer' => Integer,
|
8
|
+
'Float' => Float,
|
9
|
+
'Boolean' => Grape::API::Boolean,
|
10
|
+
'String' => String,
|
11
|
+
'Symbol' => Symbol,
|
12
|
+
'Date' => Date,
|
13
|
+
'DateTime' => DateTime,
|
14
|
+
'Time' => Time,
|
15
|
+
'File' => File,
|
16
|
+
'Hash' => Hash,
|
17
|
+
'Array' => Array,
|
18
|
+
'TzSecretKey' => String,
|
19
|
+
'TzAccount' => String,
|
20
|
+
'TzContractAddress' => String,
|
21
|
+
'TzPublicKey' => String,
|
22
|
+
'TzSignature' => String
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
class <<self
|
26
|
+
# TODO: handle the case of Object, Record, Interface(?)
|
27
|
+
def call(filter, params_scope)
|
28
|
+
unless nestable_filter?(filter)
|
29
|
+
return params_scope.send(grape_method(filter), filter.name,
|
30
|
+
**grape_options(filter))
|
31
|
+
end
|
32
|
+
|
33
|
+
parametrize_nestable(filter, params_scope)
|
34
|
+
end
|
35
|
+
|
36
|
+
def parametrize_nestable(filter, params_scope)
|
37
|
+
current_filter = filter
|
38
|
+
|
39
|
+
params_scope.send(grape_method(current_filter), current_filter.name,
|
40
|
+
**grape_options(current_filter)) do
|
41
|
+
current_filter.filters.each do |_, child_filter|
|
42
|
+
unless ParametrizeFilter.array_hash_filters?(current_filter, child_filter)
|
43
|
+
ParametrizeFilter.call(child_filter, self)
|
44
|
+
end
|
45
|
+
|
46
|
+
# skip the hash require in the case of an array of hashes (AI and grape handle this case differently)
|
47
|
+
child_filter.filters.each do |_, small_child_filter|
|
48
|
+
ParametrizeFilter.call(small_child_filter, self)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def grape_filter_type(filter)
|
55
|
+
if filter.is_a? ActiveInteraction::ArrayFilter
|
56
|
+
return array_grape_filter_type(filter)
|
57
|
+
end
|
58
|
+
|
59
|
+
filter_name = filter.class.name.split('::').second.split('Filter').first
|
60
|
+
|
61
|
+
TYPES_MAPPING.fetch(filter_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
# returns Array[<File | Integer ...>] if not array of hashes
|
65
|
+
# else return Array, because in this case we use nested params with a block
|
66
|
+
def array_grape_filter_type(filter)
|
67
|
+
child_filter = filter.filters.values.first
|
68
|
+
|
69
|
+
unless child_filter.is_a? ActiveInteraction::HashFilter
|
70
|
+
return Array[grape_filter_type(child_filter)]
|
71
|
+
end
|
72
|
+
|
73
|
+
Array
|
74
|
+
end
|
75
|
+
|
76
|
+
def grape_options(filter)
|
77
|
+
grape_options = { desc: filter.options.fetch(:desc, ''), type: grape_filter_type(filter) }
|
78
|
+
if filter.options[:default]
|
79
|
+
grape_options[:default] = filter.options[:default]
|
80
|
+
end
|
81
|
+
|
82
|
+
grape_options
|
83
|
+
end
|
84
|
+
|
85
|
+
def grape_method(filter)
|
86
|
+
filter.options.key?(:default) ? :optional : :requires
|
87
|
+
end
|
88
|
+
|
89
|
+
def array_hash_filters?(filter, child_filter)
|
90
|
+
filter.is_a?(ActiveInteraction::ArrayFilter) && child_filter.is_a?(ActiveInteraction::HashFilter)
|
91
|
+
end
|
92
|
+
|
93
|
+
def nestable_filter?(filter)
|
94
|
+
unless filter.is_a? ActiveInteraction::ArrayFilter
|
95
|
+
return filter.filters.any?
|
96
|
+
end
|
97
|
+
|
98
|
+
# this case is not supposed to happen since ActiveInteraction only allows one type in the case of an Array
|
99
|
+
raise NotImplementedError unless filter.filters.count == 1
|
100
|
+
|
101
|
+
# if it is an array of hashes => we use nested params with a block
|
102
|
+
# else we use types like Array[String] => not nestable
|
103
|
+
filter.filters.values.first.is_a? ActiveInteraction::HashFilter
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
class Base
|
5
|
+
def self.import_filters_optionally(klass, options = {})
|
6
|
+
only = options[:only]
|
7
|
+
except = options[:except]
|
8
|
+
default_value = options[:default_value]
|
9
|
+
|
10
|
+
other_filters = klass.filters.dup
|
11
|
+
other_filters.select! { |k, _| [*only].include?(k) } if only
|
12
|
+
other_filters.reject! { |k, _| [*except].include?(k) } if except
|
13
|
+
|
14
|
+
other_filters.each_value do |filter|
|
15
|
+
filter.options[:default] = default_value
|
16
|
+
initialize_filter(filter)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
# @abstract
|
5
|
+
#
|
6
|
+
# Common logic for filters that handle numeric objects.
|
7
|
+
#
|
8
|
+
# @private
|
9
|
+
class AbstractTzFilter < Filter
|
10
|
+
private
|
11
|
+
|
12
|
+
def matches?(value)
|
13
|
+
value.is_a?(String) && valid_tz_entry?(value)
|
14
|
+
rescue NoMethodError # BasicObject
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_tz_entry?(value)
|
19
|
+
TezosClient.new.decode_tz(value) do |prefix, _payload|
|
20
|
+
return false unless prefixes.include? prefix
|
21
|
+
end
|
22
|
+
|
23
|
+
true
|
24
|
+
rescue ArgumentError
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_interaction'
|
4
|
+
|
5
|
+
# credits to : https://github.com/formigarafa/active_interaction/pull/2
|
6
|
+
# This allows to import_filters inside hash. Example :
|
7
|
+
# hash :user do
|
8
|
+
# import_filters UserSignup
|
9
|
+
# end
|
10
|
+
|
11
|
+
module ActiveInteraction
|
12
|
+
class HashFilter < Filter
|
13
|
+
# Import filters from another interaction.
|
14
|
+
#
|
15
|
+
# @param klass [Class] The other interaction.
|
16
|
+
# @param options [Hash]
|
17
|
+
#
|
18
|
+
# @option options [Array<Symbol>, nil] :only Import only these filters.
|
19
|
+
# @option options [Array<Symbol>, nil] :except Import all filters except
|
20
|
+
# for these.
|
21
|
+
#
|
22
|
+
# @!visibility public
|
23
|
+
def import_filters(klass, options = {}) # rubocop:disable Metrics/AbcSize
|
24
|
+
only = options[:only]
|
25
|
+
except = options[:except]
|
26
|
+
groups = options[:groups] || [klass.to_s.demodulize.underscore.to_sym]
|
27
|
+
|
28
|
+
klass.filters.each do |name, filter|
|
29
|
+
next if only && ![*only].include?(name)
|
30
|
+
next if except && [*except].include?(name)
|
31
|
+
|
32
|
+
options = filter.options.merge(groups: groups)
|
33
|
+
filter_copy = filter.class.new(name, options)
|
34
|
+
filters[name] = filter_copy
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
class Base
|
5
|
+
# @!method self.tz_public_key(*attributes, options = {})
|
6
|
+
# Creates accessors for the attributes and ensures that values passed to
|
7
|
+
# the attributes are Strings.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# tz_public_key :public_key
|
11
|
+
end
|
12
|
+
|
13
|
+
# @private
|
14
|
+
class TzAccountFilter < AbstractTzFilter
|
15
|
+
register :tz_account
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def prefixes
|
20
|
+
%i[tz1 tz2 tz3].freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mtk_framework/gem_extensions/active_interaction/filters/tz_contract_address_filter.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
class Base
|
5
|
+
# @!method self.tz_public_key(*attributes, options = {})
|
6
|
+
# Creates accessors for the attributes and ensures that values passed to
|
7
|
+
# the attributes are Strings.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# tz_public_key :public_key
|
11
|
+
end
|
12
|
+
|
13
|
+
# @private
|
14
|
+
class TzContractAddressFilter < AbstractTzFilter
|
15
|
+
register :tz_contract_address
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def prefixes
|
20
|
+
%i[KT].freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
class Base
|
5
|
+
# @!method self.tz_operation(*attributes, options = {})
|
6
|
+
# Creates accessors for the attributes and ensures that values passed to
|
7
|
+
# the attributes are Strings.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# tz_operation :operation
|
11
|
+
end
|
12
|
+
|
13
|
+
# @private
|
14
|
+
class TzOperationFilter < AbstractTzFilter
|
15
|
+
register :tz_operation
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def prefixes
|
20
|
+
%i[o].freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInteraction
|
4
|
+
class Base
|
5
|
+
# @!method self.tz_public_key(*attributes, options = {})
|
6
|
+
# Creates accessors for the attributes and ensures that values passed to
|
7
|
+
# the attributes are Strings.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# tz_public_key :public_key
|
11
|
+
end
|
12
|
+
|
13
|
+
# @private
|
14
|
+
class TzPublicKeyFilter < AbstractTzFilter
|
15
|
+
register :tz_public_key
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def prefixes
|
20
|
+
%i[edpk].freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|