volt 0.8.27.beta2 → 0.8.27.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -0
- data/CHANGELOG.md +7 -2
- data/CONTRIBUTING.md +133 -0
- data/Gemfile +0 -1
- data/Rakefile +11 -3
- data/Readme.md +4 -4
- data/VERSION +1 -1
- data/app/volt/models/user.rb +6 -3
- data/lib/volt/cli/console.rb +21 -12
- data/lib/volt/cli/runner.rb +1 -1
- data/lib/volt/cli.rb +5 -4
- data/lib/volt/config.rb +9 -11
- data/lib/volt/controllers/model_controller.rb +16 -0
- data/lib/volt/data_stores/data_store.rb +1 -1
- data/lib/volt/extra_core/array.rb +1 -6
- data/lib/volt/extra_core/blank.rb +1 -3
- data/lib/volt/extra_core/class.rb +1 -1
- data/lib/volt/extra_core/extra_core.rb +0 -1
- data/lib/volt/extra_core/logger.rb +78 -1
- data/lib/volt/extra_core/object.rb +4 -4
- data/lib/volt/models/array_model.rb +2 -3
- data/lib/volt/models/buffer.rb +1 -2
- data/lib/volt/models/field_helpers.rb +4 -5
- data/lib/volt/models/model.rb +27 -1
- data/lib/volt/models/model_hash_behaviour.rb +3 -4
- data/lib/volt/models/persistors/array_store.rb +6 -7
- data/lib/volt/models/persistors/cookies.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +5 -6
- data/lib/volt/models/validations.rb +5 -7
- data/lib/volt/models/validators/email_validator.rb +8 -29
- data/lib/volt/models/validators/format_validator.rb +116 -0
- data/lib/volt/models/validators/numericality_validator.rb +2 -2
- data/lib/volt/models/validators/phone_number_validator.rb +8 -29
- data/lib/volt/models/validators/unique_validator.rb +2 -2
- data/lib/volt/page/bindings/content_binding.rb +1 -1
- data/lib/volt/page/bindings/each_binding.rb +1 -1
- data/lib/volt/page/bindings/template_binding/view_lookup_for_path.rb +92 -0
- data/lib/volt/page/bindings/template_binding.rb +10 -85
- data/lib/volt/page/channel.rb +0 -1
- data/lib/volt/page/page.rb +5 -7
- data/lib/volt/page/sub_context.rb +1 -1
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/helpers/comment_searchers.rb +2 -2
- data/lib/volt/reactive/reactive_accessors.rb +1 -1
- data/lib/volt/reactive/reactive_array.rb +6 -6
- data/lib/volt/router/routes.rb +4 -4
- data/lib/volt/server/rack/asset_files.rb +1 -2
- data/lib/volt/server/rack/component_code.rb +0 -2
- data/lib/volt/server/rack/component_paths.rb +2 -2
- data/lib/volt/server/rack/quiet_common_logger.rb +2 -2
- data/lib/volt/spec/capybara.rb +1 -1
- data/lib/volt/spec/sauce_labs.rb +6 -6
- data/lib/volt/spec/setup.rb +8 -7
- data/lib/volt/tasks/dispatcher.rb +12 -10
- data/lib/volt/tasks/task_handler.rb +1 -1
- data/lib/volt/utils/generic_pool.rb +2 -2
- data/lib/volt/volt/users.rb +7 -9
- data/lib/volt.rb +2 -4
- data/spec/apps/file_loading/app/missing_deps/config/dependencies.rb +1 -1
- data/spec/apps/kitchen_sink/Gemfile +2 -2
- data/spec/apps/kitchen_sink/app/main/config/dependencies.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +0 -1
- data/spec/apps/kitchen_sink/app/main/models/user.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -1
- data/spec/apps/kitchen_sink/config/app.rb +1 -1
- data/spec/extra_core/array_spec.rb +4 -2
- data/spec/extra_core/blank_spec.rb +11 -0
- data/spec/extra_core/class_spec.rb +2 -2
- data/spec/extra_core/logger_spec.rb +50 -0
- data/spec/extra_core/string_transformations_spec.rb +0 -1
- data/spec/integration/cookies_spec.rb +1 -2
- data/spec/integration/flash_spec.rb +2 -3
- data/spec/integration/list_spec.rb +1 -1
- data/spec/integration/templates_spec.rb +0 -1
- data/spec/integration/url_spec.rb +1 -2
- data/spec/integration/user_spec.rb +3 -3
- data/spec/models/field_helpers_spec.rb +2 -2
- data/spec/models/model_spec.rb +21 -2
- data/spec/models/user_spec.rb +69 -0
- data/spec/models/validations_spec.rb +69 -78
- data/spec/models/validators/email_validator_spec.rb +3 -3
- data/spec/models/validators/format_validator_spec.rb +144 -0
- data/spec/models/validators/length_validator_spec.rb +82 -0
- data/spec/models/validators/phone_number_validator_spec.rb +3 -3
- data/spec/page/bindings/template_binding/view_lookup_for_path_spec.rb +149 -0
- data/spec/page/bindings/template_binding_spec.rb +0 -151
- data/spec/reactive/computation_spec.rb +46 -0
- data/spec/reactive/dependency_spec.rb +0 -1
- data/spec/reactive/reactive_array_spec.rb +0 -1
- data/spec/router/routes_spec.rb +0 -4
- data/spec/server/html_parser/view_parser_spec.rb +0 -4
- data/spec/server/rack/asset_files_spec.rb +1 -1
- data/spec/server/rack/quite_common_logger_spec.rb +55 -0
- data/spec/spec_helper.rb +2 -5
- data/spec/tasks/dispatcher_spec.rb +16 -5
- data/spec/tasks/live_query_spec.rb +0 -1
- data/spec/tasks/query_tasks.rb +0 -1
- data/spec/tasks/query_tracker_spec.rb +0 -3
- data/spec/templates/targets/binding_document/component_node_spec.rb +0 -1
- data/spec/utils/generic_counting_pool_spec.rb +0 -1
- data/spec/utils/generic_pool_spec.rb +0 -1
- data/templates/component/assets/images/.empty_directory +0 -0
- data/templates/project/README.md.tt +3 -2
- data/templates/project/app/main/assets/images/.empty_directory +0 -0
- data/templates/project/config/base/index.html +6 -7
- data/volt.gemspec +3 -5
- metadata +27 -9
- data/lib/volt/extra_core/numeric.rb +0 -9
@@ -0,0 +1,50 @@
|
|
1
|
+
if RUBY_PLATFORM != 'opal'
|
2
|
+
describe Volt::VoltLogger do
|
3
|
+
let(:args) { [5, :arg2] }
|
4
|
+
let(:class_name) { 'ClassName' }
|
5
|
+
let(:method_name) { 'method_name' }
|
6
|
+
let(:run_time) { 50 }
|
7
|
+
|
8
|
+
let(:logger) { Volt::VoltLogger.new }
|
9
|
+
|
10
|
+
let(:logger_with_opts) do
|
11
|
+
Volt::VoltLogger.new({
|
12
|
+
args: args,
|
13
|
+
class_name: class_name,
|
14
|
+
method_name: method_name,
|
15
|
+
run_time: run_time
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should log only severity and message wrapped in line breaks' do
|
20
|
+
expect(STDOUT).to receive(:write).with("\n\n[INFO] message\n")
|
21
|
+
logger.log(Logger::INFO, "message")
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should convert an array of arguments into a string' do
|
25
|
+
expect(logger_with_opts.args).to eq([5, :arg2])
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when STDOUT is a TTY' do
|
29
|
+
it 'should return a blue class name' do
|
30
|
+
expect(logger_with_opts.class_name).to eq("\e[1;34m#{class_name}\e[0;37m")
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should return a green method name' do
|
34
|
+
expect(logger_with_opts.method_name).to eq("\e[0;32m#{method_name}\e[0;37m")
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return a green run time in milliseconds' do
|
38
|
+
expect(logger_with_opts.run_time).to eq("\e[0;32m#{run_time}ms\e[0;37m")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when STDOUT is not a TTY' do
|
43
|
+
before { allow(STDOUT).to receive(:tty?).and_return(false) }
|
44
|
+
|
45
|
+
it 'should not add any terminal color codes' do
|
46
|
+
expect(logger_with_opts.class_name).to eq(class_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
if ENV['BROWSER'] && ENV['BROWSER'] != 'sauce'
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'flash messages', type: :feature, :
|
5
|
+
describe 'flash messages', type: :feature, sauce: true do
|
6
6
|
it 'should flash on sucesses, notices, warnings, and errors' do
|
7
7
|
visit '/'
|
8
8
|
|
@@ -27,7 +27,6 @@ if ENV['BROWSER'] && ENV['BROWSER'] != 'sauce'
|
|
27
27
|
expect(page).to have_content('An error message')
|
28
28
|
find('.alert').click
|
29
29
|
expect(page).to_not have_content('An error message')
|
30
|
-
|
31
30
|
end
|
32
31
|
end
|
33
|
-
end
|
32
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
if ENV['BROWSER']
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe 'user accounts', type: :feature, sauce: true do
|
5
5
|
before(:each) do
|
6
6
|
# Clear out db
|
7
7
|
DataStore.new.drop_database
|
@@ -38,7 +38,7 @@ if ENV['BROWSER']
|
|
38
38
|
visit '/'
|
39
39
|
|
40
40
|
# Add the user
|
41
|
-
$page.store._users << {email: 'test@test.com', password: 'awes0mesEcRet', name: 'Test Account 9550'}
|
41
|
+
$page.store._users << { email: 'test@test.com', password: 'awes0mesEcRet', name: 'Test Account 9550' }
|
42
42
|
|
43
43
|
click_link 'Login'
|
44
44
|
|
@@ -77,4 +77,4 @@ if ENV['BROWSER']
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
end
|
80
|
+
end
|
@@ -6,7 +6,7 @@ class ExampleModelWithField < Volt::Model
|
|
6
6
|
field :value, Numeric
|
7
7
|
end
|
8
8
|
|
9
|
-
describe
|
9
|
+
describe 'field helpers' do
|
10
10
|
it 'should allow a user to setup a field that can be written to and read' do
|
11
11
|
model = ExampleModelWithField.new
|
12
12
|
|
@@ -26,4 +26,4 @@ describe "field helpers" do
|
|
26
26
|
ExampleModelWithField.field :awesome, Array
|
27
27
|
end.to raise_error(FieldHelpers::InvalidFieldClass)
|
28
28
|
end
|
29
|
-
end
|
29
|
+
end
|
data/spec/models/model_spec.rb
CHANGED
@@ -8,7 +8,6 @@ class Item < Volt::Model
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe Volt::Model do
|
11
|
-
|
12
11
|
it 'should allow _ methods to be used to store values without predefining them' do
|
13
12
|
a = Volt::Model.new
|
14
13
|
a._stash = 'yes'
|
@@ -131,7 +130,6 @@ describe Volt::Model do
|
|
131
130
|
Volt::Computation.flush!
|
132
131
|
|
133
132
|
expect(values).to eq([nil, 'one'])
|
134
|
-
|
135
133
|
end
|
136
134
|
|
137
135
|
it 'should trigger changed for any indicies after a deleted index' do
|
@@ -401,6 +399,27 @@ describe Volt::Model do
|
|
401
399
|
end
|
402
400
|
end
|
403
401
|
|
402
|
+
describe 'reserved attributes' do
|
403
|
+
let(:model) { Volt::Model.new }
|
404
|
+
|
405
|
+
it 'should prevent reserved attributes from being read with underscores' do
|
406
|
+
[:attributes, :parent, :path, :options, :persistor].each do |attr_name|
|
407
|
+
expect do
|
408
|
+
model.send(:"_#{attr_name}")
|
409
|
+
end.to raise_error(Volt::InvalidFieldName, "`#{attr_name}` is reserved and can not be used as a field")
|
410
|
+
end
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'should prevent reserved attributes from being assigned directly' do
|
415
|
+
[:attributes, :parent, :path, :options, :persistor].each do |attr_name|
|
416
|
+
expect do
|
417
|
+
model.send(:"_#{attr_name}=", 'assign val')
|
418
|
+
end.to raise_error(Volt::InvalidFieldName, "`#{attr_name}` is reserved and can not be used as a field")
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
404
423
|
describe 'persistors' do
|
405
424
|
it 'should setup a new instance of the persistor with self' do
|
406
425
|
persistor = double('volt/persistor')
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'volt/models/user'
|
3
|
+
|
4
|
+
class FakeConfig
|
5
|
+
def public; self; end
|
6
|
+
def auth; self; end
|
7
|
+
def use_username; true; end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Volt::User do
|
11
|
+
describe '.login_field' do
|
12
|
+
subject { Volt::User.login_field }
|
13
|
+
|
14
|
+
context 'when use_username is set to true' do
|
15
|
+
before do
|
16
|
+
allow(Volt).to receive(:config).and_return FakeConfig.new
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns :username" do
|
20
|
+
expect(subject).to eq :username
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when use_username is not set' do
|
25
|
+
it "returns :email" do
|
26
|
+
expect(subject).to eq :email
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#password=' do
|
32
|
+
let!(:user) { Volt::User.new }
|
33
|
+
|
34
|
+
subject { user.password = 'test' }
|
35
|
+
|
36
|
+
if RUBY_PLATFORM != 'opal'
|
37
|
+
context 'when it is a Volt server' do
|
38
|
+
before do
|
39
|
+
allow(BCrypt::Password).to receive(:create).with('test').
|
40
|
+
and_return 'hashed-password'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "encrypts password" do
|
44
|
+
subject
|
45
|
+
|
46
|
+
expect(BCrypt::Password).to have_received :create
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'sets _hashed_password to passed value' do
|
50
|
+
subject
|
51
|
+
|
52
|
+
expect(user._hashed_password).to eq "hashed-password"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when it is not a Volt server' do
|
58
|
+
before do
|
59
|
+
allow(Volt).to receive(:server?).and_return false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'sets _password to passed value' do
|
63
|
+
subject
|
64
|
+
|
65
|
+
expect(user._password).to eq 'test'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class TestModel < Volt::Model
|
4
|
-
validate :count, numericality: { min: 5, max: 10 }
|
5
|
-
validate :description, length: { message: 'needs to be longer', length: 50 }
|
6
|
-
validate :email, email: true
|
7
|
-
validate :name, length: 4
|
8
|
-
validate :phone_number, phone_number: true
|
9
|
-
validate :username, presence: true
|
10
|
-
end
|
11
|
-
|
12
3
|
describe Volt::Model do
|
13
|
-
|
14
|
-
|
4
|
+
let(:model) { test_model_class.new }
|
5
|
+
|
6
|
+
let(:test_model_class) do
|
7
|
+
Class.new(Volt::Model) do
|
8
|
+
validate :count, numericality: { min: 5, max: 10 }
|
9
|
+
validate :description, length: { message: 'needs to be longer',
|
10
|
+
length: 50 }
|
11
|
+
validate :email, email: true
|
12
|
+
validate :name, length: 4
|
13
|
+
validate :phone_number, phone_number: true
|
14
|
+
validate :username, presence: true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return errors for all failed validations' do
|
19
|
+
expect(model.errors).to eq(
|
15
20
|
count: ['must be a number'],
|
16
21
|
description: ['needs to be longer'],
|
17
22
|
email: ['must be an email address'],
|
@@ -21,23 +26,7 @@ describe Volt::Model do
|
|
21
26
|
)
|
22
27
|
end
|
23
28
|
|
24
|
-
it 'should show marked validations once they are marked' do
|
25
|
-
model = TestModel.new
|
26
|
-
|
27
|
-
expect(model.marked_errors).to eq({})
|
28
|
-
|
29
|
-
model.mark_field!(:name)
|
30
|
-
|
31
|
-
expect(model.marked_errors).to eq(
|
32
|
-
name: ['must be at least 4 characters']
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
29
|
it 'should show all fields in marked errors once saved' do
|
37
|
-
model = TestModel.new
|
38
|
-
|
39
|
-
expect(model.marked_errors).to eq({})
|
40
|
-
|
41
30
|
model.save!
|
42
31
|
|
43
32
|
expect(model.marked_errors.keys).to eq(
|
@@ -45,73 +34,75 @@ describe Volt::Model do
|
|
45
34
|
)
|
46
35
|
end
|
47
36
|
|
48
|
-
describe '
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
expect(model.marked_errors).to eq(
|
57
|
-
description: ['needs to be longer']
|
58
|
-
)
|
37
|
+
describe 'builtin validations' do
|
38
|
+
shared_examples_for 'a built in validation' do |field, message|
|
39
|
+
specify do
|
40
|
+
expect { model.mark_field! field }
|
41
|
+
.to change { model.marked_errors }
|
42
|
+
.from({}).to({ field => [message ] })
|
43
|
+
end
|
59
44
|
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe 'presence' do
|
63
|
-
it 'should validate presence' do
|
64
|
-
model = TestModel.new
|
65
|
-
|
66
|
-
expect(model.marked_errors).to eq({})
|
67
45
|
|
68
|
-
|
46
|
+
describe 'numericality' do
|
47
|
+
message = 'must be a number'
|
48
|
+
it_should_behave_like 'a built in validation', :count, message
|
49
|
+
end
|
69
50
|
|
70
|
-
|
71
|
-
|
72
|
-
|
51
|
+
describe 'length' do
|
52
|
+
message = 'needs to be longer'
|
53
|
+
it_should_behave_like 'a built in validation', :description, message
|
73
54
|
end
|
74
|
-
end
|
75
55
|
|
76
|
-
|
77
|
-
|
78
|
-
|
56
|
+
describe 'email' do
|
57
|
+
message = 'must be an email address'
|
58
|
+
it_should_behave_like 'a built in validation', :email, message
|
59
|
+
end
|
79
60
|
|
80
|
-
|
61
|
+
describe 'name' do
|
62
|
+
message = 'must be at least 4 characters'
|
63
|
+
it_should_behave_like 'a built in validation', :name, message
|
64
|
+
end
|
81
65
|
|
82
|
-
|
66
|
+
describe 'phone_number' do
|
67
|
+
message = 'must be a phone number with area or country code'
|
68
|
+
it_should_behave_like 'a built in validation', :phone_number, message
|
69
|
+
end
|
83
70
|
|
84
|
-
|
85
|
-
|
86
|
-
|
71
|
+
describe 'presence' do
|
72
|
+
message = 'must be specified'
|
73
|
+
it_should_behave_like 'a built in validation', :username, message
|
87
74
|
end
|
88
75
|
end
|
89
76
|
|
90
|
-
describe '
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
77
|
+
describe 'validators with multiple criteria' do
|
78
|
+
let(:regex_message) { 'regex failed' }
|
79
|
+
let(:proc_message) { 'proc failed' }
|
80
|
+
|
81
|
+
let(:test_model_class) do
|
82
|
+
Class.new(Volt::Model) do
|
83
|
+
validate :special_field, format: [
|
84
|
+
{ with: /regex/, message: 'regex failed' },
|
85
|
+
{ with: ->(x) {x == false}, message: 'proc failed' }
|
86
|
+
]
|
87
|
+
end
|
101
88
|
end
|
102
|
-
end
|
103
89
|
|
104
|
-
|
105
|
-
|
106
|
-
model = TestModel.new
|
90
|
+
context 'when multiple fail' do
|
91
|
+
before { model._special_field = 'nope' }
|
107
92
|
|
108
|
-
|
93
|
+
it 'returns an array of errors' do
|
94
|
+
expect(model.errors).to eq({
|
95
|
+
special_field: [ regex_message, proc_message ]
|
96
|
+
})
|
97
|
+
end
|
98
|
+
end
|
109
99
|
|
110
|
-
|
100
|
+
context 'when one fails' do
|
101
|
+
before { model._special_field = 'regex' }
|
111
102
|
|
112
|
-
|
113
|
-
|
114
|
-
|
103
|
+
it 'returns an array with a single error' do
|
104
|
+
expect(model.errors).to eq({ special_field: [ proc_message ] })
|
105
|
+
end
|
115
106
|
end
|
116
107
|
end
|
117
108
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Volt::EmailValidator do
|
4
4
|
subject { Volt::EmailValidator.new(*params) }
|
5
|
-
let(:params) { [
|
5
|
+
let(:params) { [model, field_name, options] }
|
6
6
|
|
7
7
|
let(:model) { Volt::Model.new email: email }
|
8
8
|
let(:field_name) { :email }
|
@@ -105,14 +105,14 @@ describe Volt::EmailValidator do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
context 'when provided a custom error message' do
|
108
|
-
let(:options) { {
|
108
|
+
let(:options) { { message: custom_message } }
|
109
109
|
let(:custom_message) { 'this is a custom message' }
|
110
110
|
|
111
111
|
context 'and the email is invalid' do
|
112
112
|
let(:email) { invalid_email }
|
113
113
|
|
114
114
|
it 'returns errors with the custom message' do
|
115
|
-
expect(subject.errors).to eq(email: [
|
115
|
+
expect(subject.errors).to eq(email: [custom_message])
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Volt::FormatValidator do
|
4
|
+
subject { described_class.new(*init_params) }
|
5
|
+
|
6
|
+
let(:init_params) { [ model, field_name ] }
|
7
|
+
let(:validate_params) { [ model, nil, field_name, options ] }
|
8
|
+
|
9
|
+
let(:model) { Volt::Model.new field: field_content }
|
10
|
+
let(:field_name) { :field }
|
11
|
+
let(:options) { regex_opts }
|
12
|
+
|
13
|
+
let(:regex) { /^valid/ }
|
14
|
+
let(:proc_regex) { /^valid/ }
|
15
|
+
let(:test_proc) { ->(content) { proc_regex.match content } }
|
16
|
+
|
17
|
+
let(:proc_opts) { { with: test_proc, message: proc_message } }
|
18
|
+
let(:regex_opts) { { with: regex, message: regex_message } }
|
19
|
+
|
20
|
+
let(:proc_message) { 'proc is invalid' }
|
21
|
+
let(:regex_message) { 'regex is invalid' }
|
22
|
+
|
23
|
+
let(:field_content) { valid_content }
|
24
|
+
let(:invalid_content) { 'invalid_content' }
|
25
|
+
let(:valid_content) { 'valid_content' }
|
26
|
+
|
27
|
+
let(:validate) { described_class.validate(*validate_params) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(described_class).to receive(:new).and_return subject
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when no criteria is provided' do
|
34
|
+
before { validate }
|
35
|
+
|
36
|
+
it 'should have no errors' do
|
37
|
+
expect(subject.errors).to eq({})
|
38
|
+
end
|
39
|
+
|
40
|
+
specify { expect(subject).to be_valid }
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when the only criterion is a regex' do
|
44
|
+
let(:options) { regex_opts }
|
45
|
+
|
46
|
+
before { validate }
|
47
|
+
|
48
|
+
context 'and the field matches' do
|
49
|
+
let(:field_content) { valid_content }
|
50
|
+
|
51
|
+
it 'should have no errors' do
|
52
|
+
expect(subject.errors).to eq({})
|
53
|
+
end
|
54
|
+
|
55
|
+
specify { expect(subject).to be_valid }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'and the field does not match' do
|
59
|
+
let(:field_content) { invalid_content }
|
60
|
+
|
61
|
+
it 'should report the related error message' do
|
62
|
+
expect(subject.errors).to eq field_name => [regex_message]
|
63
|
+
end
|
64
|
+
|
65
|
+
specify { expect(subject).to_not be_valid }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when the only criterion is a block' do
|
70
|
+
let(:options) { proc_opts }
|
71
|
+
|
72
|
+
before { validate }
|
73
|
+
|
74
|
+
context 'and the field passes the block' do
|
75
|
+
let(:field_content) { valid_content }
|
76
|
+
|
77
|
+
it 'should have no errors' do
|
78
|
+
expect(subject.errors).to eq({})
|
79
|
+
end
|
80
|
+
|
81
|
+
specify { expect(subject).to be_valid }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'and the field fails the block' do
|
85
|
+
let(:field_content) { invalid_content }
|
86
|
+
|
87
|
+
it 'should report the related error message' do
|
88
|
+
expect(subject.errors).to eq field_name => [proc_message]
|
89
|
+
end
|
90
|
+
|
91
|
+
specify { expect(subject).to_not be_valid }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when there is both regex and block criteria' do
|
96
|
+
let(:options) { [ regex_opts, proc_opts ] }
|
97
|
+
|
98
|
+
before { validate }
|
99
|
+
|
100
|
+
context 'and the field passes all criteria' do
|
101
|
+
let(:field_content) { valid_content }
|
102
|
+
|
103
|
+
it 'should have no errors' do
|
104
|
+
expect(subject.errors).to eq({})
|
105
|
+
end
|
106
|
+
|
107
|
+
specify { expect(subject).to be_valid }
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'and the field fails the regex' do
|
111
|
+
let(:regex) { /^invalid/ }
|
112
|
+
|
113
|
+
it 'should report the related error message' do
|
114
|
+
expect(subject.errors).to eq field_name => [regex_message]
|
115
|
+
end
|
116
|
+
|
117
|
+
specify { expect(subject).to_not be_valid }
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'and the field fails the block' do
|
121
|
+
let(:proc_regex) { /^invalid/ }
|
122
|
+
|
123
|
+
it 'should report the related error message' do
|
124
|
+
expect(subject.errors).to eq field_name => [proc_message]
|
125
|
+
end
|
126
|
+
|
127
|
+
specify { expect(subject).to_not be_valid }
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'and the field fails both the regex and the block' do
|
131
|
+
let(:field_content) { invalid_content }
|
132
|
+
|
133
|
+
it 'should report the regex error message' do
|
134
|
+
expect(subject.errors[field_name]).to include regex_message
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should report the proc error message' do
|
138
|
+
expect(subject.errors[field_name]).to include proc_message
|
139
|
+
end
|
140
|
+
|
141
|
+
specify { expect(subject).to_not be_valid }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|