1# frozen_string_literal: true 2 3require 'fast_spec_helper' 4require_relative '../../../../rubocop/cop/migration/add_limit_to_text_columns' 5 6RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do 7 subject(:cop) { described_class.new } 8 9 context 'when in migration' do 10 let(:msg) { 'Text columns should always have a limit set (255 is suggested)[...]' } 11 12 before do 13 allow(cop).to receive(:in_migration?).and_return(true) 14 allow(cop).to receive(:version).and_return(described_class::TEXT_LIMIT_ATTRIBUTE_ALLOWED_SINCE + 5) 15 end 16 17 context 'when text columns are defined without a limit' do 18 it 'registers an offense' do 19 expect_offense(<<~RUBY) 20 class TestTextLimits < ActiveRecord::Migration[6.0] 21 disable_ddl_transaction! 22 23 def up 24 create_table :test_text_limits, id: false do |t| 25 t.integer :test_id, null: false 26 t.text :name 27 ^^^^ #{msg} 28 end 29 30 create_table :test_text_limits_create do |t| 31 t.integer :test_id, null: false 32 t.text :title 33 t.text :description 34 ^^^^ #{msg} 35 36 t.text_limit :title, 100 37 end 38 39 add_column :test_text_limits, :email, :text 40 ^^^^^^^^^^ #{msg} 41 42 add_column_with_default :test_text_limits, :role, :text, default: 'default' 43 ^^^^^^^^^^^^^^^^^^^^^^^ #{msg} 44 45 change_column_type_concurrently :test_text_limits, :test_id, :text 46 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} 47 end 48 end 49 RUBY 50 end 51 end 52 53 context 'when text columns are defined with a limit' do 54 it 'registers no offense' do 55 expect_no_offenses(<<~RUBY) 56 class TestTextLimits < ActiveRecord::Migration[6.0] 57 disable_ddl_transaction! 58 59 def up 60 create_table :test_text_limits, id: false do |t| 61 t.integer :test_id, null: false 62 t.text :name 63 end 64 65 create_table :test_text_limits_create do |t| 66 t.integer :test_id, null: false 67 t.text :title, limit: 100 68 t.text :description, limit: 255 69 end 70 71 add_column :test_text_limits, :email, :text 72 add_column_with_default :test_text_limits, :role, :text, default: 'default' 73 change_column_type_concurrently :test_text_limits, :test_id, :text 74 75 add_text_limit :test_text_limits, :name, 255 76 add_text_limit :test_text_limits, :email, 255 77 add_text_limit :test_text_limits, :role, 255 78 add_text_limit :test_text_limits, :test_id, 255 79 end 80 end 81 RUBY 82 end 83 84 context 'for migrations before 2021_09_10_00_00_00' do 85 it 'when limit: attribute is used (which is not supported yet for this version): registers an offense' do 86 allow(cop).to receive(:version).and_return(described_class::TEXT_LIMIT_ATTRIBUTE_ALLOWED_SINCE - 5) 87 88 expect_offense(<<~RUBY) 89 class TestTextLimits < ActiveRecord::Migration[6.0] 90 def up 91 create_table :test_text_limit_attribute do |t| 92 t.integer :test_id, null: false 93 t.text :name, limit: 100 94 ^^^^ Text columns should always have a limit set (255 is suggested). Using limit: is not supported in this version. You can add a limit to a `text` column by using `add_text_limit` or `.text_limit` inside `create_table` 95 end 96 97 create_table_with_constraints :test_text_limit_attribute do |t| 98 t.integer :test_id, null: false 99 t.text :name, limit: 100 100 ^^^^ Text columns should always have a limit set (255 is suggested). Using limit: is not supported in this version. You can add a limit to a `text` column by using `add_text_limit` or `.text_limit` inside `create_table` 101 end 102 end 103 end 104 RUBY 105 end 106 end 107 end 108 109 context 'when text array columns are defined without a limit' do 110 it 'registers no offense' do 111 expect_no_offenses(<<~RUBY) 112 class TestTextLimits < ActiveRecord::Migration[6.0] 113 def up 114 create_table :test_text_limits, id: false do |t| 115 t.integer :test_id, null: false 116 t.text :name, array: true, default: [], null: false 117 end 118 119 add_column :test_text_limits, :email, :text, array: true 120 add_column_with_default :test_text_limits, :role, :text, default: [], array: true 121 change_column_type_concurrently :test_text_limits, :test_id, :text, array: true 122 end 123 end 124 RUBY 125 end 126 end 127 128 # Make sure that the cop is properly checking for an `add_text_limit` 129 # over the same {table, attribute} as the one that triggered the offense 130 context 'when the limit is defined for a same name attribute but different table' do 131 it 'registers an offense' do 132 expect_offense(<<~RUBY) 133 class TestTextLimits < ActiveRecord::Migration[6.0] 134 disable_ddl_transaction! 135 136 def up 137 create_table :test_text_limits, id: false do |t| 138 t.integer :test_id, null: false 139 t.text :name 140 ^^^^ #{msg} 141 end 142 143 add_column :test_text_limits, :email, :text 144 ^^^^^^^^^^ #{msg} 145 146 add_column_with_default :test_text_limits, :role, :text, default: 'default' 147 ^^^^^^^^^^^^^^^^^^^^^^^ #{msg} 148 149 change_column_type_concurrently :test_text_limits, :test_id, :text 150 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} 151 152 add_text_limit :wrong_table, :name, 255 153 add_text_limit :wrong_table, :email, 255 154 add_text_limit :wrong_table, :role, 255 155 add_text_limit :wrong_table, :test_id, 255 156 end 157 end 158 RUBY 159 end 160 end 161 162 context 'when text columns are used for encryption' do 163 it 'registers no offenses' do 164 expect_no_offenses(<<~RUBY) 165 class TestTextLimits < ActiveRecord::Migration[6.0] 166 disable_ddl_transaction! 167 168 def up 169 create_table :test_text_limits, id: false do |t| 170 t.integer :test_id, null: false 171 t.text :encrypted_name 172 end 173 174 add_column :encrypted_test_text_limits, :encrypted_email, :text 175 add_column_with_default :encrypted_test_text_limits, :encrypted_role, :text, default: 'default' 176 change_column_type_concurrently :encrypted_test_text_limits, :encrypted_test_id, :text 177 end 178 end 179 RUBY 180 end 181 end 182 183 context 'on down' do 184 it 'registers no offense' do 185 expect_no_offenses(<<~RUBY) 186 class TestTextLimits < ActiveRecord::Migration[6.0] 187 def up 188 drop_table :no_offense_on_down 189 end 190 191 def down 192 create_table :no_offense_on_down, id: false do |t| 193 t.integer :test_id, null: false 194 t.text :name 195 end 196 197 add_column :no_offense_on_down, :email, :text 198 199 add_column_with_default :no_offense_on_down, :role, :text, default: 'default' 200 end 201 end 202 RUBY 203 end 204 end 205 end 206 207 context 'when outside of migration' do 208 it 'registers no offense' do 209 expect_no_offenses(<<~RUBY) 210 class TestTextLimits < ActiveRecord::Migration[6.0] 211 disable_ddl_transaction! 212 213 def up 214 create_table :test_text_limits, id: false do |t| 215 t.integer :test_id, null: false 216 t.text :name 217 end 218 219 add_column :test_text_limits, :email, :text 220 add_column_with_default :test_text_limits, :role, :text, default: 'default' 221 change_column_type_concurrently :test_text_limits, :test_id, :text 222 end 223 end 224 RUBY 225 end 226 end 227end 228