summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Maczukin <tomasz@maczukin.pl>2018-03-21 17:22:52 +0100
committerTomasz Maczukin <tomasz@maczukin.pl>2018-03-28 13:58:35 +0200
commitc747d9bc0b35d2982f45e2e8a0bdaa305f504f38 (patch)
treec1f6ebb697c3d0f169e1f3659a7499e782a511de
parented86344f4941ce8b30546260b8437451026c8d97 (diff)
downloadgitlab-ce-c747d9bc0b35d2982f45e2e8a0bdaa305f504f38.tar.gz
Add validation for chronic_duration_attr_writer
-rw-r--r--app/models/concerns/chronic_duration_attribute.rb27
-rw-r--r--spec/models/concerns/chronic_duration_attribute_spec.rb66
2 files changed, 74 insertions, 19 deletions
diff --git a/app/models/concerns/chronic_duration_attribute.rb b/app/models/concerns/chronic_duration_attribute.rb
index 15095d0b758..ad8934f58d8 100644
--- a/app/models/concerns/chronic_duration_attribute.rb
+++ b/app/models/concerns/chronic_duration_attribute.rb
@@ -18,13 +18,32 @@ module ChronicDurationAttribute
end
def chronic_duration_attr_writer(virtual_attribute, source_attribute)
+ virtual_attribute_validator = "#{virtual_attribute}_validator".to_sym
+ validation_error = "#{virtual_attribute}_error".to_sym
+
+ validate virtual_attribute_validator
+ attr_accessor validation_error
+
define_method("#{virtual_attribute}=") do |value|
- new_value = ChronicDuration.parse(value).to_i unless value.nil?
- new_value = nil if !new_value.nil? && new_value <= 0
+ begin
+ self.send("#{validation_error}=", '') # rubocop:disable GitlabSecurity/PublicSend
- self.send("#{source_attribute}=", new_value) # rubocop:disable GitlabSecurity/PublicSend
+ new_value =
+ if value.blank?
+ nil
+ else
+ ChronicDuration.parse(value).to_i
+ end
+
+ self.send("#{source_attribute}=", new_value) # rubocop:disable GitlabSecurity/PublicSend
+ rescue ChronicDuration::DurationParseError => ex
+ self.send("#{validation_error}=", ex.message) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
- new_value
+ define_method(virtual_attribute_validator) do
+ error = self.send(validation_error) # rubocop:disable GitlabSecurity/PublicSend
+ self.send('errors').add(source_attribute, error) unless error.blank? # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/spec/models/concerns/chronic_duration_attribute_spec.rb b/spec/models/concerns/chronic_duration_attribute_spec.rb
index cfbf83dab54..fea3e752ab5 100644
--- a/spec/models/concerns/chronic_duration_attribute_spec.rb
+++ b/spec/models/concerns/chronic_duration_attribute_spec.rb
@@ -11,10 +11,12 @@ shared_examples 'ChronicDurationAttribute reader' do
expect(subject.send(virtual_field)).to eq('2m')
end
- it 'outputs empty string when value set to nil' do
- subject.send("#{source_field}=", nil)
+ context 'when value is set to nil' do
+ it 'outputs empty string' do
+ subject.send("#{source_field}=", nil)
- expect(subject.send(virtual_field)).to be_empty
+ expect(subject.send(virtual_field)).to be_empty
+ end
end
end
@@ -29,28 +31,62 @@ shared_examples 'ChronicDurationAttribute writer' do
expect(subject.send(source_field)).to eq(600)
end
- it 'writes nil when empty input is used' do
- subject.send("#{virtual_field}=", '')
+ it 'passes validation' do
+ subject.send("#{virtual_field}=", '10m')
- expect(subject.send(source_field)).to be_nil
+ expect(subject.valid?).to be_truthy
end
- it 'writes nil when negative input is used' do
- allow(ChronicDuration).to receive(:parse).and_return(-10)
+ context 'when negative input is used' do
+ before do
+ subject.send("#{source_field}=", 3600)
+ end
+
+ it "doesn't raise exception" do
+ expect { subject.send("#{virtual_field}=", '-10m') }.not_to raise_error(ChronicDuration::DurationParseError)
+ end
+
+ it "doesn't change value" do
+ expect { subject.send("#{virtual_field}=", '-10m') }.not_to change { subject.send(source_field) }
+ end
- subject.send("#{virtual_field}=", '-10m')
+ it "doesn't pass validation" do
+ subject.send("#{virtual_field}=", '-10m')
- expect(subject.send(source_field)).to be_nil
+ expect(subject.valid?).to be_falsey
+ end
end
- it 'writes nil when nil input is used' do
- subject.send("#{virtual_field}=", nil)
+ context 'when empty input is used' do
+ it 'writes nil' do
+ subject.send("#{virtual_field}=", '')
+
+ expect(subject.send(source_field)).to be_nil
+ end
+
+ it 'passes validation' do
+ subject.send("#{virtual_field}=", '')
- expect(subject.send(source_field)).to be_nil
+ expect(subject.valid?).to be_truthy
+ end
end
- it "doesn't raise exception when nil input is used" do
- expect { subject.send("#{virtual_field}=", nil) }.not_to raise_error(NoMethodError)
+ context 'when nil input is used' do
+ it 'writes nil' do
+ subject.send("#{virtual_field}=", nil)
+
+ expect(subject.send(source_field)).to be_nil
+ end
+
+ it 'passes validation' do
+ subject.send("#{virtual_field}=", nil)
+
+ expect(subject.valid?).to be_truthy
+ end
+
+ it "doesn't raise exception" do
+ expect { subject.send("#{virtual_field}=", nil) }.not_to raise_error(NoMethodError)
+ end
end
end