activevalidation 0.1.0 → 1.0.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 +4 -4
- data/.gitignore +32 -9
- data/.overcommit.yml +93 -0
- data/.rspec +1 -1
- data/.rubocop.yml +80 -0
- data/.rubocop_todo.yml +7 -0
- data/.travis.yml +42 -2
- data/.yardops +9 -0
- data/Appraisals +27 -0
- data/Gemfile +24 -1
- data/MIT-LICENSE +20 -0
- data/README.md +142 -20
- data/Rakefile +21 -3
- data/activevalidation.gemspec +35 -25
- data/bin/console +4 -7
- data/gemfiles/am_5.0.gemfile +17 -0
- data/gemfiles/am_5.0.gemfile.lock +159 -0
- data/gemfiles/am_5.1.gemfile +17 -0
- data/gemfiles/am_5.1.gemfile.lock +159 -0
- data/gemfiles/am_5.2.gemfile +17 -0
- data/gemfiles/am_5.2.gemfile.lock +159 -0
- data/gemfiles/am_6.0.gemfile +18 -0
- data/gemfiles/am_6.0.gemfile.lock +158 -0
- data/lib/active_validation.rb +27 -0
- data/lib/active_validation/base_adapter.rb +103 -0
- data/lib/active_validation/configuration.rb +52 -0
- data/lib/active_validation/decorator.rb +27 -0
- data/lib/active_validation/decorators/consistent_registry.rb +36 -0
- data/lib/active_validation/decorators/disallows_duplicates_registry.rb +17 -0
- data/lib/active_validation/errors.rb +28 -0
- data/lib/active_validation/ext/add_active_validation_context_check.rb +21 -0
- data/lib/active_validation/formatters/manifest_name_formatter.rb +13 -0
- data/lib/active_validation/formatters/validation_context_formatter.rb +28 -0
- data/lib/active_validation/frameworks/rspec.rb +10 -0
- data/lib/active_validation/frameworks/rspec/helpers.rb +15 -0
- data/lib/active_validation/internal/models/check.rb +51 -0
- data/lib/active_validation/internal/models/concerns/to_internal.rb +27 -0
- data/lib/active_validation/internal/models/manifest.rb +122 -0
- data/lib/active_validation/internal/models/manifest/installer.rb +86 -0
- data/lib/active_validation/internal/observers/manifest.rb +114 -0
- data/lib/active_validation/model_extension_base.rb +33 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/adapter.rb +59 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/internals/active_validation/internal_model_extensions/check.rb +11 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/model_extension/active_validation/active_record_model_extension.rb +25 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check.rb +31 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/concerns/method_must_be_allowed.rb +38 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method.rb +9 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method.rb +9 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method.rb +19 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/concerns/protect_from_mutable_instance_methods.rb +31 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest.rb +21 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/types/active_validation/type/version.rb +17 -0
- data/lib/active_validation/registry.rb +55 -0
- data/lib/active_validation/values/base.rb +39 -0
- data/lib/active_validation/values/method_name.rb +22 -0
- data/lib/active_validation/values/version.rb +17 -0
- data/lib/active_validation/verifier.rb +150 -0
- data/lib/active_validation/version.rb +5 -0
- data/spec/active_validation/base_adapter_spec.rb +23 -0
- data/spec/active_validation/configuration_spec.rb +52 -0
- data/spec/active_validation/decorators/consistent_registry_spec.rb +117 -0
- data/spec/active_validation/decorators/disallows_duplicates_registry_spec.rb +21 -0
- data/spec/active_validation/formatters/manifest_name_formatter_spec.rb +7 -0
- data/spec/active_validation/formatters/validation_context_formatter_spec.rb +39 -0
- data/spec/active_validation/internal/models/check_spec.rb +67 -0
- data/spec/active_validation/internal/models/manifest/installer_spec.rb +177 -0
- data/spec/active_validation/internal/models/manifest_spec.rb +136 -0
- data/spec/active_validation/internal/observers/manifest_spec.rb +201 -0
- data/spec/active_validation/model_extension_base_spec.rb +71 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec.rb +31 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec_orm_specific_spec.rb +84 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method_spec.rb +26 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method_spec.rb +26 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method_spec.rb +34 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check_spec.rb +48 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest_spec.rb +61 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/readme_spec.rb +89 -0
- data/spec/active_validation/registry_spec.rb +76 -0
- data/spec/active_validation/values/base_spec.rb +61 -0
- data/spec/active_validation/values/method_name_spec.rb +16 -0
- data/spec/active_validation/values/version_spec.rb +36 -0
- data/spec/active_validation/verifier_spec.rb +214 -0
- data/spec/active_validation_spec.rb +19 -0
- data/spec/factories/internal/internal_check.rb +43 -0
- data/spec/features/active_record/child_record.feature +32 -0
- data/spec/features/active_record/new_record.feature +22 -0
- data/spec/features/no_orm/install.feature +19 -0
- data/spec/features/no_orm/validate.feature +27 -0
- data/spec/features/no_orm/validate_with_multiple_manifests.feature +29 -0
- data/spec/features/no_orm/validate_with_multiple_versions.feature +42 -0
- data/spec/features/placeholders/be_matcher.rb +7 -0
- data/spec/features/placeholders/klass.rb +5 -0
- data/spec/features/placeholders/version.rb +11 -0
- data/spec/features/placeholders/whether_to.rb +11 -0
- data/spec/features/step_definitions/active_record_steps.rb +7 -0
- data/spec/features/step_definitions/steps.rb +85 -0
- data/spec/orm/active_record/db_adapters/database.mysql.yml +12 -0
- data/spec/orm/active_record/db_adapters/database.postgres.yml +11 -0
- data/spec/orm/active_record/db_adapters/database.sqlite.yml +8 -0
- data/spec/orm/active_record/factories/check/check_validate.rb +8 -0
- data/spec/orm/active_record/factories/check/check_validates.rb +8 -0
- data/spec/orm/active_record/factories/check/check_validates_with.rb +19 -0
- data/spec/orm/active_record/factories/manifest.rb +29 -0
- data/spec/orm/active_record/prepare_db.rb +89 -0
- data/spec/orm/active_record/setup.rb +11 -0
- data/spec/orm/mongoid/setup.rb +15 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/database_cleaner.rb +16 -0
- data/spec/support/deferred_garbage_collection.rb +31 -0
- data/spec/support/define_constant_macros.rb +17 -0
- data/spec/support/factory_bot.rb +12 -0
- data/spec/support/helpers.rb +3 -0
- data/spec/support/helpers/only_with_active_record.rb +15 -0
- data/spec/support/matchers/delegate.rb +50 -0
- data/spec/support/matchers/have_attr.rb +58 -0
- data/spec/support/mongoid.yml +6 -0
- data/spec/support/shared_examples/check_attributes.rb +9 -0
- data/spec/support/shared_examples/verifiers_registry.rb +10 -0
- data/spec/support/simplecov.rb +11 -0
- data/spec/turnip_helper.rb +4 -0
- metadata +304 -20
- data/lib/activevalidation.rb +0 -6
- data/lib/activevalidation/version.rb +0 -3
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Decorators::ConsistentRegistry do
|
|
4
|
+
subject { described_class.new(klass, registry) }
|
|
5
|
+
|
|
6
|
+
let(:klass) { define_const("VerifierDouble") { def initialize(_arg); end } }
|
|
7
|
+
let(:bar) { define_const "Bar" }
|
|
8
|
+
|
|
9
|
+
let(:registry) { ActiveValidation::Registry.new("Great thing") }
|
|
10
|
+
let(:inconsistent_error_class) { ActiveValidation::Errors::InconsistentRegistryError }
|
|
11
|
+
|
|
12
|
+
let(:registered_object) { instance_double("registered object") }
|
|
13
|
+
|
|
14
|
+
context "#initialize" do
|
|
15
|
+
context "raise" do
|
|
16
|
+
it "raises an error if klass not provided" do
|
|
17
|
+
expect { described_class.new(nil, registry) }.to raise_error NameError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "raises an error if klass argument is not a class" do
|
|
21
|
+
expect { described_class.new(:not_a_class, registry) }.to raise_error NameError
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "works if klass provided as Class" do
|
|
26
|
+
expect(subject).to be_a ActiveValidation::Registry
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "works if klass provided as String" do
|
|
30
|
+
expect(described_class.new(klass.name, registry)).to be_a ActiveValidation::Registry
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "have :klass reader" do
|
|
35
|
+
decorator = described_class.new(klass, "name")
|
|
36
|
+
|
|
37
|
+
expect(decorator.klass).to eq(klass)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "#first_or_build" do
|
|
41
|
+
context "existed record" do
|
|
42
|
+
before { subject.register(bar.name, klass.new(bar)) }
|
|
43
|
+
|
|
44
|
+
it "find" do
|
|
45
|
+
expect(subject.find_or_build(bar.name)).to be_a klass
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "yield given block" do
|
|
49
|
+
expect { |b| subject.find_or_build(bar.name, &b) }.to yield_control
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "new record" do
|
|
54
|
+
it "if not found build a new record" do
|
|
55
|
+
expect(subject.find_or_build(klass.name)).to be_a klass
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "is not registered by registry by default" do
|
|
59
|
+
subject.find_or_build(klass.name)
|
|
60
|
+
expect(registry).not_to be_registered(klass.name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "yield given block on new record" do
|
|
64
|
+
klass_instance = klass.new bar
|
|
65
|
+
allow(klass).to receive(:new) do |record, &blk|
|
|
66
|
+
expect(record).to eq bar
|
|
67
|
+
expect(blk.call).to eq :passed
|
|
68
|
+
klass_instance
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
subject.find_or_build(bar, &-> { :passed })
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "#find_or_add" do
|
|
77
|
+
context "with existed record" do
|
|
78
|
+
before { subject.register(bar.name, klass.new(bar)) }
|
|
79
|
+
|
|
80
|
+
it "finds" do
|
|
81
|
+
expect(subject.find_or_add(bar.name)).to be_a klass
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "do not try to add record to registry" do
|
|
85
|
+
expect(registry).to include subject.find_or_add(bar.name)
|
|
86
|
+
expect(registry.count).to eq 1
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "with new record" do
|
|
91
|
+
it "finds" do
|
|
92
|
+
expect(subject.find_or_add(bar.name)).to be_a klass
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "add record to registry" do
|
|
96
|
+
expect(registry).to include subject.find_or_add(bar.name)
|
|
97
|
+
expect(registry.count).to eq 1
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "register" do
|
|
103
|
+
context "raise" do
|
|
104
|
+
it "with inconsistent value" do
|
|
105
|
+
value = define_const "Wrong"
|
|
106
|
+
expect { subject.register(bar.name, value) }.to raise_error ActiveValidation::Errors::InconsistentRegistryError
|
|
107
|
+
expect { subject.find(bar.name) }.to raise_error KeyError
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "registers the entry" do
|
|
112
|
+
value = klass.new(bar)
|
|
113
|
+
expect(subject.register(bar.name, value)).to eq value
|
|
114
|
+
expect(subject.find(bar.name)).to eq value
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Decorators::DisallowsDuplicatesRegistry do
|
|
4
|
+
subject { described_class.new(registry) }
|
|
5
|
+
|
|
6
|
+
let(:registry) { ActiveValidation::Registry.new("Great thing") }
|
|
7
|
+
let(:error_class) { ActiveValidation::Errors::DuplicateRegistryEntryError }
|
|
8
|
+
|
|
9
|
+
let(:registered_object) { instance_double("registered object") }
|
|
10
|
+
|
|
11
|
+
it "finds a registered object" do
|
|
12
|
+
subject.register(:object_name, registered_object)
|
|
13
|
+
expect { subject.register(:object_name, registered_object) }.to raise_error error_class
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "find a registered class" do
|
|
17
|
+
define_const "Foo"
|
|
18
|
+
subject.register(:object_name, Foo)
|
|
19
|
+
expect { subject.register(:object_name, Foo) }.to raise_error error_class
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Formatters::ValidationContextFormatter do
|
|
4
|
+
context "no options" do
|
|
5
|
+
context "no name" do
|
|
6
|
+
let(:manifest) do
|
|
7
|
+
instance_double ActiveValidation::Internal::Models::Manifest, id: 23, options: {}, name: nil
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it { expect(described_class.call(manifest)).to eq "active_validation_id23" }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "with name" do
|
|
14
|
+
let(:manifest) do
|
|
15
|
+
instance_double ActiveValidation::Internal::Models::Manifest, id: 23, options: {}, name: :my_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it { expect(described_class.call(manifest)).to eq "active_validation_id23_my_name" }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "with `on` option" do
|
|
23
|
+
context "no name" do
|
|
24
|
+
let(:manifest) do
|
|
25
|
+
instance_double ActiveValidation::Internal::Models::Manifest, id: 23, options: { on: :new }, name: nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it { expect(described_class.call(manifest)).to eq "active_validation_id23_on_new" }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "with name" do
|
|
32
|
+
let(:manifest) do
|
|
33
|
+
instance_double ActiveValidation::Internal::Models::Manifest, id: 23, options: { on: :new }, name: :my_name
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it { expect(described_class.call(manifest)).to eq "active_validation_id23_on_new_my_name" }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Internal::Models::Check do
|
|
4
|
+
subject { described_class.new method_name: "validates", argument: "name" }
|
|
5
|
+
|
|
6
|
+
let(:registry) { ActiveValidation.config.method_name_values_registry }
|
|
7
|
+
|
|
8
|
+
%i[method_name argument options created_at].each do |m|
|
|
9
|
+
it { is_expected.to have_attr_reader m }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "converts the method name to value object" do
|
|
13
|
+
expect(subject.method_name).to be_a ActiveValidation::Values::MethodName
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "add method name to the registry" do
|
|
17
|
+
registry.clear
|
|
18
|
+
subject
|
|
19
|
+
expect(registry.count).to eq 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "#to_hash" do
|
|
23
|
+
it "converts to Hash with out coercion" do
|
|
24
|
+
expect { Hash(subject) }.not_to raise_error
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "#as_json" do
|
|
29
|
+
%i[method_name argument options].each do |attr|
|
|
30
|
+
it("has '#{attr}' attribute") { expect(subject.as_json[attr]).to be_truthy }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "works correctly with out 'only' option" do
|
|
34
|
+
expect(subject.as_json).to eq subject.to_hash
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "produce right output with 'only' option argument" do
|
|
38
|
+
expect(subject.as_json(only: [:argument])).to eq(argument: "name")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "produce right output with 'only' option created_at" do
|
|
42
|
+
check = described_class.new method_name: "validates", argument: "name", created_at: "10AM"
|
|
43
|
+
expect(check.as_json(only: [:created_at])).to eq(created_at: "10AM")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "#normalized_argument" do
|
|
48
|
+
%i[validate validates].each do |m|
|
|
49
|
+
it "for #{m}" do
|
|
50
|
+
check = described_class.new method_name: m, argument: "name"
|
|
51
|
+
expect(check.normalized_argument).to eq :name
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "for validates_with" do
|
|
56
|
+
define_const "MyValidator", superclass: ActiveModel::Validator
|
|
57
|
+
check = described_class.new method_name: :validates_with, argument: "MyValidator"
|
|
58
|
+
expect(check.normalized_argument).to eq MyValidator
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "is equal" do
|
|
63
|
+
check1 = described_class.new method_name: "validates", argument: "name", options: { name: "foo" }
|
|
64
|
+
check2 = described_class.new method_name: "validates", argument: "name", options: { name: "foo" }
|
|
65
|
+
expect(check1).to eq check2
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Internal::Models::Manifest::Installer do
|
|
4
|
+
subject { described_class.new base_class: Bar, context: context }
|
|
5
|
+
|
|
6
|
+
let(:check_validate) { build :internal_check_validate }
|
|
7
|
+
let(:check_validates) { build :internal_check_validates }
|
|
8
|
+
let(:check_validates_with) { build :internal_check_validates_with }
|
|
9
|
+
|
|
10
|
+
let(:callbacks) { Bar._validate_callbacks.send(:chain) }
|
|
11
|
+
let(:context) { "active_validation_1" }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
define_const("Bar") { include ActiveModel::Validations }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
%i[base_class installed_callbacks checks context].each do |m|
|
|
18
|
+
it { is_expected.to have_attr_reader m }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "#install" do
|
|
22
|
+
context "with 3 validations" do
|
|
23
|
+
before do
|
|
24
|
+
subject.checks << check_validate << check_validates << check_validates_with
|
|
25
|
+
subject.install
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "setup validations to base_klass" do
|
|
29
|
+
expect(Bar.validators).to include a_kind_of ActiveModel::Validations::PresenceValidator
|
|
30
|
+
expect(Bar.validators).to include a_kind_of MyValidator
|
|
31
|
+
expect(Bar.validators.size).to eq 2
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "setups default factories callbacks to default model" do
|
|
35
|
+
expect(callbacks.size).to eq 3
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "setups installed callbacks to default model" do
|
|
39
|
+
expect(subject.installed_callbacks.size).to eq 3
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "validations should be in the right context" do
|
|
44
|
+
let(:callback) { callbacks.last }
|
|
45
|
+
let(:bar) { Bar.new }
|
|
46
|
+
|
|
47
|
+
shared_examples "check with context" do
|
|
48
|
+
it "does not execute with out the context" do
|
|
49
|
+
bar.valid?
|
|
50
|
+
expect(validator).not_to have_received(:validate)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "executes with the context" do
|
|
54
|
+
bar.valid?(subject.context)
|
|
55
|
+
expect(validator).to have_received(:validate)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "validates_with" do
|
|
60
|
+
let(:validator) { instance_double MyValidator }
|
|
61
|
+
|
|
62
|
+
before do
|
|
63
|
+
subject.checks << check_validates_with
|
|
64
|
+
allow(MyValidator).to receive(:new).and_return(validator)
|
|
65
|
+
allow(validator).to receive(:validate)
|
|
66
|
+
subject.install
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
include_examples "check with context"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "validates" do
|
|
73
|
+
let(:validator) { instance_double ActiveModel::Validations::PresenceValidator }
|
|
74
|
+
|
|
75
|
+
before do
|
|
76
|
+
subject.checks << check_validates
|
|
77
|
+
allow(ActiveModel::Validations::PresenceValidator).to receive(:new).and_return(validator)
|
|
78
|
+
allow(validator).to receive(:validate)
|
|
79
|
+
subject.install
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
include_examples "check with context"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "validate" do
|
|
86
|
+
before do
|
|
87
|
+
define_const("Bar") do
|
|
88
|
+
include ActiveModel::Validations
|
|
89
|
+
def my_method; end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
subject.checks << check_validate
|
|
93
|
+
allow(Bar).to receive(:new).and_return(bar)
|
|
94
|
+
allow(bar).to receive(:my_method)
|
|
95
|
+
subject.install
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "does not execute with out the context" do
|
|
99
|
+
bar.valid?
|
|
100
|
+
expect(bar).not_to have_received(:my_method)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "executes with the context" do
|
|
104
|
+
bar.valid?(subject.context)
|
|
105
|
+
expect(bar).to have_received(:my_method)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "#uninstall" do
|
|
112
|
+
let(:check_validate2) { build :internal_check_validate }
|
|
113
|
+
let(:check_validates2) { build :internal_check_validates }
|
|
114
|
+
let(:check_validates_with2) { build :internal_check_validates_with, argument: "MyValidator2" }
|
|
115
|
+
|
|
116
|
+
before do
|
|
117
|
+
define_const("Bar") { include ActiveModel::Validations }
|
|
118
|
+
subject.checks << check_validate << check_validates << check_validates_with
|
|
119
|
+
subject.install
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "should correctly remove all checks" do
|
|
123
|
+
before { subject.uninstall }
|
|
124
|
+
|
|
125
|
+
it("does not have any callback chain") { expect(callbacks).to be_empty }
|
|
126
|
+
|
|
127
|
+
it("does not contain any validators") { expect(Bar.validators).to be_empty }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "does not affect checks from another installer on another class" do
|
|
131
|
+
let(:installer2) { described_class.new context: context, base_class: Baz }
|
|
132
|
+
|
|
133
|
+
before do
|
|
134
|
+
define_const("Baz") { include ActiveModel::Validations }
|
|
135
|
+
installer2.checks << check_validate2 << check_validates2 << check_validates_with2
|
|
136
|
+
installer2.install
|
|
137
|
+
subject.uninstall
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it("does not have any callback chain") { expect(callbacks).to be_empty }
|
|
141
|
+
|
|
142
|
+
it("does not affect installer2 checks") { expect(installer2.callbacks_chain.count).to eq 3 }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context "does not other affect native checks on the base class" do
|
|
146
|
+
before do
|
|
147
|
+
subject.base_class.public_send(*check_validate2.to_validation_arguments)
|
|
148
|
+
subject.base_class.public_send(*check_validates_with2.to_validation_arguments)
|
|
149
|
+
subject.uninstall
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it("has 2 callbacks in the chain") { expect(callbacks.count).to eq 2 }
|
|
153
|
+
|
|
154
|
+
it("have correct validator") { expect(Bar.validators).to all(be_a_kind_of(MyValidator2)) }
|
|
155
|
+
it("has only one validator") { expect(Bar.validators.size).to eq 1 }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context "with nested class" do
|
|
159
|
+
let(:child) { described_class.new base_class: BarChild, context: context }
|
|
160
|
+
let(:child_callbacks) { BarChild._validate_callbacks.send(:chain) }
|
|
161
|
+
|
|
162
|
+
before do
|
|
163
|
+
define_const "BarChild", superclass: Bar
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it("has 3 callbacks in the chain") { expect(child_callbacks.count).to eq 3 }
|
|
167
|
+
it("has 2 validators") { expect(BarChild.validators.size).to eq 2 }
|
|
168
|
+
|
|
169
|
+
context "after uninstall on the parent" do
|
|
170
|
+
before { subject.uninstall }
|
|
171
|
+
|
|
172
|
+
it("has 0 callbacks in the chain") { expect(child_callbacks.count).to eq 0 }
|
|
173
|
+
it("has 0 validators") { expect(BarChild.validators.size).to eq 0 }
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Internal::Models::Manifest do
|
|
4
|
+
subject { described_class.new version: 1, base_klass: "Foo" }
|
|
5
|
+
|
|
6
|
+
before { define_const "Foo" }
|
|
7
|
+
|
|
8
|
+
let(:check_validate) { build :internal_check_validate }
|
|
9
|
+
let(:check_validates) { build :internal_check_validates }
|
|
10
|
+
let(:check_validates_with) { build :internal_check_validates_with }
|
|
11
|
+
|
|
12
|
+
%i[version base_klass created_at checks options other id name].each do |m|
|
|
13
|
+
it { is_expected.to have_attr_reader m }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "#class_name" do
|
|
17
|
+
it "converts the method name to value object" do
|
|
18
|
+
expect(subject.base_class).to eq Foo
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "equality check" do
|
|
23
|
+
it "if id is equal" do
|
|
24
|
+
common = { version: 1, base_klass: "Foo", id: 42 }
|
|
25
|
+
manifest1 = described_class.new common
|
|
26
|
+
manifest2 = described_class.new common
|
|
27
|
+
expect(manifest1).to eq manifest2
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "if attributes is equal, if even id are not" do
|
|
31
|
+
common = { version: 1, base_klass: "Foo", checks: [], options: { bar: :baz } }
|
|
32
|
+
manifest1 = described_class.new common.merge id: 1
|
|
33
|
+
manifest2 = described_class.new common.merge id: 2
|
|
34
|
+
expect(manifest1).to eq manifest2
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "#to_hash" do
|
|
39
|
+
it "converts to Hash with out coercion" do
|
|
40
|
+
expect { Hash(subject) }.not_to raise_error
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "#as_json" do
|
|
45
|
+
%i[version base_klass checks name id].each do |attr|
|
|
46
|
+
it("has '#{attr}' attribute") { expect(subject.as_json).to have_key attr }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "works correctly with out 'only' option" do
|
|
50
|
+
expect(subject.as_json).to eq subject.to_hash
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "produce right output with 'only' option base_klass" do
|
|
54
|
+
expect(subject.as_json(only: [:base_klass])).to eq(base_klass: "Foo")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "with checks" do
|
|
58
|
+
subject { described_class.new version: 1, base_klass: "Foo", checks: [check1, check2] }
|
|
59
|
+
|
|
60
|
+
let(:check1) { build :internal_check_validates, argument: "check1" }
|
|
61
|
+
let(:check2) { build :internal_check_validate, argument: "check2" }
|
|
62
|
+
|
|
63
|
+
it "with out options" do
|
|
64
|
+
hash = { version: 1,
|
|
65
|
+
base_klass: "Foo",
|
|
66
|
+
checks: [{ method_name: "validates", argument: "check1", options: { "presence" => true } },
|
|
67
|
+
{ method_name: "validate", argument: "check2", options: {} }],
|
|
68
|
+
name: nil,
|
|
69
|
+
id: nil }
|
|
70
|
+
expect(subject.as_json).to eq hash
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "with options for manifest" do
|
|
74
|
+
hash = { version: 1,
|
|
75
|
+
checks: [{ method_name: "validates", argument: "check1", options: { "presence" => true } },
|
|
76
|
+
{ method_name: "validate", argument: "check2", options: {} }] }
|
|
77
|
+
expect(subject.as_json(only: %i[checks version])).to eq hash
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "with options for checks" do
|
|
81
|
+
hash = { version: 1,
|
|
82
|
+
base_klass: "Foo",
|
|
83
|
+
checks: [{ argument: "check1" },
|
|
84
|
+
{ argument: "check2" }],
|
|
85
|
+
name: nil,
|
|
86
|
+
id: nil }
|
|
87
|
+
expect(subject.as_json(checks: { only: [:argument] })).to eq hash
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "with renamed checks" do
|
|
91
|
+
hash = { version: 1,
|
|
92
|
+
base_klass: "Foo",
|
|
93
|
+
checks_attributes: [{ method_name: "validates", argument: "check1", options: { "presence" => true } },
|
|
94
|
+
{ method_name: "validate", argument: "check2", options: {} }],
|
|
95
|
+
name: nil,
|
|
96
|
+
id: nil }
|
|
97
|
+
expect(subject.as_json(checks: { as: :checks_attributes })).to eq hash
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "installation" do
|
|
103
|
+
before do
|
|
104
|
+
allow(ActiveValidation::Internal::Models::Manifest::Installer).to receive(:new).and_return(installer)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
let(:installer) do
|
|
108
|
+
instance_double ActiveValidation::Internal::Models::Manifest::Installer, uninstall: false, install: true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "install" do
|
|
112
|
+
before { subject.install }
|
|
113
|
+
|
|
114
|
+
it("installs once installed") do
|
|
115
|
+
subject.install
|
|
116
|
+
expect(installer).to have_received(:install).once
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it { expect(subject).to be_installed }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "uninstall" do
|
|
123
|
+
before do
|
|
124
|
+
subject.install
|
|
125
|
+
subject.uninstall
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it("uninstalls once when installed") do
|
|
129
|
+
subject.uninstall
|
|
130
|
+
expect(installer).to have_received(:uninstall).once
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it { expect(subject).not_to be_installed }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|