# frozen_string_literal: true
require 'intranet/core'
require 'intranet/logger'
require 'intranet/abstract_responder'
require 'intranet/pictures/responder'
RSpec.describe Intranet::Pictures::Responder do
it 'should inherit from Intranet::AbstractResponder' do
expect(described_class.superclass).to eql(Intranet::AbstractResponder)
end
it 'should define its name, version and homepage' do
expect { described_class.module_name }.not_to raise_error
expect { described_class.module_version }.not_to raise_error
expect { described_class.module_homepage }.not_to raise_error
end
before do
logger = Intranet::Logger.new(Intranet::Logger::FATAL)
@core = Intranet::Core.new(logger)
@provider = Intranet::Pictures::JsonDbProvider.new(File.join(__dir__, 'sample-db.json'))
@responder = described_class.new(@provider)
@core.register_module(
@responder, ['pictures'], File.absolute_path('../../../lib/intranet/resources', __dir__)
)
end
describe '#in_menu?' do
it 'should return the value provided at initialization' do
expect(described_class.new(nil, [], [], false).in_menu?).to be false
expect(described_class.new(nil, [], [], true).in_menu?).to be true
end
end
describe '#resources_dir' do
it 'should return the absolute path of the resources directory' do
expect(described_class.new(nil, [], [], false).resources_dir).to eql(
File.absolute_path('../../../lib/intranet/resources', __dir__)
)
end
end
describe '#title' do
it 'should return the title of the webpage provided by the module' do
expect(@responder.title).to eql('My Gallery')
end
end
describe '#generate_page' do
context 'when asked for \'/index.html\'' do
it 'should return a partial HTML content showing recent groups according to configuration' do
# Nominal case with limit
recents = [{ 'group_by' => 'location', 'sort_by' => 'datetime', 'sort_order' => 'desc', 'limit' => 2 }]
@responder.instance_variable_set(:@recents, recents)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Nominal case with limit
recents = [{ 'group_by' => 'location', 'sort_by' => 'datetime', 'limit' => 2 }]
@responder.instance_variable_set(:@recents, recents)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Nominal case without limit
recents = [{ 'group_by' => 'location', 'sort_by' => 'location', 'sort_order' => 'desc' }]
@responder.instance_variable_set(:@recents, recents)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"#{I18n.t('pictures.recents.location')}
\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Incorrect recents specification
recents = [{ 'group_by' => 'invalid', 'sort_by' => 'location' }]
@responder.instance_variable_set(:@recents, recents)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
it 'should return a partial HTML content showing all groups according to configuration' do
# Nominal case without recents
home_groups = [{ 'group_by' => 'location', 'sort_by' => 'location',
'browse_group_by' => 'author' }]
@responder.instance_variable_set(:@home_groups, home_groups)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"#{I18n.t('pictures.browse_by.location')}
\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Nominal case with recents
recents = [{ 'group_by' => 'location', 'sort_by' => 'location', 'sort_order' => 'asc' }]
@responder.instance_variable_set(:@recents, recents)
home_groups = [{ 'group_by' => 'author', 'sort_by' => 'author', 'sort_order' => 'asc',
'browse_group_by' => 'location', 'browse_sort_by' => 'location', 'browse_sort_order' => 'desc' }]
@responder.instance_variable_set(:@home_groups, home_groups)
code, mime, content = @responder.generate_page('/index.html', {})
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"#{I18n.t('pictures.recents.location')}
\n" \
"\n" \
"#{I18n.t('pictures.browse_by.author')}
\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
end
end
context 'when asked for \'/browse.html\'' do
it 'should return a partial HTML content with selected pictures grouped as requested' do
# No selector nor sort order
query = { 'group_by' => 'author' }
code, mime, content = @responder.generate_page('/browse.html', query)
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Valid selector, valid sort order
query = { 'group_by' => 'location', 'author' => 'John Doe', 'sort_by' => 'location', 'sort_order' => 'desc' }
code, mime, content = @responder.generate_page('/browse.html', query)
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Invalid selector
query = { 'group_by' => 'location', 'foo' => 'bar' }
code, mime, content = @responder.generate_page('/browse.html', query)
expect(code).to eql(206)
expect(mime).to eql('text/html')
expect(content).to eql(
{
content: "\nMy Gallery
\n" \
"\n\n" \
"\n" \
"\n",
title: 'My Gallery',
stylesheets: [
'design/style.css',
'design/photoswipe/photoswipe.css',
'design/photoswipe/photoswipe-dynamic-caption-plugin.css'
],
scripts: [{ src: 'design/jpictures.js', type: 'module' }]
}
)
# Invalid grouping criteria
query = { 'group_by' => 'foo' }
code, mime, content = @responder.generate_page('/browse.html', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
# Invalid sorting criteria
query = { 'group_by' => 'location', 'sort_order' => 'foo' }
code, mime, content = @responder.generate_page('/browse.html', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
end
context 'when asked for \'/i18n.js\'' do
it 'should return the internationalized version of required JavaScript variables' do
code, mime, content = @responder.generate_page('/i18n.js', {})
expect(code).to eql(200)
expect(mime).to eql('text/javascript')
expect(content).to eql(
"export default {\n" \
" viewer_close: '#{I18n.t('pictures.viewer.close')}',\n" \
" viewer_zoom: '#{I18n.t('pictures.viewer.zoom')}',\n" \
" viewer_previous: '#{I18n.t('pictures.viewer.previous')}',\n" \
" viewer_next: '#{I18n.t('pictures.viewer.next')}' };"
)
end
end
context 'when asked for \'/api/group_thumbnail\'' do
it 'should return the selected group thumnail' do
# Existing group with thumbnail
query = { 'location' => 'New York, USA' }
code, mime, content = @responder.generate_page('/api/group_thumbnail', query)
expect(code).to eql(200)
expect(mime).to eql('image/png')
expect(content).to eql(File.read(File.join(__dir__, 'alpha.png')))
# Existing group with no specified thumbnail
query = { 'location' => 'Paris, France' }
code, mime, content = @responder.generate_page('/api/group_thumbnail', query)
expect(code).to eql(200)
expect(mime).to eql('image/svg+xml')
expect(content).to eql(
File.read(File.join(__dir__, '../../../lib/intranet/resources/www/group_thumbnail.svg'))
)
# Existing group with non-existant thumbnail
query = { 'author' => 'Jane Doe' }
code, mime, content = @responder.generate_page('/api/group_thumbnail', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
# Invalid query
query = { 'location' => 'Tokyo, Japan', 'camera' => 'Canon EOS 5D MARK IV' }
code, mime, content = @responder.generate_page('/api/group_thumbnail', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
end
context 'when asked for \'/api/group_brief\'' do
it 'should return the selected group brief text' do
# Existing group with brief text
query = { 'location' => 'Paris, France' }
code, mime, content = @responder.generate_page('/api/group_brief', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql('The City of Light'.to_json)
# Existing group with no brief text
query = { 'location' => 'Tokyo, Japan' }
code, mime, content = @responder.generate_page('/api/group_brief', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql(''.to_json)
# Invalid query
query = { 'location' => 'Tokyo, Japan', 'camera' => 'Canon EOS 5D MARK IV' }
code, mime, content = @responder.generate_page('/api/group_brief', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
end
context 'when asked for \'/api/pictures\'' do
it 'should return a JSON representation of the selected pictures' do
# All pictures (no selector nor sort order)
code, mime, content = @responder.generate_page('/api/pictures', {})
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql(
[
{ 'datetime' => '2019:07:22 09:41:31', 'author' => 'John Doe', 'location' => 'Paris, France', 'camera' => 'Apple iPhone 11' },
{ 'datetime' => '2020:06:19 07:51:05', 'flash' => false, 'author' => 'Jane Doe', 'location' => 'Tokyo, Japan' },
{ 'datetime' => '2020:06:20 18:14:09', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'New York, USA' },
{ 'datetime' => '2020:06:20 06:09:54', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'Paris, France', 'camera' => 'Canon EOS 5D MARK IV' },
{ 'datetime' => '2019:07:22 09:45:17', 'author' => 'John Doe', 'location' => 'Tokyo, Japan' }
].to_json
)
# Valid selector, no sort order
query = { 'author' => 'Jane Doe', 'flash' => true }
code, mime, content = @responder.generate_page('/api/pictures', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql(
[
{ 'datetime' => '2020:06:20 18:14:09', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'New York, USA' },
{ 'datetime' => '2020:06:20 06:09:54', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'Paris, France', 'camera' => 'Canon EOS 5D MARK IV' }
].to_json
)
# Valid selector, valid sort order
query = { 'author' => 'Jane Doe', 'flash' => true, 'sort_by' => 'datetime' }
code, mime, content = @responder.generate_page('/api/pictures', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql(
[
{ 'datetime' => '2020:06:20 06:09:54', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'Paris, France', 'camera' => 'Canon EOS 5D MARK IV' },
{ 'datetime' => '2020:06:20 18:14:09', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'New York, USA' }
].to_json
)
query = { 'author' => 'Jane Doe', 'flash' => true, 'sort_by' => 'location',
'sort_order' => 'desc' }
code, mime, content = @responder.generate_page('/api/pictures', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql(
[
{ 'datetime' => '2020:06:20 06:09:54', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'Paris, France', 'camera' => 'Canon EOS 5D MARK IV' },
{ 'datetime' => '2020:06:20 18:14:09', 'flash' => true, 'author' => 'Jane Doe', 'location' => 'New York, USA' }
].to_json
)
# Invalid selector
query = { 'a' => 'b' }
code, mime, content = @responder.generate_page('/api/pictures', query)
expect(code).to eql(200)
expect(mime).to eql('application/json')
expect(content).to eql([].to_json)
# Invalid sort order
query = { 'sort_order' => 'foo' }
code, mime, content = @responder.generate_page('/api/pictures', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
end
context 'when asked for \'/api/picture\'' do
it 'should return the selected picture' do
# Existing picture
query = { 'uri' => 'white.jpg' }
code, mime, content = @responder.generate_page('/api/picture', query)
expect(code).to eql(200)
expect(mime).to eql('image/jpeg')
expect(content).to eql(File.read(File.join(__dir__, 'white.jpg')))
# Invalid selector
query = { 'value' => true }
code, mime, content = @responder.generate_page('/api/picture', query)
expect(code).to eql(404)
expect(mime).to be_empty
expect(content).to be_empty
end
end
context 'otherwise' do
it 'should return an HTTP 404 error' do
expect(@responder.generate_page('index.html', {})).to eql([404, '', ''])
expect(@responder.generate_page('/api/groups', {})).to eql([404, '', ''])
expect(@responder.generate_page('/api/group', {})).to eql([404, '', ''])
expect(@responder.generate_page('/api/pictures/foo', {})).to eql([404, '', ''])
end
end
end
end