A simple solution to an annoying problem!
# Rakefile task "assets:precompile" => "db:migrate" if ENV['MIGRATE_ON_PRECOMPILE'] # run to enable heroku config:set MIGRATE_ON_PRECOMPILE=1
A simple solution to an annoying problem!
# Rakefile task "assets:precompile" => "db:migrate" if ENV['MIGRATE_ON_PRECOMPILE'] # run to enable heroku config:set MIGRATE_ON_PRECOMPILE=1
We don’t want to compile assets during test runs, since that is slow, but we also don’t want the asset pipeline to fail because assets are missing.
This will not work if you plan on doing javascript integration tests, but everything else should work fine.
Rails 5.1 added a flag for this which prints deprecations and will be removed in rails 5.2 so that is not a elegant solution either.
config.assets.unknown_asset_fallback = true
So we are now using this fix to fake assets being available!:
# config/environments/test.rb # make our tests fast by avoiding asset compilation # but do not raise when assets are not compiled either Rails.application.config.assets.compile = false Sprockets::Rails::Helper.prepend(Module.new do def resolve_asset_path(path, *) super || path end end)
Rails 4 by default wants to upgrade all cookies, which makes rails 3 unable to read them. But we want that to work since we let rails 3 and 4 run in parallel to test performance (which is terrible on rails 4 … )
# While we run servers with rails 3 and rails 4 we don't want to encrypt our cookie # once everything is on rails 4 we can by using the upgrade signed to encrypted strategy # tested via test/integration/rails_compatibility_test.rb if RAILS4 ActionDispatch::Cookies::ChainedCookieJars.class_eval do def signed_or_encrypted signed end end # do not update ... compare to action_dispatch/middleware/cookies.rb:184 ActionDispatch::Cookies::UpgradeLegacySignedCookieJar.class_eval do def initialize(*args) super @verifier = @legacy_verifier end def verify_and_upgrade_legacy_signed_message(name, signed_message) deserialize(name, @legacy_verifier.verify(signed_message)) rescue ActiveSupport::MessageVerifier::InvalidSignature nil end end end
# application_helper.rb def render_nested_errors(object, seen=Set.new) return "" if seen.include?(object) seen << object return "" if object.errors.empty? content_tag :ul do lis = object.errors.map do |attribute, message| content_tag(:li) do content = "".html_safe content << object.errors.full_message(attribute, message) values = (object.respond_to?(attribute) ? Array.wrap(object.send(attribute)) : []) if values.first.is_a?(ActiveRecord::Base) values.each do |value| content << render_nested_errors(value, seen) end end content end end safe_join lis end end # application_helper_test.rb describe "#render_nested_errors" do # simulate what erb will do so we can see html_safe issues def render ERB::Util.html_escape(render_nested_errors(stage)) end let(:stage) { stages(:test_staging) } it "renders nothing for valid" do render.must_equal "" end it "renders simple errors" do stage.errors.add(:base, "Kaboom") render.must_equal "<ul><li>Kaboom</li></ul>" end it "renders nested errors" do stage.errors.add(:deploy_groups, "Invalid") # happens on save normally .. not a helpful message for our users stage.errors.add(:base, "BASE") # other error to make sure nesting is correct stage.deploy_groups.to_a.first.errors.add(:base, "Kaboom") render.must_equal "<ul><li>Deploy groups Invalid<ul><li>Kaboom</li></ul></li><li>BASE</li></ul>" end it "does not loop" do stage.errors.add(:project, "Invalid") stage.project.stubs(stages: [stage]) stage.project.errors.add(:stages, "Invalid") render.must_equal "<ul><li>Project Invalid<ul><li>Stages Invalid</li></ul></li></ul>" end it "cannot inject html" do stage.errors.add(:deploy_groups, "<foo>") stage.errors.add(:base, "<bar>") stage.deploy_groups.to_a.first.errors.add(:base, "<baz>") render.must_equal "<ul><li>Deploy groups <foo><ul><li><baz></li></ul></li><li><bar></li></ul>" end end
Not using a browser is a lot faster, so let’s try to avoid it if possible.
click_ujs_link "Delete" click_ujs_link "Post" ... def click_ujs_link(name) link = find(:link, name, {}) visit_with_method link['data-method'], link['href'] end def visit_with_method(method, url) page.driver.send method, url visit page.driver.response.location end