1
0
Fork 0
mirror of https://github.com/paper-trail-gem/paper_trail.git synced 2022-11-09 11:33:19 -05:00

Merge pull request #1111 from paper-trail-gem/json_version_spec

Various improvements to json_version_spec
This commit is contained in:
Jared Beck 2018-06-10 13:37:44 -04:00 committed by GitHub
commit 9c5e28f759
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 81 deletions

View file

@ -124,7 +124,7 @@ class SetUpTestTables < (
end end
add_index :post_versions, %i[item_type item_id] add_index :post_versions, %i[item_type item_id]
if ENV["DB"] == "postgres" && ::ActiveRecord::VERSION::MAJOR >= 4 if ENV["DB"] == "postgres"
create_table :json_versions, force: true do |t| create_table :json_versions, force: true do |t|
t.string :item_type, null: false t.string :item_type, null: false
t.integer :item_id, null: false t.integer :item_id, null: false

View file

@ -3,99 +3,120 @@
require "spec_helper" require "spec_helper"
# The `json_versions` table tests postgres' `json` data type. So, that # The `json_versions` table tests postgres' `json` data type. So, that
# table is only created when testing against postgres and ActiveRecord >= 4. # table is only created when testing against postgres.
if JsonVersion.table_exists? if JsonVersion.table_exists?
RSpec.describe JsonVersion, type: :model do RSpec.describe JsonVersion, type: :model do
it "includes the VersionConcern module" do it "includes the VersionConcern module" do
expect(described_class).to include(PaperTrail::VersionConcern) expect(described_class).to include(PaperTrail::VersionConcern)
end end
describe "Methods" do describe "#where_object" do
describe "Class" do it { expect(described_class).to respond_to(:where_object) }
describe "#where_object" do
it { expect(described_class).to respond_to(:where_object) }
it "escapes values" do it "escapes values" do
f = Fruit.create(name: "Bobby") f = Fruit.create(name: "Bobby")
expect( expect(
f. f.
versions. versions.
where_object(name: "Robert'; DROP TABLE Students;--"). where_object(name: "Robert'; DROP TABLE Students;--").
count count
).to eq(0) ).to eq(0)
end end
context "invalid arguments" do context "invalid arguments" do
it "raises an error" do it "raises an error" do
expect { described_class.where_object(:foo) }.to raise_error(ArgumentError) expect { described_class.where_object(:foo) }.to raise_error(ArgumentError)
expect { described_class.where_object([]) }.to raise_error(ArgumentError) expect { described_class.where_object([]) }.to raise_error(ArgumentError)
end end
end end
context "valid arguments", versioning: true do context "valid arguments", versioning: true do
let(:fruit_names) { %w[apple orange lemon banana lime coconut strawberry blueberry] } it "locates versions according to their `object` contents" do
let(:fruit) { Fruit.new } fruit = Fruit.create!(name: "apple")
let(:name) { "pomegranate" } expect(fruit.versions.length).to eq(1)
let(:color) { FFaker::Color.name } fruit.update_attributes!(name: "banana", color: "aqua")
expect(fruit.versions.length).to eq(2)
fruit.update_attributes!(name: "coconut", color: "black")
expect(fruit.versions.length).to eq(3)
where_apple = described_class.where_object(name: "apple")
expect(where_apple.to_sql).to eq(
<<-SQL.squish
SELECT "json_versions".*
FROM "json_versions"
WHERE (object->>'name' = 'apple')
SQL
)
expect(where_apple).to eq([fruit.versions[1]])
expect(
described_class.where_object(color: "aqua")
).to eq([fruit.versions[2]])
end
end
end
before do describe "#where_object_changes" do
fruit.update_attributes!(name: name) it "escapes values" do
fruit.update_attributes!(name: fruit_names.sample, color: color) f = Fruit.create(name: "Bobby")
fruit.update_attributes!(name: fruit_names.sample, color: FFaker::Color.name) expect(
end f.
versions.
where_object_changes(name: "Robert'; DROP TABLE Students;--").
count
).to eq(0)
end
it "locates versions according to their `object` contents" do context "invalid arguments" do
expect(described_class.where_object(name: name)).to eq([fruit.versions[1]]) it "raises an error" do
expect(described_class.where_object(color: color)).to eq([fruit.versions[2]]) expect { described_class.where_object_changes(:foo) }.to raise_error(ArgumentError)
end expect { described_class.where_object_changes([]) }.to raise_error(ArgumentError)
end end
end
context "valid arguments", versioning: true do
it "finds versions according to their `object_changes` contents" do
fruit = Fruit.create!(name: "apple")
fruit.update_attributes!(name: "banana", color: "red")
fruit.update_attributes!(name: "coconut", color: "green")
where_apple = fruit.versions.where_object_changes(name: "apple")
expect(where_apple.to_sql.squish).to eq(
<<-SQL.squish
SELECT "json_versions".*
FROM "json_versions"
WHERE "json_versions"."item_id" = #{fruit.id}
AND "json_versions"."item_type" = 'Fruit'
AND
(((object_changes->>'name' ILIKE '["apple",%')
OR (object_changes->>'name' ILIKE '[%,"apple"]%')))
ORDER BY "json_versions"."created_at" ASC,
"json_versions"."id" ASC
SQL
)
expect(where_apple).to match_array(fruit.versions[0..1])
expect(
fruit.versions.where_object_changes(color: "red")
).to match_array(fruit.versions[1..2])
end end
describe "#where_object_changes" do it "finds versions with multiple attributes changed" do
it { expect(described_class).to respond_to(:where_object_changes) } fruit = Fruit.create!(name: "apple")
fruit.update_attributes!(name: "banana", color: "red")
it "escapes values" do fruit.update_attributes!(name: "coconut", color: "green")
f = Fruit.create(name: "Bobby") where_red_apple = fruit.versions.where_object_changes(color: "red", name: "apple")
expect( expect(where_red_apple.to_sql.squish).to eq(
f. <<-SQL.squish
versions. SELECT "json_versions".*
where_object_changes(name: "Robert'; DROP TABLE Students;--"). FROM "json_versions"
count WHERE "json_versions"."item_id" = #{fruit.id}
).to eq(0) AND "json_versions"."item_type" = 'Fruit'
end AND (((object_changes->>'color' ILIKE '["red",%')
OR (object_changes->>'color' ILIKE '[%,"red"]%'))
context "invalid arguments" do and ((object_changes->>'name' ILIKE '["apple",%')
it "raises an error" do OR (object_changes->>'name' ILIKE '[%,"apple"]%')))
expect { described_class.where_object_changes(:foo) }.to raise_error(ArgumentError) ORDER BY "json_versions"."created_at" ASC,
expect { described_class.where_object_changes([]) }.to raise_error(ArgumentError) "json_versions"."id" ASC
end SQL
end )
expect(where_red_apple).to match_array([fruit.versions[1]])
context "valid arguments", versioning: true do
let(:color) { %w[red green] }
let(:fruit) { Fruit.create!(name: name[0]) }
let(:name) { %w[banana kiwi mango] }
before do
fruit.update_attributes!(name: name[1], color: color[0])
fruit.update_attributes!(name: name[2], color: color[1])
end
it "finds versions according to their `object_changes` contents" do
expect(
fruit.versions.where_object_changes(name: name[0])
).to match_array(fruit.versions[0..1])
expect(
fruit.versions.where_object_changes(color: color[0])
).to match_array(fruit.versions[1..2])
end
it "finds versions with multiple attributes changed" do
expect(
fruit.versions.where_object_changes(color: color[0], name: name[0])
).to match_array([fruit.versions[1]])
end
end
end end
end end
end end