1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
require_relative '../tests/bundle'
require_relative '../tests/command_runner'
require_relative '../tests/database'
require_relative '../tests/filesystem'
require_relative 'helpers/rails_versions'
require_relative 'helpers/ruby_versions'
require 'yaml'
module UnitTests
class RailsApplication
def initialize
@fs = Tests::Filesystem.new
@bundle = Tests::Bundle.new
@database = Tests::Database.instance
end
def create
fs.clean
generate
fs.within_project do
update_gems
end
end
def load
load_environment
add_active_storage_migration
add_action_text_migration
run_migrations
end
def gemfile_path
fs.find('Gemfile')
end
def environment_file_path
fs.find_in_project('config/environment')
end
def temp_views_directory
fs.find_in_project('tmp/views')
end
def create_temp_view(path, contents)
full_path = temp_view_path_for(path)
full_path.dirname.mkpath
full_path.open('w') { |f| f.write(contents) }
end
def delete_temp_views
if temp_views_directory.exist?
temp_views_directory.rmtree
end
end
def draw_routes(&block)
Rails.application.routes.draw(&block)
Rails.application.routes
end
protected
attr_reader :fs, :shell, :bundle, :database
private
def migrations_directory
fs.find_in_project('db/migrate')
end
def temp_view_path_for(path)
temp_views_directory.join(path)
end
def generate
rails_new
fix_available_locales_warning
write_database_configuration
write_activerecord_model_with_default_connection
write_activerecord_model_with_different_connection
add_initializer_for_time_zone_aware_types
end
def rails_new
run_command!(*rails_new_command)
end
def rails_new_command
"bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap"
end
def fix_available_locales_warning
# See here for more on this:
# https://stackoverflow.com/questions/20361428/rails-i18n-validation-deprecation-warning
fs.transform('config/application.rb') do |lines|
lines.insert(-3, <<-EOT)
if I18n.respond_to?(:enforce_available_locales=)
I18n.enforce_available_locales = false
end
EOT
end
end
def write_database_configuration
fs.open('config/database.yml', 'w') do |file|
YAML.dump(database.config.load_file, file)
end
end
def write_activerecord_model_with_different_connection
# To simulate multi-db connections, we create a new "base model" which
# connects to a different database (in this case -
# shoulda-matchers-test_production).
# Any models which inherit from this class, or uses this model's
# connection will be routed to this database.
path = 'app/models/production_record.rb'
fs.write(path, <<-TEXT)
class ProductionRecord < ActiveRecord::Base
self.abstract_class = true
establish_connection :production
end
TEXT
end
def write_activerecord_model_with_default_connection
# Alongside ProductionRecord created above, we also create a dummy
# DevelopmentRecord which connects to the default database (in this case -
# shoulda-matchers-test_development, for symmetry's sake. This allows us
# to be a little more explicit when writing tests, for example:
# expect(with_index_on(:age1, parent_class: DevelopmentRecord)).to have_db_index(:age1)
# expect(with_index_on(:age2, parent_class: ProductionRecord)).to have_db_index(:age2)
path = 'app/models/development_record.rb'
fs.write(path, <<-TEXT)
class DevelopmentRecord < ActiveRecord::Base
self.abstract_class = true
end
TEXT
end
def add_action_text_migration
fs.within_project do
run_command! 'bundle exec rake action_text:install:migrations'
end
end
def add_active_storage_migration
fs.within_project do
run_command! 'bundle exec rake active_storage:install:migrations'
end
end
def add_initializer_for_time_zone_aware_types
path = 'config/initializers/configure_time_zone_aware_types.rb'
fs.write(path, <<-TEXT)
Rails.application.configure do
config.active_record.time_zone_aware_types = [:datetime, :time]
end
TEXT
end
def load_environment
require environment_file_path
end
def run_migrations
fs.within_project do
run_command! 'bundle exec rake db:drop:all'
run_command! 'bundle exec rake db:create RAILS_ENV=test'
run_command! 'bundle exec rake db:create RAILS_ENV=development'
run_command! 'bundle exec rake db:create RAILS_ENV=production'
end
fs.within_project do
run_command! 'bundle exec rake db:migrate'
end
end
def update_gems
bundle.updating do
bundle.remove_gem 'turn'
bundle.remove_gem 'coffee-rails'
bundle.remove_gem 'uglifier'
bundle.remove_gem 'debugger'
bundle.remove_gem 'byebug'
bundle.remove_gem 'web-console'
end
end
def run_command!(*args)
Tests::CommandRunner.run!(*args)
end
def rails_version
bundle.version_of('rails')
end
end
end
|