# frozen_string_literal: true require 'intranet/pictures/json_db_provider' RSpec.describe Intranet::Pictures::JsonDbProvider do describe '.initialize' do it 'should propagate the filesystem exceptions' do file = File.join(__dir__, 'non-existant.json') expect { described_class.new(file) }.to raise_error(Errno::ENOENT) end it 'should propagate the JSON parser exceptions (file format)' do file = __FILE__ expect { described_class.new(file) }.to raise_error(JSON::ParserError) end end describe '#title' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end it 'should return the gallery title' do expect(@provider.title).to eql('My Gallery') end end describe '#group_types' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end it 'should return the available group types' do expect(@provider.group_types).to eql(%w[group1 group2 group3]) end end describe '#list_groups' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end context 'given a valid +type+' do it 'should return the list of groups of the given +type+ without the +uri+ key' do expect(@provider.list_groups('group1')).to eql( [ { 'id' => 'group1_title1', 'title' => 'Group 1, Title 1', 'brief' => 'brief_text_1' }, { 'id' => 'group1_title2', 'title' => 'Group 1, Title 2' } ] ) expect(@provider.list_groups('group2')).to eql( [ { 'id' => 'group2_title1', 'title' => 'Group 2, Title 1', 'value' => 'abcd' }, { 'id' => 'group2_title2', 'title' => 'Group 2, Title 2', 'value' => 'bcde', 'brief' => 'brief_text_2' }, { 'id' => 'group2_title3', 'title' => 'Group 2, Title 3', 'value' => 'aabb' } ] ) expect(@provider.list_groups('group3')).to eql( [ { 'id' => 'group3_title1', 'title' => 'Group 3, Title 1' }, { 'id' => 'group3_title2', 'title' => 'Group 3, Title 2' } ] ) end it 'should return only the groups matching the given +selector+' do selector = { 'group1' => 'group1_title1' } expect(@provider.list_groups('group2', selector)).to eql( [ { 'id' => 'group2_title2', 'title' => 'Group 2, Title 2', 'value' => 'bcde', 'brief' => 'brief_text_2' }, { 'id' => 'group2_title3', 'title' => 'Group 2, Title 3', 'value' => 'aabb' } ] ) selector = { 'uri' => 'white.jpg' } expect(@provider.list_groups('group1', selector)).to eql( [ { 'id' => 'group1_title1', 'title' => 'Group 1, Title 1', 'brief' => 'brief_text_1' } ] ) selector = { 'group1' => 'group1_title2', 'value' => true } expect(@provider.list_groups('group2', selector)).to eql( [ { 'id' => 'group2_title1', 'title' => 'Group 2, Title 1', 'value' => 'abcd' }, { 'id' => 'group2_title3', 'title' => 'Group 2, Title 3', 'value' => 'aabb' } ] ) selector = { 'group2' => 'group2_title2', 'value' => false } expect(@provider.list_groups('group2', selector)).to eql( [ { 'id' => 'group2_title2', 'title' => 'Group 2, Title 2', 'value' => 'bcde', 'brief' => 'brief_text_2' } ] ) selector = { 'value' => true } expect(@provider.list_groups('group3', selector)).to eql( [ { 'id' => 'group3_title2', 'title' => 'Group 3, Title 2' } ] ) selector = { 'group4' => 'foo_bar_boz' } # referencing undefined fields expect(@provider.list_groups('group2', selector)).to eql([]) end end context 'given an invalid +type+' do it 'should raise KeyError' do expect { @provider.list_groups('invalid') }.to raise_error(KeyError) end end context 'given a valid +sort_by+ key' do it 'should sort the groups by the given key' do expect(@provider.list_groups('group1', {}, 'title', false)).to eql( [ { 'id' => 'group1_title2', 'title' => 'Group 1, Title 2' }, { 'id' => 'group1_title1', 'title' => 'Group 1, Title 1', 'brief' => 'brief_text_1' } ] ) expect(@provider.list_groups('group2', {}, 'value')).to eql( [ { 'id' => 'group2_title3', 'title' => 'Group 2, Title 3', 'value' => 'aabb' }, { 'id' => 'group2_title1', 'title' => 'Group 2, Title 1', 'value' => 'abcd' }, { 'id' => 'group2_title2', 'title' => 'Group 2, Title 2', 'value' => 'bcde', 'brief' => 'brief_text_2' } ] ) end end context 'given an invalid +sort_by+ key' do it 'should raise KeyError' do expect { @provider.list_groups('group1', {}, 'invalid') }.to raise_error(KeyError) end end end describe '#list_pictures' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end it 'should return the list of pictures without the uri key' do expect(@provider.list_pictures).to eql( [ { 'datetime' => '2019:07:22 09:41:31', 'group1' => 'group1_title1', 'group2' => 'group2_title2', 'group3' => 'group3_title1' }, { 'datetime' => '2020:06:19 07:51:05', 'value' => false, 'group1' => 'group1_title2', 'group2' => 'group2_title2' }, { 'datetime' => '2020:06:20 18:14:09', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title1' }, { 'datetime' => '2020:06:20 06:09:54', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title3', 'group3' => 'group3_title2' }, { 'datetime' => '2019:07:22 09:45:17', 'group1' => 'group1_title1', 'group2' => 'group2_title3' } ] ) end it 'should return only the pictures matching the given selector' do selector = { 'group1' => 'group1_title2' } expect(@provider.list_pictures(selector)).to eql( [ { 'datetime' => '2020:06:19 07:51:05', 'value' => false, 'group1' => 'group1_title2', 'group2' => 'group2_title2' }, { 'datetime' => '2020:06:20 18:14:09', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title1' }, { 'datetime' => '2020:06:20 06:09:54', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title3', 'group3' => 'group3_title2' } ] ) end context 'given a valid +sort_by+ key' do it 'should sort the pictures by the given key' do selector = { 'group1' => 'group1_title2' } expect(@provider.list_pictures(selector, 'group2')).to eql( [ { 'datetime' => '2020:06:20 18:14:09', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title1' }, { 'datetime' => '2020:06:19 07:51:05', 'value' => false, 'group1' => 'group1_title2', 'group2' => 'group2_title2' }, { 'datetime' => '2020:06:20 06:09:54', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title3', 'group3' => 'group3_title2' } ] ) expect(@provider.list_pictures(selector, 'datetime', false)).to eql( [ { 'datetime' => '2020:06:20 18:14:09', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title1' }, { 'datetime' => '2020:06:20 06:09:54', 'value' => true, 'group1' => 'group1_title2', 'group2' => 'group2_title3', 'group3' => 'group3_title2' }, { 'datetime' => '2020:06:19 07:51:05', 'value' => false, 'group1' => 'group1_title2', 'group2' => 'group2_title2' } ] ) end end context 'given an invalid +sort_by+ key' do it 'should raise KeyError' do expect { @provider.list_pictures({}, 'invalid') }.to raise_error(KeyError) end end end describe '#picture' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end context 'when +selector+ matches exactly one picture, with +uri+ pointing to a valid image file' do it 'should return the file mime type and content' do selector = { 'uri' => 'white.jpg' } expect(@provider.picture(selector)).to eql( ['image/jpeg', File.read(File.join(__dir__, 'white.jpg'))] ) selector = { 'uri' => './alpha.png' } expect(@provider.picture(selector)).to eql( ['image/png', File.read(File.join(__dir__, 'alpha.png'))] ) end end context 'when +selector+ matches exactly one picture, with a +uri+ pointing to a non-existing file' do it 'should raise KeyError' do selector = { 'uri' => 'pic3.jpg' } expect { @provider.picture(selector) }.to raise_error(KeyError) end end context 'when +selector+ matches exactly one picture, with a +uri+ pointing to a non-image file' do it 'should raise KeyError' do selector = { 'uri' => 'sample-db.json' } expect { @provider.picture(selector) }.to raise_error(KeyError) end end context 'when +selector+ matches exactly one picture, with +uri+ not defined' do it 'should raise KeyError' do selector = { 'datetime' => '2019:07:22 09:45:17' } expect { @provider.picture(selector) }.to raise_error(KeyError) end end context 'when +selector+ matches zero or more than one picture' do it 'should raise KeyError' do selector = { 'group1' => 'group1_title2' } expect { @provider.picture(selector) }.to raise_error(KeyError) selector = { 'uri' => 'black.jpg' } expect { @provider.picture(selector) }.to raise_error(KeyError) end end end describe '#group_thumbnail' do before do @provider = described_class.new(File.join(__dir__, 'sample-db.json')) end context 'when +selector+ matches exactly one group, with +uri+ pointing to a valid image file' do it 'should return the thumbnail file mime type and content' do selector = { 'group1' => 'group1_title1' } expect(@provider.group_thumbnail('group1', selector)).to eql( ['image/jpeg', File.read(File.join(__dir__, 'white.jpg'))] ) selector = { 'uri' => 'pic3.jpg' } expect(@provider.group_thumbnail('group2', selector)).to eql( ['image/png', File.read(File.join(__dir__, 'alpha.png'))] ) end end context 'when +selector+ matches exactly one group, with a +uri+ pointing to a non-existing file' do it 'should raise KeyError' do selector = { 'group1' => 'group1_title2' } expect { @provider.group_thumbnail('group1', selector) }.to raise_error(KeyError) end end context 'when +selector+ matches exactly one group, with +uri+ not defined' do it 'should return nil' do selector = { 'group2' => 'group2_title2' } expect(@provider.group_thumbnail('group2', selector)).to be_nil end end context 'when +selector+ matches zero or more than one group' do it 'should raise KeyError' do selector = { 'group1' => 'invalid' } expect { @provider.group_thumbnail('group1', selector) }.to raise_error(KeyError) selector = { 'value' => true } expect { @provider.group_thumbnail('group2', selector) }.to raise_error(KeyError) end end end end