diff --git a/.rubocop.yml b/.rubocop.yml index e67f01d..b02a7d9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -43,11 +43,6 @@ Metrics/AbcSize: - db/migrate/**/* Max: 20 -# TODO: remove this cop exception after refactor -Metrics/ClassLength: - Exclude: - - test/**/* - Metrics/LineLength: Max: 110 Exclude: diff --git a/Guardfile b/Guardfile index 7c89660..b58c512 100644 --- a/Guardfile +++ b/Guardfile @@ -15,11 +15,16 @@ # # and, you'll have to watch "config/Guardfile" instead of "Guardfile" -guard :minitest, spring: true do # , all_after_pass: true +guard :minitest, spring: "bin/rails test", all_after_pass: true, all_on_start: false do watch(%r{^test/test_helper\.rb$}) { 'test' } watch(%r{^test/(.*)\/?(.*)_test\.rb$}) - watch(%r{^app/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" } - watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/lib/#{m[1]}#{m[2]}_test.rb" } + + # run tests when touching files matching: /app/**/*.rb + watch(%r{^app/(.*/)?([^/]+)\.rb$}) { |m| ["test/#{m[1]}#{m[2]}_test.rb", "test/#{m[1]}#{m[2]}"] } + + # run tests when touching files matching: /lib/**/*.rb + watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| ["test/lib/#{m[1]}#{m[2]}_test.rb", "test/lib/#{m[1]}#{m[2]}"] } + end guard 'livereload' do diff --git a/bower.json b/bower.json index 4022d5f..f05a02e 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,8 @@ "jquery": "1.9.1", "jquery-validate": "", "tota11y": "", - "modernizr-lite": "*" + "modernizr-lite": "*", + "html5shiv": "^3.7.3" }, "ignore": [ "**/.*", @@ -18,6 +19,5 @@ "tests" ], "devDependencies": { - "html5shiv": "^3.7.3" } } diff --git a/test/test_helper.rb b/test/test_helper.rb index 5087494..b3eba45 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,6 +4,8 @@ require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' require "minitest/autorun" require 'minitest/reporters' +Dir[Rails.root.join("test/test_helpers/**/*.rb")].each { |f| require f } + Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(color: true)] class ActiveSupport::TestCase diff --git a/test/test_helpers/README.txt b/test/test_helpers/README.txt new file mode 100644 index 0000000..037f183 --- /dev/null +++ b/test/test_helpers/README.txt @@ -0,0 +1,25 @@ +Use this folder to store mocks, stubs, etc to make isolated testing possible. + +Some definitions borrowed from: +http://martinfowler.com/articles/mocksArentStubs.html + +* Dummy + objects are passed around but never actually used. + Usually they are just used to fill parameter lists. + +* Fake + objects actually have working implementations, but usually + take some shortcut which makes them not suitable for + production (an in memory database is a good example). + +* Stubs + provide canned answers to calls made during the test, + usually not responding at all to anything outside what's + programmed in for the test. Stubs may also record information + about calls, such as an email gateway stub that remembers the + messages it 'sent', or maybe only how many messages it 'sent'. + +* Mocks + objects pre-programmed with expectations which form a + specification of the calls they are expected to receive. + diff --git a/test/test_helpers/answer_validatable.rb b/test/test_helpers/answer_validatable.rb new file mode 100644 index 0000000..0b0e71e --- /dev/null +++ b/test/test_helpers/answer_validatable.rb @@ -0,0 +1,18 @@ +class AnswerValidatable + include ActiveModel::Validations + + attr_accessor :answer + attr_accessor :question + + validates :answer, answer_format: true + + MockQuestion = Struct.new(:input_type) + + def initialize input_type + @input_type = input_type + end + + def question + MockQuestion.new(@input_type) + end +end diff --git a/test/validators/answer_format_validator/checkbox_test.rb b/test/validators/answer_format_validator/checkbox_test.rb new file mode 100644 index 0000000..8899919 --- /dev/null +++ b/test/validators/answer_format_validator/checkbox_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' + +class AnswerFormatValidatorTest < ActiveSupport::TestCase + test "checkbox should PASS with populated array" do + obj = AnswerValidatable.new('checkbox') + obj.answer = ["", "", "valid answer"] + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "checkbox should FAIL with nil" do + obj = AnswerValidatable.new('checkbox') + obj.answer = nil + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "checkbox should FAIL with empty string" do + obj = AnswerValidatable.new('checkbox') + obj.answer = " " + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "checkbox should FAIL with array of empty strings" do + obj = AnswerValidatable.new('checkbox') + obj.answer = ["", "", " "] + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end +end diff --git a/test/validators/answer_format_validator/live_code_test.rb b/test/validators/answer_format_validator/live_code_test.rb new file mode 100644 index 0000000..9f6de95 --- /dev/null +++ b/test/validators/answer_format_validator/live_code_test.rb @@ -0,0 +1,51 @@ +require 'test_helper' + +class AnswerFormatValidatorTest < ActiveSupport::TestCase + test "live_code should PASS with populated hash" do + obj = AnswerValidatable.new('live_code') + obj.answer = { html: 'this is html', css: '', js: '', text: 'some reasons' } + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "live_code should PASS with finish later" do + obj = AnswerValidatable.new('live_code') + obj.answer = { later: "true" } + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "live_code should FAIL with nil" do + obj = AnswerValidatable.new('live_code') + obj.answer = nil + + refute obj.valid? + assert_match(/write.*code/, obj.errors.messages[:answer][0]) + end + + test "live_code should FAIL without checking finish later" do + obj = AnswerValidatable.new('live_code') + obj.answer = { later: "" } + + refute obj.valid? + assert_match(/come back/, obj.errors.messages[:answer][0]) + end + + test "live_code should FAIL without values" do + obj = AnswerValidatable.new('live_code') + obj.answer = { text: "", html: "", css: "", js: "" } + + refute obj.valid? + assert_match(/write.*code/, obj.errors.messages[:answer][0]) + end + + test "live_code should PASS with text only" do + obj = AnswerValidatable.new('live_code') + obj.answer = { html: "", css: "", js: "", text: "reasons" } + + assert obj.valid? + assert obj.errors.messages.empty? + end +end diff --git a/test/validators/answer_format_validator/radio_test.rb b/test/validators/answer_format_validator/radio_test.rb new file mode 100644 index 0000000..6629d87 --- /dev/null +++ b/test/validators/answer_format_validator/radio_test.rb @@ -0,0 +1,27 @@ +require 'test_helper' + +class AnswerFormatValidatorTest < ActiveSupport::TestCase + test "radio should pass with string" do + obj = AnswerValidatable.new('radio') + obj.answer = 'option-1' + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "radio should FAIL with nil" do + obj = AnswerValidatable.new('radio') + obj.answer = nil + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "radio should FAIL with empty string" do + obj = AnswerValidatable.new('radio') + obj.answer = '' + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end +end diff --git a/test/validators/answer_format_validator/text_test.rb b/test/validators/answer_format_validator/text_test.rb new file mode 100644 index 0000000..b0a8396 --- /dev/null +++ b/test/validators/answer_format_validator/text_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' + +class AnswerFormatValidatorTest < ActiveSupport::TestCase + test "text should PASS with string" do + obj = AnswerValidatable.new('text') + obj.answer = "this is a valid answer" + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "text should FAIL with nil" do + obj = AnswerValidatable.new('text') + obj.answer = nil + + refute obj.valid? + assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) + end + + test "text should FAIL with empry string" do + obj = AnswerValidatable.new('text') + obj.answer = " " + + refute obj.valid? + assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) + end + + test "text should FAIL with more than 1000 charactures" do + obj = AnswerValidatable.new('text') + obj.answer = SecureRandom.urlsafe_base64(1001) + + refute obj.valid? + assert_match(/char.*limit.*1000.$/, obj.errors.messages[:answer][0]) + end +end diff --git a/test/validators/answer_format_validator_test.rb b/test/validators/answer_format_validator_test.rb deleted file mode 100644 index 263941c..0000000 --- a/test/validators/answer_format_validator_test.rb +++ /dev/null @@ -1,165 +0,0 @@ -require 'test_helper' - -class AnswerValidatable - include ActiveModel::Validations - - attr_accessor :answer - attr_accessor :question - - validates :answer, answer_format: true - - MockQuestion = Struct.new(:input_type) - - def initialize input_type - @input_type = input_type - end - - def question - MockQuestion.new(@input_type) - end -end - -class AnswerFormatValidatorTest < ActiveSupport::TestCase - # input_type RADIO - - test "radio should pass with string" do - obj = AnswerValidatable.new('radio') - obj.answer = 'option-1' - - assert obj.valid? - assert obj.errors.messages.empty? - end - - test "radio should FAIL with nil" do - obj = AnswerValidatable.new('radio') - obj.answer = nil - - refute obj.valid? - assert_match(/select.*answer/, obj.errors.messages[:answer][0]) - end - - test "radio should FAIL with empty string" do - obj = AnswerValidatable.new('radio') - obj.answer = '' - - refute obj.valid? - assert_match(/select.*answer/, obj.errors.messages[:answer][0]) - end - - # input_type TEXT - - test "text should PASS with string" do - obj = AnswerValidatable.new('text') - obj.answer = "this is a valid answer" - - assert obj.valid? - assert obj.errors.messages.empty? - end - - test "text should FAIL with nil" do - obj = AnswerValidatable.new('text') - obj.answer = nil - - refute obj.valid? - assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) - end - - test "text should FAIL with empry string" do - obj = AnswerValidatable.new('text') - obj.answer = " " - - refute obj.valid? - assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) - end - - test "text should FAIL with more than 1000 charactures" do - obj = AnswerValidatable.new('text') - obj.answer = SecureRandom.urlsafe_base64(1001) - - refute obj.valid? - assert_match(/char.*limit.*1000.$/, obj.errors.messages[:answer][0]) - end - - # input_type CHECK BOX - - test "checkbox should PASS with populated array" do - obj = AnswerValidatable.new('checkbox') - obj.answer = ["", "", "valid answer"] - - assert obj.valid? - assert obj.errors.messages.empty? - end - - test "checkbox should FAIL with nil" do - obj = AnswerValidatable.new('checkbox') - obj.answer = nil - - refute obj.valid? - assert_match(/select.*answer/, obj.errors.messages[:answer][0]) - end - - test "checkbox should FAIL with empty string" do - obj = AnswerValidatable.new('checkbox') - obj.answer = " " - - refute obj.valid? - assert_match(/select.*answer/, obj.errors.messages[:answer][0]) - end - - test "checkbox should FAIL with array of empty strings" do - obj = AnswerValidatable.new('checkbox') - obj.answer = ["", "", " "] - - refute obj.valid? - assert_match(/select.*answer/, obj.errors.messages[:answer][0]) - end - - # input_type LIVE CODER - test "live_code should PASS with populated hash" do - obj = AnswerValidatable.new('live_code') - obj.answer = { html: 'this is html', css: '', js: '', text: 'some reasons' } - - assert obj.valid? - assert obj.errors.messages.empty? - end - - test "live_code should PASS with finish later" do - obj = AnswerValidatable.new('live_code') - obj.answer = { later: "true" } - - assert obj.valid? - assert obj.errors.messages.empty? - end - - test "live_code should FAIL with nil" do - obj = AnswerValidatable.new('live_code') - obj.answer = nil - - refute obj.valid? - assert_match(/write.*code/, obj.errors.messages[:answer][0]) - end - - test "live_code should FAIL without checking finish later" do - obj = AnswerValidatable.new('live_code') - obj.answer = { later: "" } - - refute obj.valid? - assert_match(/come back/, obj.errors.messages[:answer][0]) - end - - test "live_code should FAIL without values" do - obj = AnswerValidatable.new('live_code') - obj.answer = { text: "", html: "", css: "", js: "" } - - refute obj.valid? - assert_match(/write.*code/, obj.errors.messages[:answer][0]) - end - - test "live_code should PASS with text only" do - obj = AnswerValidatable.new('live_code') - obj.answer = { html: "", css: "", js: "", text: "reasons" } - - assert obj.valid? - assert obj.errors.messages.empty? - end -end