# frozen_string_literal: true package_require("ree_dao/wrappers/pg_jsonb") RSpec.describe 'ReeDao::PgJsonb' do link :build_mapper_factory, from: :ree_mapper link :build_mapper_strategy, from: :ree_mapper let(:mapper_factory) { build_mapper_factory( strategies: [ build_mapper_strategy(method: :cast), build_mapper_strategy(method: :serialize), build_mapper_strategy(method: :db_dump, dto: Hash), build_mapper_strategy(method: :db_load, dto: Hash, always_optional: true) ] ).register_wrapper(:pg_jsonb, ReeDao::PgJsonb) } let(:mapper) { mapper_factory.call.use(:db_dump).use(:db_load) do pg_jsonb? :payload do string :key end pg_jsonb? :numbers, array(integer) pg_jsonb? :figures, (array do string :coords end) pg_jsonb? :number, integer pg_jsonb? :boolean, bool pg_jsonb? :any, any pg_jsonb? :rational, rational end } describe '#db_dump' do it { expect(mapper.db_dump({ payload: { key: 'key' }, numbers: [1, 2], figures: [{ coords: 'x=1,y=1' }], number: 1, boolean: true, rational: Rational("1/3"), })).to eq({ payload: { key: 'key' }, numbers: [1, 2], figures: [{ coords: 'x=1,y=1' }], number: 1, boolean: true, rational: "1/3", }) } it { expect { mapper.db_dump({ numbers: ['1'] }) }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `\"1\"`/) } it { object = Object.new expect { mapper.db_dump({ any: object }) }.to raise_error(ReeMapper::TypeError, /`any` should be an jsonb primitive, got `#{object.inspect}`/) } end describe '#db_load' do it { expect(mapper.db_load({ payload: Sequel::Postgres::JSONBHash.new({ key: 'key' }), numbers: Sequel::Postgres::JSONBArray.new([1, 2]), figures: Sequel::Postgres::JSONBArray.new([{ coords: 'x=1,y=1' }]), number: 1, boolean: true, rational: "1/3" })).to eq({ payload: { key: 'key' }, numbers: [1, 2], figures: [{ coords: 'x=1,y=1' }], number: 1, boolean: true, rational: Rational("1/3"), }) } it { expect { mapper.db_load({ numbers: Sequel::Postgres::JSONBArray.new([1.1]) }) }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `1.1`/) } it { object = Object.new expect { mapper.db_load({ numbers: object }) }.to raise_error(ReeMapper::TypeError, /`numbers` should be a Sequel::Postgres::JSONB, got `#{object.inspect}`/) } end end