Testing YAML Serialization Implementation in PaperTrail
This test suite validates the YAML serialization functionality in PaperTrail’s implementation, focusing on data serialization and deserialization methods. It ensures proper handling of Ruby objects when converting to and from YAML format while maintaining data integrity and security considerations.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
paper-trail-gem/paper_trail
spec/paper_trail/serializers/yaml_spec.rb
# frozen_string_literal: true
require "spec_helper"
module PaperTrail
module Serializers
::RSpec.describe(YAML, versioning: true) do
let(:array) { ::Array.new(10) { ::FFaker::Lorem.word } }
let(:hash) {
{
alice: "bob",
binary: 0xdeadbeef,
octal_james_bond: 0o7,
int: 42,
float: 4.2
}
}
let(:hash_with_indifferent_access) { HashWithIndifferentAccess.new(hash) }
describe ".load" do
it "deserializes YAML to Ruby" do
expect(described_class.load(hash.to_yaml)).to eq(hash)
expect(described_class.load(array.to_yaml)).to eq(array)
end
it "calls the expected load method based on Psych version" do
# `use_yaml_unsafe_load` was added in 5.2.8.1, 6.0.5.1, 6.1.6.1, and 7.0.3.1
if rails_supports_safe_load?
allow(::YAML).to receive(:safe_load)
described_class.load("string")
expect(::YAML).to have_received(:safe_load)
# Psych 4+ implements .unsafe_load
elsif ::YAML.respond_to?(:unsafe_load)
allow(::YAML).to receive(:unsafe_load)
described_class.load("string")
expect(::YAML).to have_received(:unsafe_load)
else # Psych < 4
allow(::YAML).to receive(:load)
described_class.load("string")
expect(::YAML).to have_received(:load)
end
end
end
describe ".dump" do
it "serializes Ruby to YAML" do
expect(described_class.dump(hash)).to eq(hash.to_yaml)
expect(described_class.dump(hash_with_indifferent_access)).
to eq(hash.stringify_keys.to_yaml)
expect(described_class.dump(array)).to eq(array.to_yaml)
end
end
describe ".where_object" do
it "constructs the correct WHERE query" do
matches = described_class.where_object_condition(
::PaperTrail::Version.arel_table[:object], :arg1, "Val 1"
)
expect(matches.instance_of?(Arel::Nodes::Matches)).to(eq(true))
expect(arel_value(matches.right)).to eq("%\narg1: Val 1\n%")
end
end
private
def rails_supports_safe_load?
# Rails 7.0.3.1 onwards will always support YAML safe loading
return true if ::ActiveRecord.gem_version >= Gem::Version.new("7.0.3.1")
# Older Rails versions may or may not, depending on whether they have been patched.
defined?(ActiveRecord::Base.use_yaml_unsafe_load)
end
end
end
end