Commit 87b51c24 by Shu Fujita Committed by Andrew W. Lee

Refactor RSpec for AnnotateModels (1) (#726)

I refactored and structuralized RSpec test cases of AnnotateModels for readability and scalability because it was too complex to read. cf. #718 In this PR, I refactored test cases of some methods in `AnnotateModels`. I will refactor test cases of other methods in another PR.
parent 1c5deb09
......@@ -6,6 +6,20 @@ require 'active_support/core_ext/string'
require 'files'
describe AnnotateModels do # rubocop:disable Metrics/BlockLength
MAGIC_COMMENTS = [
'# encoding: UTF-8',
'# coding: UTF-8',
'# -*- coding: UTF-8 -*-',
'#encoding: utf-8',
'# encoding: utf-8',
'# -*- encoding : utf-8 -*-',
"# encoding: utf-8\n# frozen_string_literal: true",
"# frozen_string_literal: true\n# encoding: utf-8",
'# frozen_string_literal: true',
'#frozen_string_literal: false',
'# -*- frozen_string_literal : true -*-'
].freeze
def mock_index(name, params = {})
double('IndexKeyDefinition',
name: name,
......@@ -64,16 +78,71 @@ describe AnnotateModels do # rubocop:disable Metrics/BlockLength
double('Column', stubs)
end
it { expect(AnnotateModels.quote(nil)).to eql('NULL') }
it { expect(AnnotateModels.quote(true)).to eql('TRUE') }
it { expect(AnnotateModels.quote(false)).to eql('FALSE') }
it { expect(AnnotateModels.quote(25)).to eql('25') }
it { expect(AnnotateModels.quote(25.6)).to eql('25.6') }
it { expect(AnnotateModels.quote(1e-20)).to eql('1.0e-20') }
it { expect(AnnotateModels.quote(BigDecimal('1.2'))).to eql('1.2') }
it { expect(AnnotateModels.quote([BigDecimal('1.2')])).to eql(['1.2']) }
describe '.quote' do
subject do
AnnotateModels.quote(value)
end
context 'when the argument is nil' do
let(:value) { nil }
it 'returns string "NULL"' do
is_expected.to eq('NULL')
end
end
describe '#parse_options' do
context 'when the argument is true' do
let(:value) { true }
it 'returns string "TRUE"' do
is_expected.to eq('TRUE')
end
end
context 'when the argument is false' do
let(:value) { false }
it 'returns string "FALSE"' do
is_expected.to eq('FALSE')
end
end
context 'when the argument is an integer' do
let(:value) { 25 }
it 'returns the integer as a string' do
is_expected.to eq('25')
end
end
context 'when the argument is a float number' do
context 'when the argument is like 25.6' do
let(:value) { 25.6 }
it 'returns the float number as a string' do
is_expected.to eq('25.6')
end
end
context 'when the argument is like 1e-20' do
let(:value) { 1e-20 }
it 'returns the float number as a string' do
is_expected.to eq('1.0e-20')
end
end
end
context 'when the argument is a BigDecimal number' do
let(:value) { BigDecimal('1.2') }
it 'returns the float number as a string' do
is_expected.to eq('1.2')
end
end
context 'when the argument is an array' do
let(:value) { [BigDecimal('1.2')] }
it 'returns an array of which elements are converted to string' do
is_expected.to eq(['1.2'])
end
end
end
describe '.parse_options' do
let(:options) do
{
root_dir: '/root',
......@@ -81,20 +150,28 @@ describe AnnotateModels do # rubocop:disable Metrics/BlockLength
}
end
it 'sets @root_dir' do
before :each do
AnnotateModels.send(:parse_options, options)
expect(AnnotateModels.instance_variable_get(:@root_dir)).to eq('/root')
end
it 'sets @model_dir separated with a comma' do
AnnotateModels.send(:parse_options, options)
expected = [
'app/models',
'app/one',
'app/two',
'app/three'
]
expect(AnnotateModels.instance_variable_get(:@model_dir)).to eq(expected)
describe '@root_dir' do
subject do
AnnotateModels.instance_variable_get(:@root_dir)
end
it 'sets @root_dir' do
is_expected.to eq('/root')
end
end
describe '@model_dir' do
subject do
AnnotateModels.instance_variable_get(:@model_dir)
end
it 'separates option "model_dir" with commas and sets @model_dir as an array of string' do
is_expected.to eq(['app/models', 'app/one', 'app/two', 'app/three'])
end
end
end
......@@ -788,14 +865,25 @@ EOS
EOS
end
describe '#set_defaults' do
it 'should default show_complete_foreign_keys to false' do
expect(Annotate::Helpers.true?(ENV['show_complete_foreign_keys'])).to be(false)
describe '.set_defaults' do
subject do
Annotate::Helpers.true?(ENV['show_complete_foreign_keys'])
end
it 'should be able to set show_complete_foreign_keys to true' do
context 'when default value of "show_complete_foreign_keys" is not set' do
it 'returns false' do
is_expected.to be(false)
end
end
context 'when default value of "show_complete_foreign_keys" is set' do
before do
Annotate.set_defaults('show_complete_foreign_keys' => 'true')
expect(Annotate::Helpers.true?(ENV['show_complete_foreign_keys'])).to be(true)
end
it 'returns true' do
is_expected.to be(true)
end
end
after :each do
......@@ -803,14 +891,14 @@ EOS
end
end
describe '#files_by_pattern' do
describe '.files_by_pattern' do
subject { AnnotateModels.files_by_pattern(root_directory, pattern_type, options) }
context 'when pattern_type=additional_file_patterns' do
let(:pattern_type) { 'additional_file_patterns' }
context 'when pattern_type is "additional_file_patterns"' do
let(:root_directory) { nil }
let(:pattern_type) { 'additional_file_patterns' }
context 'with additional_file_patterns' do
context 'when additional_file_patterns is specified in the options' do
let(:additional_file_patterns) do
[
'%PLURALIZED_MODEL_NAME%/**/*.rb',
......@@ -820,28 +908,28 @@ EOS
let(:options) { { additional_file_patterns: additional_file_patterns } }
it do
expect(subject).to eq(additional_file_patterns)
it 'returns additional_file_patterns in the argument "options"' do
is_expected.to eq(additional_file_patterns)
end
end
context 'without additional_file_patterns' do
context 'when additional_file_patterns is not specified is the options' do
let(:options) { {} }
it do
expect(subject).to eq([])
it 'returns an empty array' do
is_expected.to eq([])
end
end
end
end
describe '#get_patterns' do
describe '.get_patterns' do
subject { AnnotateModels.get_patterns(options, pattern_type) }
context 'when pattern_type=additional_file_patterns' do
context 'when pattern_type is "additional_file_patterns"' do
let(:pattern_type) { 'additional_file_patterns' }
context 'with additional_file_patterns' do
context 'when additional_file_patterns is specified in the options' do
let(:additional_file_patterns) do
[
'/%PLURALIZED_MODEL_NAME%/**/*.rb',
......@@ -851,16 +939,16 @@ EOS
let(:options) { { additional_file_patterns: additional_file_patterns } }
it do
expect(subject).to eq(additional_file_patterns)
it 'returns additional_file_patterns in the argument "options"' do
is_expected.to eq(additional_file_patterns)
end
end
context 'without additional_file_patterns' do
context 'when additional_file_patterns is not specified is the options' do
let(:options) { {} }
it do
expect(subject).to eq([])
it 'returns an empty array' do
is_expected.to eq([])
end
end
end
......@@ -1147,7 +1235,7 @@ EOS
end
end
describe '#get_model_files' do
describe '.get_model_files' do
subject { described_class.get_model_files(options) }
before do
......@@ -1262,432 +1350,653 @@ EOS
end
end
describe '#get_model_class' do
describe '.get_model_class' do # rubocop:disable Metrics/BlockLength
before :all do
require 'tmpdir'
AnnotateModels.model_dir = Dir.mktmpdir('annotate_models')
end
# TODO: use 'files' gem instead
def create(file, body = 'hi')
file_path = File.join(AnnotateModels.model_dir[0], file)
FileUtils.mkdir_p(File.dirname(file_path))
File.open(file_path, 'wb') do |f|
f.puts(body)
def create(filename, file_content)
File.join(AnnotateModels.model_dir[0], filename).tap do |path|
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'wb') do |f|
f.puts(file_content)
end
end
file_path
end
def check_class_name(file, class_name)
klass = AnnotateModels.get_model_class(File.join(AnnotateModels.model_dir[0], file))
before :each do
create(filename, file_content)
end
expect(klass).not_to eq(nil)
expect(klass.name).to eq(class_name)
let :klass do
AnnotateModels.get_model_class(File.join(AnnotateModels.model_dir[0], filename))
end
before :each do
AnnotateModels.model_dir = Dir.mktmpdir 'annotate_models'
context 'when class Foo is defined in "foo.rb"' do
let :filename do
'foo.rb'
end
it 'should work' do
create 'foo.rb', <<-EOS
let :file_content do
<<~EOS
class Foo < ActiveRecord::Base
end
EOS
check_class_name 'foo.rb', 'Foo'
end
it 'should find models with non standard capitalization' do
create 'foo_with_capitals.rb', <<-EOS
it 'works' do
expect(klass.name).to eq('Foo')
end
end
context 'when class name is not capitalized normally' do
context 'when class FooWithCAPITALS is defined in "foo_with_capitals.rb"' do
let :filename do
'foo_with_capitals.rb'
end
let :file_content do
<<~EOS
class FooWithCAPITALS < ActiveRecord::Base
end
EOS
check_class_name 'foo_with_capitals.rb', 'FooWithCAPITALS'
end
it 'should find models inside modules' do
create 'bar/foo_inside_bar.rb', <<-EOS
it 'works' do
expect(klass.name).to eq('FooWithCAPITALS')
end
end
end
context 'when class is defined inside module' do
context 'when class Bar::FooInsideBar is defined in "bar/foo_inside_bar.rb"' do
let :filename do
'bar/foo_inside_bar.rb'
end
let :file_content do
<<~EOS
module Bar
class FooInsideBar < ActiveRecord::Base
end
end
EOS
check_class_name 'bar/foo_inside_bar.rb', 'Bar::FooInsideBar'
end
it 'should find AR model when duplicated by a nested model' do
create 'foo.rb', <<-EOS
class Foo < ActiveRecord::Base
it 'works' do
expect(klass.name).to eq('Bar::FooInsideBar')
end
end
end
EOS
create 'bar/foo.rb', <<-EOS
class Bar::Foo
context 'when class is defined inside module and class name is not capitalized normally' do
context 'when class Bar::FooInsideCapitalsBAR is defined in "bar/foo_inside_capitals_bar.rb"' do
let :filename do
'bar/foo_inside_capitals_bar.rb'
end
let :file_content do
<<~EOS
module BAR
class FooInsideCapitalsBAR < ActiveRecord::Base
end
end
EOS
check_class_name 'bar/foo.rb', 'Bar::Foo'
check_class_name 'foo.rb', 'Foo'
end
it 'should find AR model nested inside a class' do
create 'voucher.rb', <<-EOS
class Voucher < ActiveRecord::Base
it 'works' do
expect(klass.name).to eq('BAR::FooInsideCapitalsBAR')
end
end
end
EOS
create 'voucher/foo.rb', <<-EOS
class Voucher
class Foo
context 'when unknown macros exist in class' do
context 'when class FooWithMacro is defined in "foo_with_macro.rb"' do
let :filename do
'foo_with_macro.rb'
end
let :file_content do
<<~EOS
class FooWithMacro < ActiveRecord::Base
acts_as_awesome :yah
end
EOS
end
it 'works and does not care about known macros' do
expect(klass.name).to eq('FooWithMacro')
end
end
check_class_name 'voucher.rb', 'Voucher'
check_class_name 'voucher/foo.rb', 'Voucher::Foo'
context 'when class name is with ALL CAPS segments' do
context 'when class is "FooWithCAPITALS" is defined in "foo_with_capitals.rb"' do
let :filename do
'foo_with_capitals.rb'
end
it 'should not care about unknown macros' do
create 'foo_with_macro.rb', <<-EOS
class FooWithMacro < ActiveRecord::Base
let :file_content do
<<~EOS
class FooWithCAPITALS < ActiveRecord::Base
acts_as_awesome :yah
end
EOS
check_class_name 'foo_with_macro.rb', 'FooWithMacro'
end
it 'should not care about known macros' do
create('foo_with_known_macro.rb', <<-EOS)
it 'works' do
expect(klass.name).to eq('FooWithCAPITALS')
end
end
end
end
context 'when known macros exist in class' do
context 'when class FooWithKnownMacro is defined in "foo_with_known_macro.rb"' do
let :filename do
'foo_with_known_macro.rb'
end
let :file_content do
<<~EOS
class FooWithKnownMacro < ActiveRecord::Base
has_many :yah
end
EOS
check_class_name 'foo_with_known_macro.rb', 'FooWithKnownMacro'
end
it 'should work with class names with ALL CAPS segments' do
create('foo_with_capitals.rb', <<-EOS)
class FooWithCAPITALS < ActiveRecord::Base
acts_as_awesome :yah
it 'works and does not care about known macros' do
expect(klass.name).to eq('FooWithKnownMacro')
end
EOS
check_class_name 'foo_with_capitals.rb', 'FooWithCAPITALS'
end
end
context 'when the file includes invlaid multibyte chars (USASCII)' do
context 'when class FooWithUtf8 is defined in "foo_with_utf8.rb"' do
let :filename do
'foo_with_utf8.rb'
end
it 'should not complain of invalid multibyte char (USASCII)' do
create 'foo_with_utf8.rb', <<-EOS
#encoding: utf-8
let :file_content do
<<~EOS
# encoding: utf-8
class FooWithUtf8 < ActiveRecord::Base
UTF8STRINGS = %w[résumé façon âge]
end
EOS
check_class_name 'foo_with_utf8.rb', 'FooWithUtf8'
end
it 'should find models inside modules with non standard capitalization' do
create 'bar/foo_inside_capitals_bar.rb', <<-EOS
module BAR
class FooInsideCapitalsBAR < ActiveRecord::Base
it 'works without complaining of invalid multibyte chars' do
expect(klass.name).to eq('FooWithUtf8')
end
end
EOS
check_class_name 'bar/foo_inside_capitals_bar.rb', 'BAR::FooInsideCapitalsBAR'
end
it 'should find non-namespaced models inside subdirectories' do
create 'bar/non_namespaced_foo_inside_bar.rb', <<-EOS
context 'when non-namespaced model is inside subdirectory' do
context 'when class NonNamespacedFooInsideBar is defined in "bar/non_namespaced_foo_inside_bar.rb"' do
let :filename do
'bar/non_namespaced_foo_inside_bar.rb'
end
let :file_content do
<<~EOS
class NonNamespacedFooInsideBar < ActiveRecord::Base
end
EOS
check_class_name 'bar/non_namespaced_foo_inside_bar.rb', 'NonNamespacedFooInsideBar'
end
it 'should find non-namespaced models with non standard capitalization inside subdirectories' do
create 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', <<-EOS
it 'works' do
expect(klass.name).to eq('NonNamespacedFooInsideBar')
end
end
context 'when class name is not capitalized normally' do
context 'when class NonNamespacedFooWithCapitalsInsideBar is defined in "bar/non_namespaced_foo_with_capitals_inside_bar.rb"' do
let :filename do
'bar/non_namespaced_foo_with_capitals_inside_bar.rb'
end
let :file_content do
<<~EOS
class NonNamespacedFooWithCapitalsInsideBar < ActiveRecord::Base
end
EOS
check_class_name 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', 'NonNamespacedFooWithCapitalsInsideBar'
end
it 'should allow known macros' do
create('foo_with_known_macro.rb', <<-EOS)
class FooWithKnownMacro < ActiveRecord::Base
has_many :yah
it 'works' do
expect(klass.name).to eq('NonNamespacedFooWithCapitalsInsideBar')
end
end
EOS
expect(capturing(:stderr) do
check_class_name 'foo_with_known_macro.rb', 'FooWithKnownMacro'
end).to eq('')
end
end
context 'when class file is loaded twice' do
context 'when class LoadedClass is defined in "loaded_class.rb"' do
let :filename do
'loaded_class.rb'
end
it 'should not require model files twice' do
create 'loaded_class.rb', <<-EOS
let :file_content do
<<~EOS
class LoadedClass < ActiveRecord::Base
CONSTANT = 1
end
EOS
path = File.expand_path('loaded_class', AnnotateModels.model_dir[0])
Kernel.load "#{path}.rb"
end
before :each do
path = File.expand_path(filename, AnnotateModels.model_dir[0])
Kernel.load(path)
expect(Kernel).not_to receive(:require)
end
expect(capturing(:stderr) do
check_class_name 'loaded_class.rb', 'LoadedClass'
end).to be_blank
it 'does not require model file twice' do
expect(klass.name).to eq('LoadedClass')
end
end
it 'should not require model files twice which is inside a subdirectory' do
context 'when class is defined in a subdirectory' do
dir = Array.new(8) { (0..9).to_a.sample(random: Random.new) }.join
context "when class SubdirLoadedClass is defined in \"#{dir}/subdir_loaded_class.rb\"" do
before :each do
$LOAD_PATH.unshift(File.join(AnnotateModels.model_dir[0], dir))
create "#{dir}/subdir_loaded_class.rb", <<-EOS
path = File.expand_path(filename, AnnotateModels.model_dir[0])
Kernel.load(path)
expect(Kernel).not_to receive(:require)
end
let :filename do
"#{dir}/subdir_loaded_class.rb"
end
let :file_content do
<<~EOS
class SubdirLoadedClass < ActiveRecord::Base
CONSTANT = 1
end
EOS
path = File.expand_path("#{dir}/subdir_loaded_class", AnnotateModels.model_dir[0])
Kernel.load "#{path}.rb"
expect(Kernel).not_to receive(:require)
end
expect(capturing(:stderr) do
check_class_name "#{dir}/subdir_loaded_class.rb", 'SubdirLoadedClass'
end).to be_blank
it 'does not require model file twice' do
expect(klass.name).to eq('SubdirLoadedClass')
end
end
end
end
describe '#remove_annotation_of_file' do
require 'tmpdir'
context 'when two class exist' do
before :each do
create(filename_2, file_content_2)
end
def create(file, body = 'hi')
path = File.join(@dir, file)
File.open(path, 'w') do |f|
f.puts(body)
context 'the base names are duplicated' do
let :filename do
'foo.rb'
end
path
let :file_content do
<<-EOS
class Foo < ActiveRecord::Base
end
EOS
end
def content(path)
File.read(path)
let :filename_2 do
'bar/foo.rb'
end
before :each do
@dir = Dir.mktmpdir 'annotate_models'
let :file_content_2 do
<<-EOS
class Bar::Foo
end
EOS
end
it 'should remove before annotate' do
path = create 'before.rb', <<-EOS
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
let :klass_2 do
AnnotateModels.get_model_class(File.join(AnnotateModels.model_dir[0], filename_2))
end
class Foo < ActiveRecord::Base
end
EOS
it 'finds valid model' do
expect(klass.name).to eq('Foo')
expect(klass_2.name).to eq('Bar::Foo')
end
end
AnnotateModels.remove_annotation_of_file(path)
context 'one of the classes is nested in another class' do
let :filename do
'voucher.rb'
end
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
let :file_content do
<<-EOS
class Voucher < ActiveRecord::Base
end
EOS
end
it 'should remove annotate if CRLF is used for line breaks' do
path = create 'before.rb', <<-EOS
# == Schema Information
#
# Table name: foo\r\n#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
\r\n
class Foo < ActiveRecord::Base
end
let :filename_2 do
'voucher/foo.rb'
end
let :file_content_2 do
<<~EOS
class Voucher
class Foo
end
end
EOS
end
let :klass_2 do
AnnotateModels.get_model_class(File.join(AnnotateModels.model_dir[0], filename_2))
end
it 'finds valid model' do
expect(klass.name).to eq('Voucher')
expect(klass_2.name).to eq('Voucher::Foo')
end
end
end
end
describe '.remove_annotation_of_file' do
subject do
AnnotateModels.remove_annotation_of_file(path)
end
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
let :tmpdir do
require 'tmpdir'
Dir.mktmpdir('annotate_models')
end
let :path do
File.join(tmpdir, filename).tap do |path|
File.open(path, 'w') do |f|
f.puts(file_content)
end
end
end
let :file_content_after_removal do
subject
File.read(path)
end
let :expected_result do
<<~EOS
class Foo < ActiveRecord::Base
end
EOS
end
it 'should remove after annotate' do
path = create 'after.rb', <<-EOS
class Foo < ActiveRecord::Base
end
context 'when annotation is before main content' do
let :filename do
'before.rb'
end
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
let :file_content do
<<~EOS
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
class Foo < ActiveRecord::Base
end
EOS
end
AnnotateModels.remove_annotation_of_file(path)
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
context 'when annotation is before main content and CRLF is used for line breaks' do
let :filename do
'before.rb'
end
let :file_content do
<<~EOS
# == Schema Information
#
# Table name: foo\r\n#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
\r\n
class Foo < ActiveRecord::Base
end
EOS
end
it 'should remove opening wrapper' do
path = create 'opening_wrapper.rb', <<-EOS
# wrapper
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
class Foo < ActiveRecord::Base
end
context 'when annotation is before main content and with opening wrapper' do
let :filename do
'opening_wrapper.rb'
end
let :file_content do
<<~EOS
# wrapper
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
class Foo < ActiveRecord::Base
end
EOS
end
subject do
AnnotateModels.remove_annotation_of_file(path, wrapper_open: 'wrapper')
end
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
EOS
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
it 'should remove wrapper if CRLF is used for line breaks' do
path = create 'opening_wrapper.rb', <<-EOS
# wrapper\r\n# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
context 'when annotation is before main content and with opening wrapper' do
let :filename do
'opening_wrapper.rb'
end
class Foo < ActiveRecord::Base
end
let :file_content do
<<~EOS
# wrapper\r\n# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
class Foo < ActiveRecord::Base
end
EOS
end
subject do
AnnotateModels.remove_annotation_of_file(path, wrapper_open: 'wrapper')
end
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
context 'when annotation is after main content' do
let :filename do
'after.rb'
end
let :file_content do
<<~EOS
class Foo < ActiveRecord::Base
end
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
EOS
end
it 'should remove closing wrapper' do
path = create 'closing_wrapper.rb', <<-EOS
class Foo < ActiveRecord::Base
end
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
# wrapper
context 'when annotation is after main content and with closing wrapper' do
let :filename do
'closing_wrapper.rb'
end
let :file_content do
<<~EOS
class Foo < ActiveRecord::Base
end
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
# wrapper
EOS
end
subject do
AnnotateModels.remove_annotation_of_file(path, wrapper_close: 'wrapper')
end
expect(content(path)).to eq <<-EOS
class Foo < ActiveRecord::Base
end
EOS
it 'removes annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
it 'does not change file with #SkipSchemaAnnotations' do
content = <<-EOS
# -*- SkipSchemaAnnotations
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
context 'when annotation is before main content and with comment "-*- SkipSchemaAnnotations"' do
let :filename do
'skip.rb'
end
class Foo < ActiveRecord::Base
end
let :file_content do
<<~EOS
# -*- SkipSchemaAnnotations
# == Schema Information
#
# Table name: foo
#
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
class Foo < ActiveRecord::Base
end
EOS
end
path = create 'skip.rb', content
let :expected_result do
file_content
end
AnnotateModels.remove_annotation_of_file(path)
expect(content(path)).to eq(content)
it 'does not remove annotation' do
expect(file_content_after_removal).to eq expected_result
end
end
end
describe '#resolve_filename' do
it 'should return the test path for a model' do
filename_template = 'test/unit/%MODEL_NAME%_test.rb'
model_name = 'example_model'
table_name = 'example_models'
describe '.resolve_filename' do
subject do
AnnotateModels.resolve_filename(filename_template, model_name, table_name)
end
context 'When model_name is "example_model" and table_name is "example_models"' do
let(:model_name) { 'example_model' }
let(:table_name) { 'example_models' }
context "when filename_template is 'test/unit/%MODEL_NAME%_test.rb'" do
let(:filename_template) { 'test/unit/%MODEL_NAME%_test.rb' }
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq 'test/unit/example_model_test.rb'
it 'returns the test path for a model' do
is_expected.to eq 'test/unit/example_model_test.rb'
end
end
it 'should return the additional glob' do
filename_template = '/foo/bar/%MODEL_NAME%/testing.rb'
model_name = 'example_model'
table_name = 'example_models'
context "when filename_template is '/foo/bar/%MODEL_NAME%/testing.rb'" do
let(:filename_template) { '/foo/bar/%MODEL_NAME%/testing.rb' }
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq '/foo/bar/example_model/testing.rb'
it 'returns the additional glob' do
is_expected.to eq '/foo/bar/example_model/testing.rb'
end
end
it 'should return the additional glob' do
filename_template = '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb'
model_name = 'example_model'
table_name = 'example_models'
context "when filename_template is '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb'" do
let(:filename_template) { '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb' }
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq '/foo/bar/example_models/testing.rb'
it 'returns the additional glob' do
is_expected.to eq '/foo/bar/example_models/testing.rb'
end
end
it 'should return the fixture path for a model' do
filename_template = 'test/fixtures/%TABLE_NAME%.yml'
model_name = 'example_model'
table_name = 'example_models'
context "when filename_template is 'test/fixtures/%TABLE_NAME%.yml'" do
let(:filename_template) { 'test/fixtures/%TABLE_NAME%.yml' }
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq 'test/fixtures/example_models.yml'
it 'returns the fixture path for a model' do
is_expected.to eq 'test/fixtures/example_models.yml'
end
end
end
context 'When model_name is "parent/child" and table_name is "parent_children"' do
let(:model_name) { 'parent/child' }
let(:table_name) { 'parent_children' }
it 'should return the fixture path for a nested model' do
filename_template = 'test/fixtures/%PLURALIZED_MODEL_NAME%.yml'
model_name = 'parent/child'
table_name = 'parent_children'
context "when filename_template is 'test/fixtures/%PLURALIZED_MODEL_NAME%.yml'" do
let(:filename_template) { 'test/fixtures/%PLURALIZED_MODEL_NAME%.yml' }
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq 'test/fixtures/parent/children.yml'
it 'returns the fixture path for a nested model' do
is_expected.to eq 'test/fixtures/parent/children.yml'
end
end
end
end
describe 'annotating a file' do
before do
@model_dir = Dir.mktmpdir('annotate_models')
(@model_file_name, @file_content) = write_model 'user.rb', <<-EOS
class User < ActiveRecord::Base
end
(@model_file_name, @file_content) = write_model 'user.rb', <<~EOS
class User < ActiveRecord::Base
end
EOS
@klass = mock_class(:users,
......@@ -1720,22 +2029,6 @@ end
Annotate::Constants::PATH_OPTIONS.each { |key| ENV[key.to_s] = '' }
end
def magic_comments_list_each
[
'# encoding: UTF-8',
'# coding: UTF-8',
'# -*- coding: UTF-8 -*-',
'#encoding: utf-8',
'# encoding: utf-8',
'# -*- encoding : utf-8 -*-',
"# encoding: utf-8\n# frozen_string_literal: true",
"# frozen_string_literal: true\n# encoding: utf-8",
'# frozen_string_literal: true',
'#frozen_string_literal: false',
'# -*- frozen_string_literal : true -*-'
].each { |magic_comment| yield magic_comment }
end
['before', :before, 'top', :top].each do |position|
it "should put annotation before class if :position == #{position}" do
annotate_one_file position: position
......@@ -1854,9 +2147,9 @@ end
end
it 'works with namespaced models (i.e. models inside modules/subdirectories)' do
(model_file_name, file_content) = write_model 'foo/user.rb', <<-EOS
class Foo::User < ActiveRecord::Base
end
(model_file_name, file_content) = write_model 'foo/user.rb', <<~EOS
class Foo::User < ActiveRecord::Base
end
EOS
klass = mock_class(:'foo_users',
......@@ -1871,11 +2164,11 @@ end
end
it 'should not touch magic comments' do
magic_comments_list_each do |magic_comment|
write_model 'user.rb', <<-EOS
#{magic_comment}
class User < ActiveRecord::Base
end
MAGIC_COMMENTS.each do |magic_comment|
write_model 'user.rb', <<~EOS
#{magic_comment}
class User < ActiveRecord::Base
end
EOS
annotate_one_file position: :before
......@@ -1891,7 +2184,7 @@ end
it 'adds an empty line between magic comments and annotation (position :before)' do
content = "class User < ActiveRecord::Base\nend\n"
magic_comments_list_each do |magic_comment|
MAGIC_COMMENTS.each do |magic_comment|
model_file_name, = write_model 'user.rb', "#{magic_comment}\n#{content}"
annotate_one_file position: :before
......@@ -1903,7 +2196,7 @@ end
it 'only keeps a single empty line around the annotation (position :before)' do
content = "class User < ActiveRecord::Base\nend\n"
magic_comments_list_each do |magic_comment|
MAGIC_COMMENTS.each do |magic_comment|
schema_info = AnnotateModels.get_schema_info(@klass, '== Schema Info')
model_file_name, = write_model 'user.rb', "#{magic_comment}\n\n\n\n#{content}"
......@@ -1915,7 +2208,7 @@ end
it 'does not change whitespace between magic comments and model file content (position :after)' do
content = "class User < ActiveRecord::Base\nend\n"
magic_comments_list_each do |magic_comment|
MAGIC_COMMENTS.each do |magic_comment|
model_file_name, = write_model 'user.rb', "#{magic_comment}\n#{content}"
annotate_one_file position: :after
......@@ -1929,7 +2222,7 @@ end
before do
allow(AnnotateModels).to receive(:get_loaded_model_by_path).with('user').and_return(nil)
write_model('user.rb', <<-EOS)
write_model('user.rb', <<~EOS)
class User < ActiveRecord::Base
raise "oops"
end
......@@ -1959,7 +2252,7 @@ end
before do
allow(AnnotateModels).to receive(:get_loaded_model_by_path).with('user').and_return(nil)
write_model('user.rb', <<-EOS)
write_model('user.rb', <<~EOS)
class User < ActiveRecord::Base
raise "oops"
end
......@@ -2012,12 +2305,14 @@ end
allow(Foo).to receive(:table_exists?) { false }
end
subject do
AnnotateModels.annotate_model_file([], 'foo.rb', nil, {})
end
after { Object.send :remove_const, 'Foo' }
it 'skips attempt to annotate if no table exists for model' do
annotate_model_file = AnnotateModels.annotate_model_file([], 'foo.rb', nil, {})
expect(annotate_model_file).to eq nil
is_expected.to eq nil
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment