mirror of
https://github.com/thoughtbot/shoulda-matchers.git
synced 2022-11-09 12:01:38 -05:00
Add support for Postgres
When running tests, you can now switch between running them against a SQLite or PostgreSQL database. This is accomplished by modifying the unit and acceptance tests so that when they generate and load the test Rails application, database.yml is replaced with content that will configure the database appropriately.
This commit is contained in:
parent
942a600e07
commit
72f60fae94
30 changed files with 288 additions and 51 deletions
|
@ -6,6 +6,10 @@ branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
env:
|
||||||
|
- DATABASE_ADAPTER=sqlite3
|
||||||
|
- DATABASE_ADAPTER=postgresql
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
- 2.0.0
|
- 2.0.0
|
||||||
- 2.1.4
|
- 2.1.4
|
||||||
|
|
|
@ -4,6 +4,7 @@ shared_dependencies = proc do
|
||||||
gem 'rspec-rails', '>= 3.2.0', '< 4'
|
gem 'rspec-rails', '>= 3.2.0', '< 4'
|
||||||
gem 'shoulda-context', '~> 1.2.0'
|
gem 'shoulda-context', '~> 1.2.0'
|
||||||
gem 'sqlite3', platform: :ruby
|
gem 'sqlite3', platform: :ruby
|
||||||
|
gem 'pg', platform: :ruby
|
||||||
gem 'activerecord-jdbc-adapter', platform: :jruby
|
gem 'activerecord-jdbc-adapter', platform: :jruby
|
||||||
gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
|
gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
|
||||||
gem 'jdbc-sqlite3', platform: :jruby
|
gem 'jdbc-sqlite3', platform: :jruby
|
||||||
|
|
1
Rakefile
1
Rakefile
|
@ -3,6 +3,7 @@ require 'bundler/gem_tasks'
|
||||||
require 'rspec/core/rake_task'
|
require 'rspec/core/rake_task'
|
||||||
require 'appraisal'
|
require 'appraisal'
|
||||||
require_relative 'tasks/documentation'
|
require_relative 'tasks/documentation'
|
||||||
|
require_relative 'spec/support/tests/database'
|
||||||
|
|
||||||
RSpec::Core::RakeTask.new('spec:unit') do |t|
|
RSpec::Core::RakeTask.new('spec:unit') do |t|
|
||||||
t.ruby_opts = '-w -r ./spec/report_warnings'
|
t.ruby_opts = '-w -r ./spec/report_warnings'
|
||||||
|
|
|
@ -15,6 +15,7 @@ gem "watchr"
|
||||||
gem "rspec-rails", ">= 3.2.0", "< 4"
|
gem "rspec-rails", ">= 3.2.0", "< 4"
|
||||||
gem "shoulda-context", "~> 1.2.0"
|
gem "shoulda-context", "~> 1.2.0"
|
||||||
gem "sqlite3", :platform => :ruby
|
gem "sqlite3", :platform => :ruby
|
||||||
|
gem "pg", :platform => :ruby
|
||||||
gem "activerecord-jdbc-adapter", :platform => :jruby
|
gem "activerecord-jdbc-adapter", :platform => :jruby
|
||||||
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
||||||
gem "jdbc-sqlite3", :platform => :jruby
|
gem "jdbc-sqlite3", :platform => :jruby
|
||||||
|
|
|
@ -70,6 +70,7 @@ GEM
|
||||||
minitest (>= 2.12, < 5.0)
|
minitest (>= 2.12, < 5.0)
|
||||||
powerbar
|
powerbar
|
||||||
multi_json (1.10.1)
|
multi_json (1.10.1)
|
||||||
|
pg (0.18.1)
|
||||||
polyglot (0.3.5)
|
polyglot (0.3.5)
|
||||||
posix-spawn (0.3.9)
|
posix-spawn (0.3.9)
|
||||||
powerbar (1.0.11)
|
powerbar (1.0.11)
|
||||||
|
@ -181,6 +182,7 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jruby-openssl
|
jruby-openssl
|
||||||
minitest-reporters
|
minitest-reporters
|
||||||
|
pg
|
||||||
protected_attributes
|
protected_attributes
|
||||||
pry-nav
|
pry-nav
|
||||||
pygments.rb
|
pygments.rb
|
||||||
|
|
|
@ -15,6 +15,7 @@ gem "watchr"
|
||||||
gem "rspec-rails", ">= 3.2.0", "< 4"
|
gem "rspec-rails", ">= 3.2.0", "< 4"
|
||||||
gem "shoulda-context", "~> 1.2.0"
|
gem "shoulda-context", "~> 1.2.0"
|
||||||
gem "sqlite3", :platform => :ruby
|
gem "sqlite3", :platform => :ruby
|
||||||
|
gem "pg", :platform => :ruby
|
||||||
gem "activerecord-jdbc-adapter", :platform => :jruby
|
gem "activerecord-jdbc-adapter", :platform => :jruby
|
||||||
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
||||||
gem "jdbc-sqlite3", :platform => :jruby
|
gem "jdbc-sqlite3", :platform => :jruby
|
||||||
|
|
|
@ -70,6 +70,7 @@ GEM
|
||||||
minitest (>= 2.12, < 5.0)
|
minitest (>= 2.12, < 5.0)
|
||||||
powerbar
|
powerbar
|
||||||
multi_json (1.10.1)
|
multi_json (1.10.1)
|
||||||
|
pg (0.18.1)
|
||||||
polyglot (0.3.5)
|
polyglot (0.3.5)
|
||||||
posix-spawn (0.3.9)
|
posix-spawn (0.3.9)
|
||||||
powerbar (1.0.11)
|
powerbar (1.0.11)
|
||||||
|
@ -181,6 +182,7 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jruby-openssl
|
jruby-openssl
|
||||||
minitest-reporters
|
minitest-reporters
|
||||||
|
pg
|
||||||
protected_attributes
|
protected_attributes
|
||||||
pry-nav
|
pry-nav
|
||||||
pygments.rb
|
pygments.rb
|
||||||
|
|
|
@ -15,6 +15,7 @@ gem "watchr"
|
||||||
gem "rspec-rails", ">= 3.2.0", "< 4"
|
gem "rspec-rails", ">= 3.2.0", "< 4"
|
||||||
gem "shoulda-context", "~> 1.2.0"
|
gem "shoulda-context", "~> 1.2.0"
|
||||||
gem "sqlite3", :platform => :ruby
|
gem "sqlite3", :platform => :ruby
|
||||||
|
gem "pg", :platform => :ruby
|
||||||
gem "activerecord-jdbc-adapter", :platform => :jruby
|
gem "activerecord-jdbc-adapter", :platform => :jruby
|
||||||
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
||||||
gem "jdbc-sqlite3", :platform => :jruby
|
gem "jdbc-sqlite3", :platform => :jruby
|
||||||
|
|
|
@ -70,6 +70,7 @@ GEM
|
||||||
minitest (>= 5.0)
|
minitest (>= 5.0)
|
||||||
ruby-progressbar
|
ruby-progressbar
|
||||||
multi_json (1.10.1)
|
multi_json (1.10.1)
|
||||||
|
pg (0.18.1)
|
||||||
posix-spawn (0.3.9)
|
posix-spawn (0.3.9)
|
||||||
protected_attributes (1.0.8)
|
protected_attributes (1.0.8)
|
||||||
activemodel (>= 4.0.1, < 5.0)
|
activemodel (>= 4.0.1, < 5.0)
|
||||||
|
@ -178,6 +179,7 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jruby-openssl
|
jruby-openssl
|
||||||
minitest-reporters
|
minitest-reporters
|
||||||
|
pg
|
||||||
protected_attributes (~> 1.0.6)
|
protected_attributes (~> 1.0.6)
|
||||||
pry-nav
|
pry-nav
|
||||||
pygments.rb
|
pygments.rb
|
||||||
|
|
|
@ -15,6 +15,7 @@ gem "watchr"
|
||||||
gem "rspec-rails", ">= 3.2.0", "< 4"
|
gem "rspec-rails", ">= 3.2.0", "< 4"
|
||||||
gem "shoulda-context", "~> 1.2.0"
|
gem "shoulda-context", "~> 1.2.0"
|
||||||
gem "sqlite3", :platform => :ruby
|
gem "sqlite3", :platform => :ruby
|
||||||
|
gem "pg", :platform => :ruby
|
||||||
gem "activerecord-jdbc-adapter", :platform => :jruby
|
gem "activerecord-jdbc-adapter", :platform => :jruby
|
||||||
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
|
||||||
gem "jdbc-sqlite3", :platform => :jruby
|
gem "jdbc-sqlite3", :platform => :jruby
|
||||||
|
|
|
@ -87,6 +87,7 @@ GEM
|
||||||
multi_json (1.10.1)
|
multi_json (1.10.1)
|
||||||
nokogiri (1.6.6.2)
|
nokogiri (1.6.6.2)
|
||||||
mini_portile (~> 0.6.0)
|
mini_portile (~> 0.6.0)
|
||||||
|
pg (0.18.1)
|
||||||
posix-spawn (0.3.9)
|
posix-spawn (0.3.9)
|
||||||
protected_attributes (1.0.8)
|
protected_attributes (1.0.8)
|
||||||
activemodel (>= 4.0.1, < 5.0)
|
activemodel (>= 4.0.1, < 5.0)
|
||||||
|
@ -205,6 +206,7 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jruby-openssl
|
jruby-openssl
|
||||||
minitest-reporters
|
minitest-reporters
|
||||||
|
pg
|
||||||
protected_attributes (~> 1.0.6)
|
protected_attributes (~> 1.0.6)
|
||||||
pry-nav
|
pry-nav
|
||||||
pygments.rb
|
pygments.rb
|
||||||
|
|
|
@ -14,7 +14,7 @@ describe 'shoulda-matchers integrates with Rails' do
|
||||||
end
|
end
|
||||||
FILE
|
FILE
|
||||||
|
|
||||||
run_rake_tasks!('db:migrate', 'db:test:prepare')
|
run_rake_tasks! *%w(db:drop db:create db:migrate)
|
||||||
|
|
||||||
write_file 'app/models/user.rb', <<-FILE
|
write_file 'app/models/user.rb', <<-FILE
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
|
|
|
@ -5,6 +5,8 @@ Tests::CurrentBundle.instance.assert_appraisal!
|
||||||
#---
|
#---
|
||||||
|
|
||||||
require 'rspec/core'
|
require 'rspec/core'
|
||||||
|
require 'pry'
|
||||||
|
require 'pry-nav'
|
||||||
|
|
||||||
Dir[ File.join(File.expand_path('../support/acceptance/**/*.rb', __FILE__)) ].sort.each do |file|
|
Dir[ File.join(File.expand_path('../support/acceptance/**/*.rb', __FILE__)) ].sort.each do |file|
|
||||||
require file
|
require file
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require_relative '../../tests/filesystem'
|
|
||||||
require_relative '../../tests/bundle'
|
require_relative '../../tests/bundle'
|
||||||
|
require_relative '../../tests/database'
|
||||||
|
require_relative '../../tests/filesystem'
|
||||||
|
|
||||||
module AcceptanceTests
|
module AcceptanceTests
|
||||||
module BaseHelpers
|
module BaseHelpers
|
||||||
|
@ -10,5 +11,9 @@ module AcceptanceTests
|
||||||
def bundle
|
def bundle
|
||||||
@_bundle ||= Tests::Bundle.new
|
@_bundle ||= Tests::Bundle.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def database
|
||||||
|
@_database ||= Tests::Database.instance
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,11 +41,15 @@ module AcceptanceTests
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_rake_tasks(*tasks)
|
def run_rake_tasks(*tasks)
|
||||||
run_command_within_bundle('rake', *tasks)
|
options = tasks.last.is_a?(Hash) ? tasks.pop : {}
|
||||||
|
args = ['rake', *tasks, '--trace'] + [options]
|
||||||
|
run_command_within_bundle(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_rake_tasks!(*tasks)
|
def run_rake_tasks!(*tasks)
|
||||||
run_command_within_bundle!('rake', *tasks)
|
options = tasks.last.is_a?(Hash) ? tasks.pop : {}
|
||||||
|
args = ['rake', *tasks, '--trace'] + [options]
|
||||||
|
run_command_within_bundle!(*args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@ require_relative 'file_helpers'
|
||||||
require_relative 'gem_helpers'
|
require_relative 'gem_helpers'
|
||||||
require_relative 'minitest_helpers'
|
require_relative 'minitest_helpers'
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
module AcceptanceTests
|
module AcceptanceTests
|
||||||
module StepHelpers
|
module StepHelpers
|
||||||
include FileHelpers
|
include FileHelpers
|
||||||
|
@ -72,6 +74,11 @@ module AcceptanceTests
|
||||||
bundle.remove_gem 'debugger'
|
bundle.remove_gem 'debugger'
|
||||||
bundle.remove_gem 'byebug'
|
bundle.remove_gem 'byebug'
|
||||||
bundle.remove_gem 'web-console'
|
bundle.remove_gem 'web-console'
|
||||||
|
bundle.add_gem 'pg'
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.open('config/database.yml', 'w') do |file|
|
||||||
|
YAML.dump(database.config.to_hash, file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ Output:
|
||||||
end
|
end
|
||||||
|
|
||||||
def command
|
def command
|
||||||
([command_prefix] + args).flat_map do |word|
|
([command_prefix] + args).flatten.flat_map do |word|
|
||||||
Shellwords.split(word)
|
Shellwords.split(word)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
28
spec/support/tests/database.rb
Normal file
28
spec/support/tests/database.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
require_relative 'database_configuration'
|
||||||
|
|
||||||
|
module Tests
|
||||||
|
class Database
|
||||||
|
NAME = 'shoulda-matchers-test'
|
||||||
|
ADAPTER_NAME = ENV.fetch('DATABASE_ADAPTER', 'sqlite3').to_sym
|
||||||
|
|
||||||
|
include Singleton
|
||||||
|
|
||||||
|
attr_reader :config
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@config = Tests::DatabaseConfiguration.for(NAME, ADAPTER_NAME)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
config.database
|
||||||
|
end
|
||||||
|
|
||||||
|
def adapter_name
|
||||||
|
config.adapter
|
||||||
|
end
|
||||||
|
|
||||||
|
def adapter_class
|
||||||
|
config.adapter_class
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
spec/support/tests/database_adapters/postgresql.rb
Normal file
25
spec/support/tests/database_adapters/postgresql.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
module Tests
|
||||||
|
module DatabaseAdapters
|
||||||
|
class PostgreSQL
|
||||||
|
def self.name
|
||||||
|
:postgresql
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :database
|
||||||
|
|
||||||
|
def initialize(database)
|
||||||
|
@database = database
|
||||||
|
end
|
||||||
|
|
||||||
|
def adapter
|
||||||
|
self.class.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_dependencies
|
||||||
|
require 'pg'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DatabaseConfigurationRegistry.instance.register(PostgreSQL)
|
||||||
|
end
|
||||||
|
end
|
26
spec/support/tests/database_adapters/sqlite3.rb
Normal file
26
spec/support/tests/database_adapters/sqlite3.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module Tests
|
||||||
|
module DatabaseAdapters
|
||||||
|
class SQLite3
|
||||||
|
def self.name
|
||||||
|
:sqlite3
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(_database)
|
||||||
|
end
|
||||||
|
|
||||||
|
def adapter
|
||||||
|
self.class.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def database
|
||||||
|
'db/db.sqlite3'
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_dependencies
|
||||||
|
require 'sqlite3'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DatabaseConfigurationRegistry.instance.register(SQLite3)
|
||||||
|
end
|
||||||
|
end
|
26
spec/support/tests/database_configuration.rb
Normal file
26
spec/support/tests/database_configuration.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
require_relative 'database_configuration_registry'
|
||||||
|
require 'delegate'
|
||||||
|
|
||||||
|
module Tests
|
||||||
|
class DatabaseConfiguration < SimpleDelegator
|
||||||
|
ENVIRONMENTS = %w(development test production)
|
||||||
|
|
||||||
|
def self.for(database_name, adapter_name)
|
||||||
|
config_class = DatabaseConfigurationRegistry.instance.get(adapter_name)
|
||||||
|
config = config_class.new(database_name)
|
||||||
|
new(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
ENVIRONMENTS.each_with_object({}) do |env, config_as_hash|
|
||||||
|
config_as_hash[env] = inner_config_as_hash
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def inner_config_as_hash
|
||||||
|
{ 'adapter' => adapter.to_s, 'database' => database.to_s }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
28
spec/support/tests/database_configuration_registry.rb
Normal file
28
spec/support/tests/database_configuration_registry.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
require 'singleton'
|
||||||
|
|
||||||
|
module Tests
|
||||||
|
class DatabaseConfigurationRegistry
|
||||||
|
include Singleton
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@registry = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def register(config_class)
|
||||||
|
registry[config_class.name] = config_class
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(name)
|
||||||
|
registry.fetch(name) do
|
||||||
|
raise KeyError, "No such adapter registered: #{name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
attr_reader :registry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require_relative 'database_adapters/postgresql'
|
||||||
|
require_relative 'database_adapters/sqlite3'
|
26
spec/support/unit/helpers/column_type_helpers.rb
Normal file
26
spec/support/unit/helpers/column_type_helpers.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module UnitTests
|
||||||
|
module ColumnTypeHelpers
|
||||||
|
def self.configure_example_group(example_group)
|
||||||
|
example_group.include(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def column_type_class_namespace
|
||||||
|
if database_adapter == :postgresql
|
||||||
|
ActiveRecord::ConnectionAdapters::PostgreSQL
|
||||||
|
else
|
||||||
|
ActiveRecord::Type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def column_type_class_for(type)
|
||||||
|
namespace =
|
||||||
|
if type == :integer && database_adapter == :postgresql
|
||||||
|
column_type_class_namespace::OID
|
||||||
|
else
|
||||||
|
column_type_class_namespace
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace.const_get(type.to_s.camelize)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
16
spec/support/unit/helpers/database_helpers.rb
Normal file
16
spec/support/unit/helpers/database_helpers.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module UnitTests
|
||||||
|
module DatabaseHelpers
|
||||||
|
def self.configure_example_group(example_group)
|
||||||
|
example_group.include(self)
|
||||||
|
example_group.extend(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def database_adapter
|
||||||
|
Tests::Database.instance.adapter_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def database_supports_uuid_columns?
|
||||||
|
database_adapter == :postgresql
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -66,17 +66,21 @@ module UnitTests
|
||||||
create_table(table_name, &table_block)
|
create_table(table_name, &table_block)
|
||||||
end
|
end
|
||||||
|
|
||||||
define_model_class(class_name).tap do |model|
|
model = define_model_class(class_name).tap do |m|
|
||||||
if block
|
if block
|
||||||
if block.arity == 0
|
if block.arity == 0
|
||||||
model.class_eval(&block)
|
m.class_eval(&block)
|
||||||
else
|
else
|
||||||
block.call(model)
|
block.call(m)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
model.table_name = table_name
|
m.table_name = table_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defined_models << model
|
||||||
|
|
||||||
|
model
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -89,6 +93,10 @@ module UnitTests
|
||||||
elsif ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!)
|
elsif ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!)
|
||||||
ActiveRecord::Base.connection_pool.clear_cache!
|
ActiveRecord::Base.connection_pool.clear_cache!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defined_models.each do |model|
|
||||||
|
model.reset_column_information
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def drop_created_tables
|
def drop_created_tables
|
||||||
|
@ -102,5 +110,9 @@ module UnitTests
|
||||||
def created_tables
|
def created_tables
|
||||||
@_created_tables ||= []
|
@_created_tables ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def defined_models
|
||||||
|
@_defined_models ||= []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
require_relative '../tests/command_runner'
|
|
||||||
require_relative '../tests/filesystem'
|
|
||||||
require_relative '../tests/bundle'
|
require_relative '../tests/bundle'
|
||||||
|
require_relative '../tests/command_runner'
|
||||||
|
require_relative '../tests/database'
|
||||||
|
require_relative '../tests/filesystem'
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
module UnitTests
|
module UnitTests
|
||||||
class RailsApplication
|
class RailsApplication
|
||||||
def initialize
|
def initialize
|
||||||
@fs = Tests::Filesystem.new
|
@fs = Tests::Filesystem.new
|
||||||
@bundle = Tests::Bundle.new
|
@bundle = Tests::Bundle.new
|
||||||
|
@database = Tests::Database.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
fs.clean
|
fs.clean
|
||||||
generate
|
generate
|
||||||
|
|
||||||
fs.within_project do
|
fs.within_project do
|
||||||
install_gems
|
install_gems
|
||||||
remove_unwanted_gems
|
remove_unwanted_gems
|
||||||
|
@ -54,7 +59,7 @@ module UnitTests
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
attr_reader :fs, :shell, :bundle
|
attr_reader :fs, :shell, :bundle, :database
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
@ -69,6 +74,7 @@ module UnitTests
|
||||||
def generate
|
def generate
|
||||||
rails_new
|
rails_new
|
||||||
fix_available_locales_warning
|
fix_available_locales_warning
|
||||||
|
write_database_configuration
|
||||||
end
|
end
|
||||||
|
|
||||||
def rails_new
|
def rails_new
|
||||||
|
@ -87,13 +93,18 @@ end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def write_database_configuration
|
||||||
|
YAML.dump(database.config.to_hash, fs.open('config/database.yml', 'w'))
|
||||||
|
end
|
||||||
|
|
||||||
def load_environment
|
def load_environment
|
||||||
require environment_file_path
|
require environment_file_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_migrations
|
def run_migrations
|
||||||
ActiveRecord::Migration.verbose = false
|
fs.within_project do
|
||||||
ActiveRecord::Migrator.migrate(migrations_directory)
|
run_command! 'bundle exec rake db:drop db:create db:migrate'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_gems
|
def install_gems
|
||||||
|
|
|
@ -237,19 +237,22 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
context 'when the value is outside of the range of the column' do
|
context 'when the value is outside of the range of the column' do
|
||||||
context 'not qualified with strict' do
|
context 'not qualified with strict' do
|
||||||
it 'rejects, failing with the correct message' do
|
it 'rejects, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> { expect(record).to allow_value(100000).for(:attr) }
|
assertion = -> { expect(record).to allow_value(100000).for(:attr) }
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect errors when attr is set to 100000,
|
Did not expect errors when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'qualified with a message' do
|
context 'qualified with a message' do
|
||||||
it 'ignores any specified message, failing with the correct message' do
|
it 'ignores any specified message, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -257,9 +260,10 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
for(:attr).
|
for(:attr).
|
||||||
with_message('some message')
|
with_message('some message')
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect errors to include "some message" when attr is set to 100000,
|
Did not expect errors to include "some message" when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
@ -269,7 +273,8 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
if active_model_supports_strict?
|
if active_model_supports_strict?
|
||||||
context 'qualified with strict' do
|
context 'qualified with strict' do
|
||||||
it 'rejects, failing with the correct message' do
|
it 'rejects, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -277,16 +282,18 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
for(:attr).
|
for(:attr).
|
||||||
strict
|
strict
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect an exception to have been raised when attr is set to 100000,
|
Did not expect an exception to have been raised when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'qualified with a message' do
|
context 'qualified with a message' do
|
||||||
it 'ignores any specified message' do
|
it 'ignores any specified message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -295,9 +302,10 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
with_message('some message').
|
with_message('some message').
|
||||||
strict
|
strict
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect exception to include "some message" when attr is set to 100000,
|
Did not expect exception to include "some message" when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
@ -306,4 +314,5 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -83,19 +83,22 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
|
||||||
context 'when the value is outside of the range of the column' do
|
context 'when the value is outside of the range of the column' do
|
||||||
context 'not qualified with strict' do
|
context 'not qualified with strict' do
|
||||||
it 'accepts, failing with the correct message' do
|
it 'accepts, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> { expect(record).not_to disallow_value(100000).for(:attr) }
|
assertion = -> { expect(record).not_to disallow_value(100000).for(:attr) }
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect errors when attr is set to 100000,
|
Did not expect errors when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'qualified with a message' do
|
context 'qualified with a message' do
|
||||||
it 'ignores any specified message, failing with the correct message' do
|
it 'ignores any specified message, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -103,9 +106,10 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
|
||||||
for(:attr).
|
for(:attr).
|
||||||
with_message('some message')
|
with_message('some message')
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect errors to include "some message" when attr is set to 100000,
|
Did not expect errors to include "some message" when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
@ -115,7 +119,8 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
|
||||||
if active_model_supports_strict?
|
if active_model_supports_strict?
|
||||||
context 'qualified with strict' do
|
context 'qualified with strict' do
|
||||||
it 'accepts, failing with the correct message' do
|
it 'accepts, failing with the correct message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -123,16 +128,18 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
|
||||||
for(:attr).
|
for(:attr).
|
||||||
strict
|
strict
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect an exception to have been raised when attr is set to 100000,
|
Did not expect an exception to have been raised when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'qualified with a message' do
|
context 'qualified with a message' do
|
||||||
it 'ignores any specified message' do
|
it 'ignores any specified message' do
|
||||||
attribute_options = { type: :integer, options: { limit: 2 } }
|
type = :integer
|
||||||
|
attribute_options = { type: type, options: { limit: 2 } }
|
||||||
record = define_model(:example, attr: attribute_options).new
|
record = define_model(:example, attr: attribute_options).new
|
||||||
assertion = -> do
|
assertion = -> do
|
||||||
expect(record).
|
expect(record).
|
||||||
|
@ -141,9 +148,10 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
|
||||||
with_message('some message').
|
with_message('some message').
|
||||||
strict
|
strict
|
||||||
end
|
end
|
||||||
|
column_type_class = column_type_class_for(type)
|
||||||
message = <<-MESSAGE.strip_heredoc.strip
|
message = <<-MESSAGE.strip_heredoc.strip
|
||||||
Did not expect exception to include "some message" when attr is set to 100000,
|
Did not expect exception to include "some message" when attr is set to 100000,
|
||||||
got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
|
got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
|
||||||
MESSAGE
|
MESSAGE
|
||||||
expect(&assertion).to fail_with_message(message)
|
expect(&assertion).to fail_with_message(message)
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,15 +16,6 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
||||||
)
|
)
|
||||||
expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
|
expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'still accepts if the value of the scope is nil' do
|
|
||||||
record = build_record_validating_uniqueness(
|
|
||||||
scopes: [
|
|
||||||
build_attribute(name: :scope, value: nil)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
expect(record).to validate_uniqueness.scoped_to(:scope)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the subject is an existing record' do
|
context 'when the subject is an existing record' do
|
||||||
|
@ -38,15 +29,6 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
||||||
|
|
||||||
expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
|
expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'still accepts if the value of the scope is nil' do
|
|
||||||
record = create_record_validating_uniqueness(
|
|
||||||
scopes: [
|
|
||||||
build_attribute(name: :scope, value: nil)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
expect(record).to validate_uniqueness.scoped_to(:scope)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -330,9 +312,11 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
||||||
value_type: :time
|
value_type: :time
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when one of the scoped attributes is a UUID column' do
|
if database_supports_uuid_columns?
|
||||||
include_context 'it supports scoped attributes of a certain type',
|
context 'when one of the scoped attributes is a UUID column' do
|
||||||
column_type: :uuid
|
include_context 'it supports scoped attributes of a certain type',
|
||||||
|
column_type: :uuid
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ RSpec.configure do |config|
|
||||||
UnitTests::RailsVersions.configure_example_group(config)
|
UnitTests::RailsVersions.configure_example_group(config)
|
||||||
UnitTests::ActiveRecordVersions.configure_example_group(config)
|
UnitTests::ActiveRecordVersions.configure_example_group(config)
|
||||||
UnitTests::ActiveModelVersions.configure_example_group(config)
|
UnitTests::ActiveModelVersions.configure_example_group(config)
|
||||||
|
UnitTests::DatabaseHelpers.configure_example_group(config)
|
||||||
|
UnitTests::ColumnTypeHelpers.configure_example_group(config)
|
||||||
|
|
||||||
config.include UnitTests::Matchers
|
config.include UnitTests::Matchers
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue