# frozen_string_literal: true
require "isolation/abstract_unit"
module ApplicationTests
module RakeTests
class RakeDbsTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
def setup
build_app
FileUtils.rm_rf("#{app_path}/config/environments")
end
def teardown
teardown_app
end
def database_url_db_name
"db/database_url_db.sqlite3"
end
def set_database_url
ENV["DATABASE_URL"] = "sqlite3:#{database_url_db_name}"
# ensure it's using the DATABASE_URL
FileUtils.rm_rf("#{app_path}/config/database.yml")
end
def db_create_and_drop(expected_database)
Dir.chdir(app_path) do
output = `bin/rails db:create`
assert_match(/Created database/, output)
assert File.exist?(expected_database)
assert_equal expected_database, ActiveRecord::Base.connection_config[:database]
output = `bin/rails db:drop`
assert_match(/Dropped database/, output)
assert !File.exist?(expected_database)
end
end
test "db:create and db:drop without database url" do
require "#{app_path}/config/environment"
db_create_and_drop ActiveRecord::Base.configurations[Rails.env]["database"]
end
test "db:create and db:drop with database url" do
require "#{app_path}/config/environment"
set_database_url
db_create_and_drop database_url_db_name
end
def with_database_existing
Dir.chdir(app_path) do
set_database_url
`bin/rails db:create`
yield
`bin/rails db:drop`
end
end
test "db:create failure because database exists" do
with_database_existing do
output = `bin/rails db:create 2>&1`
assert_match(/already exists/, output)
assert_equal 0, $?.exitstatus
end
end
def with_bad_permissions
Dir.chdir(app_path) do
set_database_url
FileUtils.chmod("-w", "db")
yield
FileUtils.chmod("+w", "db")
end
end
test "db:create failure because bad permissions" do
with_bad_permissions do
output = `bin/rails db:create 2>&1`
assert_match(/Couldn't create database/, output)
assert_equal 1, $?.exitstatus
end
end
test "db:drop failure because database does not exist" do
Dir.chdir(app_path) do
output = `bin/rails db:drop:_unsafe --trace 2>&1`
assert_match(/does not exist/, output)
assert_equal 0, $?.exitstatus
end
end
test "db:drop failure because bad permissions" do
with_database_existing do
with_bad_permissions do
output = `bin/rails db:drop 2>&1`
assert_match(/Couldn't drop/, output)
assert_equal 1, $?.exitstatus
end
end
end
def db_migrate_and_status(expected_database)
Dir.chdir(app_path) do
`bin/rails generate model book title:string;
bin/rails db:migrate`
output = `bin/rails db:migrate:status`
assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output)
assert_match(/up\s+\d{14}\s+Create books/, output)
end
end
test "db:migrate and db:migrate:status without database_url" do
require "#{app_path}/config/environment"
db_migrate_and_status ActiveRecord::Base.configurations[Rails.env]["database"]
end
test "db:migrate and db:migrate:status with database_url" do
require "#{app_path}/config/environment"
set_database_url
db_migrate_and_status database_url_db_name
end
def db_schema_dump
Dir.chdir(app_path) do
`bin/rails generate model book title:string;
bin/rails db:migrate db:schema:dump`
schema_dump = File.read("db/schema.rb")
assert_match(/create_table \"books\"/, schema_dump)
end
end
test "db:schema:dump without database_url" do
db_schema_dump
end
test "db:schema:dump with database_url" do
set_database_url
db_schema_dump
end
def db_fixtures_load(expected_database)
Dir.chdir(app_path) do
`bin/rails generate model book title:string;
bin/rails db:migrate db:fixtures:load`
assert_match expected_database, ActiveRecord::Base.connection_config[:database]
require "#{app_path}/app/models/book"
assert_equal 2, Book.count
end
end
test "db:fixtures:load without database_url" do
require "#{app_path}/config/environment"
db_fixtures_load ActiveRecord::Base.configurations[Rails.env]["database"]
end
test "db:fixtures:load with database_url" do
require "#{app_path}/config/environment"
set_database_url
db_fixtures_load database_url_db_name
end
test "db:fixtures:load with namespaced fixture" do
require "#{app_path}/config/environment"
Dir.chdir(app_path) do
`bin/rails generate model admin::book title:string;
bin/rails db:migrate db:fixtures:load`
require "#{app_path}/app/models/admin/book"
assert_equal 2, Admin::Book.count
end
end
def db_structure_dump_and_load(expected_database)
Dir.chdir(app_path) do
`bin/rails generate model book title:string;
bin/rails db:migrate db:structure:dump`
structure_dump = File.read("db/structure.sql")
assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, structure_dump)
`bin/rails environment db:drop db:structure:load`
assert_match expected_database, ActiveRecord::Base.connection_config[:database]
require "#{app_path}/app/models/book"
#if structure is not loaded correctly, exception would be raised
assert_equal 0, Book.count
end
end
test "db:structure:dump and db:structure:load without database_url" do
require "#{app_path}/config/environment"
db_structure_dump_and_load ActiveRecord::Base.configurations[Rails.env]["database"]
end
test "db:structure:dump and db:structure:load with database_url" do
require "#{app_path}/config/environment"
set_database_url
db_structure_dump_and_load database_url_db_name
end
test "db:structure:dump does not dump schema information when no migrations are used" do
Dir.chdir(app_path) do
# create table without migrations
`bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
stderr_output = capture(:stderr) { `bin/rails db:structure:dump` }
assert_empty stderr_output
structure_dump = File.read("db/structure.sql")
assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump)
end
end
test "db:schema:load and db:structure:load do not purge the existing database" do
Dir.chdir(app_path) do
`bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
app_file "db/schema.rb", <<-RUBY
ActiveRecord::Schema.define(version: 20140423102712) do
create_table(:comments) {}
end
RUBY
list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip }
assert_equal '["posts"]', list_tables[]
`bin/rails db:schema:load`
assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[]
app_file "db/structure.sql", <<-SQL
CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
SQL
`bin/rails db:structure:load`
assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
end
end
test "db:schema:load with inflections" do
Dir.chdir(app_path) do
app_file "config/initializers/inflection.rb", <<-RUBY
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'goose', 'geese'
end
RUBY
app_file "config/initializers/primary_key_table_name.rb", <<-RUBY
ActiveRecord::Base.primary_key_prefix_type = :table_name
RUBY
app_file "db/schema.rb", <<-RUBY
ActiveRecord::Schema.define(version: 20140423102712) do
create_table("goose".pluralize) do |t|
t.string :name
end
end
RUBY
`bin/rails db:schema:load`
tables = `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip
assert_match(/"geese"/, tables)
columns = `bin/rails runner 'p ActiveRecord::Base.connection.columns("geese").map(&:name)'`.strip
assert_equal columns, '["gooseid", "name"]'
end
end
test "db:schema:load fails if schema.rb doesn't exist yet" do
Dir.chdir(app_path) do
stderr_output = capture(:stderr) { `bin/rails db:schema:load` }
assert_match(/Run `rails db:migrate` to create it/, stderr_output)
end
end
def db_test_load_structure
Dir.chdir(app_path) do
`bin/rails generate model book title:string;
bin/rails db:migrate db:structure:dump db:test:load_structure`
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
ActiveRecord::Base.establish_connection :test
require "#{app_path}/app/models/book"
#if structure is not loaded correctly, exception would be raised
assert_equal 0, Book.count
assert_match ActiveRecord::Base.configurations["test"]["database"],
ActiveRecord::Base.connection_config[:database]
end
end
test "db:test:load_structure without database_url" do
require "#{app_path}/config/environment"
db_test_load_structure
end
test "db:setup loads schema and seeds database" do
begin
@old_rails_env = ENV["RAILS_ENV"]
@old_rack_env = ENV["RACK_ENV"]
ENV.delete "RAILS_ENV"
ENV.delete "RACK_ENV"
app_file "db/schema.rb", <<-RUBY
ActiveRecord::Schema.define(version: "1") do
create_table :users do |t|
t.string :name
end
end
RUBY
app_file "db/seeds.rb", <<-RUBY
puts ActiveRecord::Base.connection_config[:database]
RUBY
Dir.chdir(app_path) do
database_path = `bin/rails db:setup`
assert_equal "development.sqlite3", File.basename(database_path.strip)
end
ensure
ENV["RAILS_ENV"] = @old_rails_env
ENV["RACK_ENV"] = @old_rack_env
end
end
end
end
end