diff --git a/spec/lib/annotate/annotate_models_spec.rb b/spec/lib/annotate/annotate_models_spec.rb index 029718d09..a01de1aa0 100644 --- a/spec/lib/annotate/annotate_models_spec.rb +++ b/spec/lib/annotate/annotate_models_spec.rb @@ -987,283 +987,429 @@ def mock_column(name, type, options = {}) end end - describe '#get_schema_info with custom options' do - def self.when_called_with(options = {}) - expected = options.delete(:returns) - default_columns = [ - [:id, :integer, { limit: 8 }], - [:active, :boolean, { limit: 1 }], - [:name, :string, { limit: 50 }], - [:notes, :text, { limit: 55 }] - ] + describe '.get_schema_info (with custom options)' do + let :klass do + mock_class(:users, :id, columns) + end + + subject do + AnnotateModels.get_schema_info(klass, header, options) + end + + context 'when header is "Schema Info"' do + let :header do + 'Schema Info' + end + + context 'with options' do + context 'when "hide_limit_column_types" is specified in options' do + let :columns do + [ + mock_column(:id, :integer, limit: 8), + mock_column(:active, :boolean, limit: 1), + mock_column(:name, :string, limit: 50), + mock_column(:notes, :text, limit: 55) + ] + end + + context 'when "hide_limit_column_types" is blank string' do + let :options do + { hide_limit_column_types: '' } + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id :integer not null, primary key + # active :boolean not null + # name :string(50) not null + # notes :text(55) not null + # + EOS + end + + it 'works with option "hide_limit_column_types"' do + is_expected.to eq expected_result + end + end + + context 'when "hide_limit_column_types" is "integer,boolean"' do + let :options do + { hide_limit_column_types: 'integer,boolean' } + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id :integer not null, primary key + # active :boolean not null + # name :string(50) not null + # notes :text(55) not null + # + EOS + end + + it 'works with option "hide_limit_column_types"' do + is_expected.to eq expected_result + end + end - it "should work with options = #{options}" do - with_columns = (options.delete(:with_columns) || default_columns).map do |column| - mock_column(column[0], column[1], column[2]) + context 'when "hide_limit_column_types" is "integer,boolean,string,text"' do + let :options do + { hide_limit_column_types: 'integer,boolean,string,text' } + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id :integer not null, primary key + # active :boolean not null + # name :string not null + # notes :text not null + # + EOS + end + + it 'works with option "hide_limit_column_types"' do + is_expected.to eq expected_result + end + end end - klass = mock_class(:users, :id, with_columns) + context 'when "hide_default_column_types" is specified in options' do + let :columns do + [ + mock_column(:profile, :json, default: {}), + mock_column(:settings, :jsonb, default: {}), + mock_column(:parameters, :hstore, default: {}) + ] + end - schema_info = AnnotateModels.get_schema_info(klass, 'Schema Info', options) - expect(schema_info).to eql(expected) - end - end + context 'when "hide_default_column_types" is blank string' do + let :options do + { hide_default_column_types: '' } + end - describe 'hide_limit_column_types option' do - when_called_with hide_limit_column_types: '', returns: <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id :integer not null, primary key - # active :boolean not null - # name :string(50) not null - # notes :text(55) not null - # - EOS + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # profile :json not null + # settings :jsonb not null + # parameters :hstore not null + # + EOS + end - when_called_with hide_limit_column_types: 'integer,boolean', returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id :integer not null, primary key - # active :boolean not null - # name :string(50) not null - # notes :text(55) not null - # - EOS + it 'works with option "hide_default_column_types"' do + is_expected.to eq expected_result + end + end - when_called_with hide_limit_column_types: 'integer,boolean,string,text', - returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id :integer not null, primary key - # active :boolean not null - # name :string not null - # notes :text not null - # - EOS - end + context 'when "hide_default_column_types" is "skip"' do + let :options do + { hide_default_column_types: 'skip' } + end - describe 'hide_default_column_types option' do - mocked_columns_without_id = [ - [:profile, :json, default: {}], - [:settings, :jsonb, default: {}], - [:parameters, :hstore, default: {}] - ] + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # profile :json default({}), not null + # settings :jsonb default({}), not null + # parameters :hstore default({}), not null + # + EOS + end - when_called_with hide_default_column_types: '', - with_columns: mocked_columns_without_id, - returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # profile :json not null - # settings :jsonb not null - # parameters :hstore not null - # - EOS + it 'works with option "hide_default_column_types"' do + is_expected.to eq expected_result + end + end - when_called_with hide_default_column_types: 'skip', - with_columns: mocked_columns_without_id, - returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # profile :json default({}), not null - # settings :jsonb default({}), not null - # parameters :hstore default({}), not null - # - EOS + context 'when "hide_default_column_types" is "json"' do + let :options do + { hide_default_column_types: 'json' } + end - when_called_with hide_default_column_types: 'json', - with_columns: mocked_columns_without_id, - returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # profile :json not null - # settings :jsonb default({}), not null - # parameters :hstore default({}), not null - # - EOS - end + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # profile :json not null + # settings :jsonb default({}), not null + # parameters :hstore default({}), not null + # + EOS + end - describe 'classified_sort option' do - mocked_columns_without_id = [ - [:active, :boolean, { limit: 1 }], - [:name, :string, { limit: 50 }], - [:notes, :text, { limit: 55 }] - ] + it 'works with option "hide_limit_column_types"' do + is_expected.to eq expected_result + end + end + end - when_called_with classified_sort: 'yes', - with_columns: mocked_columns_without_id, returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # active :boolean not null - # name :string(50) not null - # notes :text(55) not null - # - EOS - end + context 'when "classified_sort" is specified in options' do + let :columns do + [ + mock_column(:active, :boolean, limit: 1), + mock_column(:name, :string, limit: 50), + mock_column(:notes, :text, limit: 55) + ] + end - describe 'with_comment option' do - mocked_columns_with_comment = [ - [:id, :integer, { limit: 8, comment: 'ID' }], - [:active, :boolean, { limit: 1, comment: 'Active' }], - [:name, :string, { limit: 50, comment: 'Name' }], - [:notes, :text, { limit: 55, comment: 'Notes' }], - [:no_comment, :text, { limit: 20, comment: nil }] - ] + context 'when "classified_sort" is "yes"' do + let :options do + { classified_sort: 'yes' } + end - when_called_with with_comment: 'yes', - with_columns: mocked_columns_with_comment, returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id(ID) :integer not null, primary key - # active(Active) :boolean not null - # name(Name) :string(50) not null - # notes(Notes) :text(55) not null - # no_comment :text(20) not null - # - EOS + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # active :boolean not null + # name :string(50) not null + # notes :text(55) not null + # + EOS + end - mocked_columns_with_multibyte_comment = [ - [:id, :integer, { limit: 8, comment: 'ID' }], - [:active, :boolean, { limit: 1, comment: 'ACTIVE' }], - [:name, :string, { limit: 50, comment: 'NAME' }], - [:notes, :text, { limit: 55, comment: 'NOTES' }], - [:cyrillic, :text, { limit: 30, comment: 'Кириллица' }], - [:japanese, :text, { limit: 60, comment: '熊本大学 イタリア 宝島' }], - [:arabic, :text, { limit: 20, comment: 'لغة' }], - [:no_comment, :text, { limit: 20, comment: nil }], - [:location, :geometry_collection, { limit: nil, comment: nil }] - ] + it 'works with option "classified_sort"' do + is_expected.to eq expected_result + end + end + end - when_called_with with_comment: 'yes', - with_columns: mocked_columns_with_multibyte_comment, returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id(ID) :integer not null, primary key - # active(ACTIVE) :boolean not null - # name(NAME) :string(50) not null - # notes(NOTES) :text(55) not null - # cyrillic(Кириллица) :text(30) not null - # japanese(熊本大学 イタリア 宝島) :text(60) not null - # arabic(لغة) :text(20) not null - # no_comment :text(20) not null - # location :geometry_collect not null - # - EOS + context 'when "with_comment" is specified in options' do + context 'when "with_comment" is "yes"' do + let :options do + { with_comment: 'yes' } + end - mocked_columns_with_geometries = [ - [:id, :integer, { limit: 8 }], - [:active, :boolean, { default: false, null: false }], - [:geometry, :geometry, { - geometric_type: 'Geometry', srid: 4326, - limit: { srid: 4326, type: 'geometry' } - }], - [:location, :geography, { - geometric_type: 'Point', srid: 0, - limit: { srid: 0, type: 'geometry' } - }] - ] + context 'when columns have comments' do + let :columns do + [ + mock_column(:id, :integer, limit: 8, comment: 'ID'), + mock_column(:active, :boolean, limit: 1, comment: 'Active'), + mock_column(:name, :string, limit: 50, comment: 'Name'), + mock_column(:notes, :text, limit: 55, comment: 'Notes'), + mock_column(:no_comment, :text, limit: 20, comment: nil) + ] + end - when_called_with with_columns: mocked_columns_with_geometries, returns: - <<-EOS.strip_heredoc - # Schema Info - # - # Table name: users - # - # id :integer not null, primary key - # active :boolean default(FALSE), not null - # geometry :geometry not null, geometry, 4326 - # location :geography not null, point, 0 - # - EOS + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id(ID) :integer not null, primary key + # active(Active) :boolean not null + # name(Name) :string(50) not null + # notes(Notes) :text(55) not null + # no_comment :text(20) not null + # + EOS + end - it 'should get schema info as RDoc' do - klass = mock_class(:users, - :id, - [ - mock_column(:id, :integer, comment: 'ID'), - mock_column(:name, :string, limit: 50, comment: 'Name') - ]) - expect(AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX, format_rdoc: true, with_comment: true)).to eql(<<-EOS.strip_heredoc) - # #{AnnotateModels::PREFIX} - # - # Table name: users - # - # *id(ID)*:: integer, not null, primary key - # *name(Name)*:: string(50), not null - #-- - # #{AnnotateModels::END_MARK} - #++ - EOS + it 'works with option "with_comment"' do + is_expected.to eq expected_result + end + end + + context 'when columns have multibyte comments' do + let :columns do + [ + mock_column(:id, :integer, limit: 8, comment: 'ID'), + mock_column(:active, :boolean, limit: 1, comment: 'ACTIVE'), + mock_column(:name, :string, limit: 50, comment: 'NAME'), + mock_column(:notes, :text, limit: 55, comment: 'NOTES'), + mock_column(:cyrillic, :text, limit: 30, comment: 'Кириллица'), + mock_column(:japanese, :text, limit: 60, comment: '熊本大学 イタリア 宝島'), + mock_column(:arabic, :text, limit: 20, comment: 'لغة'), + mock_column(:no_comment, :text, limit: 20, comment: nil), + mock_column(:location, :geometry_collection, limit: nil, comment: nil) + ] + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id(ID) :integer not null, primary key + # active(ACTIVE) :boolean not null + # name(NAME) :string(50) not null + # notes(NOTES) :text(55) not null + # cyrillic(Кириллица) :text(30) not null + # japanese(熊本大学 イタリア 宝島) :text(60) not null + # arabic(لغة) :text(20) not null + # no_comment :text(20) not null + # location :geometry_collect not null + # + EOS + end + + it 'works with option "with_comment"' do + is_expected.to eq expected_result + end + end + + context 'when geometry columns are included' do + let :columns do + [ + mock_column(:id, :integer, limit: 8), + mock_column(:active, :boolean, default: false, null: false), + mock_column(:geometry, :geometry, + geometric_type: 'Geometry', srid: 4326, + limit: { srid: 4326, type: 'geometry' }), + mock_column(:location, :geography, + geometric_type: 'Point', srid: 0, + limit: { srid: 0, type: 'geometry' }) + ] + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users + # + # id :integer not null, primary key + # active :boolean default(FALSE), not null + # geometry :geometry not null, geometry, 4326 + # location :geography not null, point, 0 + # + EOS + end + + it 'works with option "with_comment"' do + is_expected.to eq expected_result + end + end + end + end end + end - it 'should get schema info as Markdown with multibyte comment' do - klass = mock_class(:users, - :id, - [ - mock_column(:id, :integer, comment: 'ID'), - mock_column(:name, :string, limit: 50, comment: 'NAME') - ]) - expect(AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX, format_markdown: true, with_comment: true)).to eql(<<-EOS.strip_heredoc) - # #{AnnotateModels::PREFIX} - # - # Table name: `users` - # - # ### Columns - # - # Name | Type | Attributes - # --------------------- | ------------------ | --------------------------- - # **`id(ID)`** | `integer` | `not null, primary key` - # **`name(NAME)`** | `string(50)` | `not null` - # - EOS + context 'when header is "== Schema Information"' do + let :header do + AnnotateModels::PREFIX end - it 'should get schema info as Markdown' do - klass = mock_class(:users, - :id, - [ - mock_column(:id, :integer, comment: 'ID'), - mock_column(:name, :string, limit: 50, comment: 'Name') - ]) - expect(AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX, format_markdown: true, with_comment: true)).to eql(<<-EOS.strip_heredoc) - # #{AnnotateModels::PREFIX} - # - # Table name: `users` - # - # ### Columns - # - # Name | Type | Attributes - # ----------------- | ------------------ | --------------------------- - # **`id(ID)`** | `integer` | `not null, primary key` - # **`name(Name)`** | `string(50)` | `not null` - # - EOS + context 'when "format_doc" and "with_comment" are specified in options' do + subject do + AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX, format_rdoc: true, with_comment: true) + end + + context 'when columns are normal' do + let :columns do + [ + mock_column(:id, :integer, comment: 'ID'), + mock_column(:name, :string, limit: 50, comment: 'Name') + ] + end + + let :expected_result do + <<~EOS + # == Schema Information + # + # Table name: users + # + # *id(ID)*:: integer, not null, primary key + # *name(Name)*:: string(50), not null + #-- + # == Schema Information End + #++ + EOS + end + + it 'returns schema info in RDoc format' do + is_expected.to eq expected_result + end + end + end + + context 'when "format_markdown" and "with_comment" are specified in options' do + subject do + AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX, format_markdown: true, with_comment: true) + end + + context 'when columns have comments' do + let :columns do + [ + mock_column(:id, :integer, comment: 'ID'), + mock_column(:name, :string, limit: 50, comment: 'Name') + ] + end + + let :expected_result do + <<~EOS + # == Schema Information + # + # Table name: `users` + # + # ### Columns + # + # Name | Type | Attributes + # ----------------- | ------------------ | --------------------------- + # **`id(ID)`** | `integer` | `not null, primary key` + # **`name(Name)`** | `string(50)` | `not null` + # + EOS + end + + it 'returns schema info in Markdown format' do + is_expected.to eq expected_result + end + end + + context 'when columns have multibyte comments' do + let :columns do + [ + mock_column(:id, :integer, comment: 'ID'), + mock_column(:name, :string, limit: 50, comment: 'NAME') + ] + end + + let :expected_result do + <<~EOS + # == Schema Information + # + # Table name: `users` + # + # ### Columns + # + # Name | Type | Attributes + # --------------------- | ------------------ | --------------------------- + # **`id(ID)`** | `integer` | `not null, primary key` + # **`name(NAME)`** | `string(50)` | `not null` + # + EOS + end + + it 'returns schema info in Markdown format' do + is_expected.to eq expected_result + end + end end end end