2017-12-10 23:05:11 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-05-30 00:58:26 -04:00
|
|
|
require "spec_helper"
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2015-11-17 23:59:35 -05:00
|
|
|
# The `json_versions` table tests postgres' `json` data type. So, that
|
2018-06-09 23:21:45 -04:00
|
|
|
# table is only created when testing against postgres.
|
2015-11-17 23:59:35 -05:00
|
|
|
if JsonVersion.table_exists?
|
2017-04-01 01:50:13 -04:00
|
|
|
RSpec.describe JsonVersion, type: :model do
|
|
|
|
it "includes the VersionConcern module" do
|
|
|
|
expect(described_class).to include(PaperTrail::VersionConcern)
|
2015-05-07 14:56:28 -04:00
|
|
|
end
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
describe "#where_object" do
|
|
|
|
it { expect(described_class).to respond_to(:where_object) }
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
it "escapes values" do
|
|
|
|
f = Fruit.create(name: "Bobby")
|
|
|
|
expect(
|
|
|
|
f.
|
|
|
|
versions.
|
|
|
|
where_object(name: "Robert'; DROP TABLE Students;--").
|
|
|
|
count
|
|
|
|
).to eq(0)
|
|
|
|
end
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
context "invalid arguments" do
|
|
|
|
it "raises an error" do
|
|
|
|
expect { described_class.where_object(:foo) }.to raise_error(ArgumentError)
|
|
|
|
expect { described_class.where_object([]) }.to raise_error(ArgumentError)
|
2015-05-06 22:29:39 -04:00
|
|
|
end
|
2018-06-09 23:21:45 -04:00
|
|
|
end
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
context "valid arguments", versioning: true do
|
|
|
|
it "locates versions according to their `object` contents" do
|
|
|
|
fruit = Fruit.create!(name: "apple")
|
|
|
|
expect(fruit.versions.length).to eq(1)
|
2018-12-04 16:10:35 -05:00
|
|
|
fruit.update!(name: "banana", color: "aqua")
|
2018-06-09 23:21:45 -04:00
|
|
|
expect(fruit.versions.length).to eq(2)
|
2018-12-04 16:10:35 -05:00
|
|
|
fruit.update!(name: "coconut", color: "black")
|
2018-06-09 23:21:45 -04:00
|
|
|
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
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
describe "#where_object_changes" do
|
|
|
|
it "escapes values" do
|
|
|
|
f = Fruit.create(name: "Bobby")
|
|
|
|
expect(
|
|
|
|
f.
|
|
|
|
versions.
|
|
|
|
where_object_changes(name: "Robert'; DROP TABLE Students;--").
|
|
|
|
count
|
|
|
|
).to eq(0)
|
|
|
|
end
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
context "invalid arguments" do
|
|
|
|
it "raises an error" do
|
|
|
|
expect { described_class.where_object_changes(:foo) }.to raise_error(ArgumentError)
|
|
|
|
expect { described_class.where_object_changes([]) }.to raise_error(ArgumentError)
|
|
|
|
end
|
|
|
|
end
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
context "valid arguments", versioning: true do
|
|
|
|
it "finds versions according to their `object_changes` contents" do
|
|
|
|
fruit = Fruit.create!(name: "apple")
|
2018-12-04 16:10:35 -05:00
|
|
|
fruit.update!(name: "banana", color: "red")
|
|
|
|
fruit.update!(name: "coconut", color: "green")
|
2018-06-09 23:21:45 -04:00
|
|
|
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
|
2015-05-06 22:29:39 -04:00
|
|
|
|
2018-06-09 23:21:45 -04:00
|
|
|
it "finds versions with multiple attributes changed" do
|
|
|
|
fruit = Fruit.create!(name: "apple")
|
2018-12-04 16:10:35 -05:00
|
|
|
fruit.update!(name: "banana", color: "red")
|
|
|
|
fruit.update!(name: "coconut", color: "green")
|
2018-06-09 23:21:45 -04:00
|
|
|
where_red_apple = fruit.versions.where_object_changes(color: "red", name: "apple")
|
|
|
|
expect(where_red_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->>'color' ILIKE '["red",%')
|
|
|
|
OR (object_changes->>'color' ILIKE '[%,"red"]%'))
|
|
|
|
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_red_apple).to match_array([fruit.versions[1]])
|
2015-05-06 22:29:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|