discourse/spec/components/migration/column_dropper_spec.rb
Sam Saffron 4ea21fa2d0 DEV: use #frozen_string_literal: true on all spec
This change both speeds up specs (less strings to allocate) and helps catch
cases where methods in Discourse are mutating inputs.

Overall we will be migrating everything to use #frozen_string_literal: true
it will take a while, but this is the first and safest move in this direction
2019-04-30 10:27:42 +10:00

128 lines
3.2 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
require_dependency 'migration/column_dropper'
RSpec.describe Migration::ColumnDropper do
def has_column?(table, column)
DB.exec(<<~SQL, table: table, column: column) == 1
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
table_schema = 'public' AND
table_name = :table AND
column_name = :column
SQL
end
describe ".execute_drop" do
let(:columns) { %w{junk junk2} }
before do
columns.each do |column|
DB.exec("ALTER TABLE topics ADD COLUMN #{column} int")
end
end
after do
columns.each do |column|
DB.exec("ALTER TABLE topics DROP COLUMN IF EXISTS #{column}")
end
end
it "drops the columns" do
Migration::ColumnDropper.execute_drop("topics", columns)
columns.each do |column|
expect(has_column?('topics', column)).to eq(false)
end
end
end
describe '.mark_readonly' do
let(:table_name) { "table_with_readonly_column" }
before do
DB.exec <<~SQL
CREATE TABLE #{table_name} (topic_id INTEGER, email TEXT);
INSERT INTO #{table_name} (topic_id, email)
VALUES (1, 'something@email.com');
SQL
Migration::ColumnDropper.mark_readonly(table_name, 'email')
end
after do
ActiveRecord::Base.connection.reset!
DB.exec <<~SQL
DROP TABLE IF EXISTS #{table_name};
DROP FUNCTION IF EXISTS #{Migration::BaseDropper.readonly_function_name(table_name, 'email')} CASCADE;
SQL
end
it 'should be droppable' do
Migration::ColumnDropper.execute_drop(table_name, ['email'])
expect(has_trigger?(Migration::BaseDropper.readonly_trigger_name(
table_name, 'email'
))).to eq(false)
expect(has_column?(table_name, 'email')).to eq(false)
end
it 'should prevent updates to the readonly column' do
begin
DB.exec <<~SQL
UPDATE #{table_name}
SET email = 'testing@email.com'
WHERE topic_id = 1;
SQL
rescue PG::RaiseException => e
[
"Discourse: email in #{table_name} is readonly",
'discourse_functions.raise_table_with_readonly_column_email_readonly()'
].each do |message|
expect(e.message).to include(message)
end
end
end
it 'should allow updates to the other columns' do
DB.exec <<~SQL
UPDATE #{table_name}
SET topic_id = 2
WHERE topic_id = 1
SQL
expect(
ActiveRecord::Base.exec_sql("SELECT * FROM #{table_name};").values
).to include([2, "something@email.com"])
end
it 'should prevent insertions to the readonly column' do
expect do
ActiveRecord::Base.connection.raw_connection.exec <<~SQL
INSERT INTO #{table_name} (topic_id, email)
VALUES (2, 'something@email.com');
SQL
end.to raise_error(
PG::RaiseException,
/Discourse: email in table_with_readonly_column is readonly/
)
end
it 'should allow insertions to the other columns' do
DB.exec <<~SQL
INSERT INTO #{table_name} (topic_id)
VALUES (2);
SQL
expect(
DB.query_single("SELECT topic_id FROM #{table_name} WHERE topic_id = 2")
).to eq([2])
end
end
end