7 changed files with 81 additions and 20 deletions
@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class PollExpirationValidator < ActiveModel::Validator |
||||
MAX_EXPIRATION = 1.month.freeze |
||||
MIN_EXPIRATION = 5.minutes.freeze |
||||
|
||||
def validate(poll) |
||||
current_time = Time.now.utc |
||||
|
||||
poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_long')) if poll.expires_at.nil? || poll.expires_at - current_time > MAX_EXPIRATION |
||||
poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_short')) if poll.expires_at.present? && (poll.expires_at - current_time).ceil < MIN_EXPIRATION |
||||
end |
||||
end |
||||
@ -1,19 +1,13 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class PollValidator < ActiveModel::Validator |
||||
class PollOptionsValidator < ActiveModel::Validator |
||||
MAX_OPTIONS = 4 |
||||
MAX_OPTION_CHARS = 50 |
||||
MAX_EXPIRATION = 1.month.freeze |
||||
MIN_EXPIRATION = 5.minutes.freeze |
||||
|
||||
def validate(poll) |
||||
current_time = Time.now.utc |
||||
|
||||
poll.errors.add(:options, I18n.t('polls.errors.too_few_options')) unless poll.options.size > 1 |
||||
poll.errors.add(:options, I18n.t('polls.errors.too_many_options', max: MAX_OPTIONS)) if poll.options.size > MAX_OPTIONS |
||||
poll.errors.add(:options, I18n.t('polls.errors.over_character_limit', max: MAX_OPTION_CHARS)) if poll.options.any? { |option| option.mb_chars.grapheme_length > MAX_OPTION_CHARS } |
||||
poll.errors.add(:options, I18n.t('polls.errors.duplicate_options')) unless poll.options.uniq.size == poll.options.size |
||||
poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_long')) if poll.expires_at.nil? || poll.expires_at - current_time > MAX_EXPIRATION |
||||
poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_short')) if poll.expires_at.present? && (poll.expires_at - current_time).ceil < MIN_EXPIRATION |
||||
end |
||||
end |
||||
@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
require 'rails_helper' |
||||
|
||||
RSpec.describe PollOptionsValidator do |
||||
describe '#validate' do |
||||
before do |
||||
validator.validate(poll) |
||||
end |
||||
|
||||
let(:validator) { described_class.new } |
||||
let(:poll) { instance_double(Poll, options: options, expires_at: expires_at, errors: errors) } |
||||
let(:errors) { instance_double(ActiveModel::Errors, add: nil) } |
||||
let(:options) { %w(foo bar) } |
||||
let(:expires_at) { 1.day.from_now } |
||||
|
||||
it 'has no errors' do |
||||
expect(errors).to_not have_received(:add) |
||||
end |
||||
|
||||
context 'when the poll has duplicate options' do |
||||
let(:options) { %w(foo foo) } |
||||
|
||||
it 'adds errors' do |
||||
expect(errors).to have_received(:add) |
||||
end |
||||
end |
||||
|
||||
context 'when the poll has no options' do |
||||
let(:options) { [] } |
||||
|
||||
it 'adds errors' do |
||||
expect(errors).to have_received(:add) |
||||
end |
||||
end |
||||
|
||||
context 'when the poll has too many options' do |
||||
let(:options) { Array.new(described_class::MAX_OPTIONS + 1) { |i| "option #{i}" } } |
||||
|
||||
it 'adds errors' do |
||||
expect(errors).to have_received(:add) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
Loading…
Reference in new issue