Skip to content

Commit

Permalink
Merge pull request #29 from sul-dlss/v3-image_resource-tests
Browse files Browse the repository at this point in the history
V3 resource and image_resource tests improved
  • Loading branch information
jmartin-sul authored Jul 25, 2017
2 parents 74eb138 + 7d6f96a commit 7164dc7
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 29 deletions.
9 changes: 8 additions & 1 deletion lib/iiif/v3/abstract_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ def validate
end
end

self.uri_only_keys.each do |k|
if self[k]
vals = *self[k]
vals.each { |val| validate_uri(val, k) }
end
end

# Note: self.define_methods_for_xxx_only_keys provides some validation at assignment time
# currently, there is NO validation when key values are assigned directly with hash syntax,
# e.g. my_image_resource['format'] = 'image/jpeg'
Expand Down Expand Up @@ -494,7 +501,7 @@ def define_accessor_methods(*keys, &validation)
private
def validate_uri(val, key)
unless val.kind_of?(String) && val =~ URI::regexp
m = "#{key} value must be a String containing a URI"
m = "#{key} value must be a String containing a URI for #{self.class}"
raise IIIF::V3::Presentation::IllegalValueError, m
end
end
Expand Down
12 changes: 4 additions & 8 deletions lib/iiif/v3/presentation/image_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,17 @@ module V3
module Presentation
class ImageResource < Resource

TYPE = 'Image'

def int_only_keys
super + %w{ width height }
end
TYPE = 'Image'.freeze

def initialize(hsh={})
hsh['type'] = TYPE unless hsh.has_key? 'type'
super(hsh)
end

class << self
IMAGE_API_DEFAULT_PARAMS = '/full/!200,200/0/default.jpg'
IMAGE_API_CONTEXT = 'http://iiif.io/api/image/2/context.json'
DEFAULT_FORMAT = 'image/jpeg'
IMAGE_API_DEFAULT_PARAMS = '/full/!200,200/0/default.jpg'.freeze
IMAGE_API_CONTEXT = 'http://iiif.io/api/image/2/context.json'.freeze
DEFAULT_FORMAT = 'image/jpeg'.freeze
# Create a new ImageResource that includes a IIIF Image API Service
# See http://iiif.io/api/presentation/2.0/#image-resources
#
Expand Down
19 changes: 14 additions & 5 deletions lib/iiif/v3/presentation/resource.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
module IIIF
module V3
module Presentation
# class for generic content resource
class Resource < IIIF::V3::AbstractResource

def required_keys
%w{ id }
super + %w{ id }
end

def string_only_keys
super + %w{ format }
def prohibited_keys
super + PAGING_PROPERTIES + %w{ nav_date viewing_direction start_canvas content_annotations}
end

def numeric_only_keys
super + %w{ duration }
def uri_only_keys
super + %w{ id }
end

def validate
super

unless self['id'] =~ /^https?:/
err_msg = "id must be an http(s) URI for #{self.class}"
raise IIIF::V3::Presentation::IllegalValueError, err_msg
end
end
end
end
end
Expand Down
6 changes: 5 additions & 1 deletion lib/iiif/v3/presentation/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ def required_keys

def prohibited_keys
super + CONTENT_RESOURCE_PROPERTIES + PAGING_PROPERTIES +
%w{ nav_date viewing_direction start_canvas content_annotation }
%w{ nav_date viewing_direction start_canvas content_annotations }
end

def uri_only_keys
super + %w{ @context id @id }
end

def any_type_keys
super + %w{ profile }
end

def validate
super
if IIIF_IMAGE_V2_CONTEXT == self['@context']
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/iiif/v3/abstract_resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def legal_viewing_hint_values
end
it 'raises IllegalValueError for entry with "id" that is not URI' do
subject['rights'] = [{ 'id' => 'bar', 'format' => 'text/html' }]
exp_err_msg = "id value must be a String containing a URI"
exp_err_msg = "id value must be a String containing a URI for #{subject.class}"
expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
end
it 'raises IllegalValueError for entry that does not contain "id"' do
Expand Down Expand Up @@ -179,7 +179,7 @@ def legal_viewing_hint_values
describe 'startCanvas' do
it 'raises IllegalValueError for entry that is not URI' do
subject.startCanvas = 'foo'
exp_err_msg = "startCanvas value must be a String containing a URI"
exp_err_msg = "startCanvas value must be a String containing a URI for #{subject.class}"
expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
end
end
Expand Down
184 changes: 181 additions & 3 deletions spec/unit/iiif/v3/presentation/image_resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,186 @@
end
end

describe "#{described_class}.int_only_keys" do
it_behaves_like 'it has the appropriate methods for integer-only keys v3'
end
describe 'realistic examples' do
let(:img_id) { 'https://example.org/image/iiif/abc666' }
let(:image_v2_service) {
IIIF::V3::Presentation::Service.new(
'@context' => 'http://iiif.io/api/image/2/context.json',
'@id' => img_id,
'id' => img_id,
'profile' => 'http://iiif.io/api/image/2/level1.json'
)
}
let(:img_mimetype) { 'image/jpeg' }
let(:width) { 999 }
let(:height) { 666 }
describe 'stanford' do
describe 'thumbnail per purl code' do
let(:thumb_id) { "#{img_id}/full/!400,400/0/default.jpg" }
let(:thumb_object) {
thumb = IIIF::V3::Presentation::ImageResource.new
thumb['type'] = 'Image'
thumb['id'] = thumb_id
thumb.format = img_mimetype
thumb.service = image_v2_service
thumb
}
it 'validates' do
expect{thumb_object.validate}.not_to raise_error
end
it 'has expected required values' do
expect(thumb_object.type).to eq 'Image'
expect(thumb_object.id).to eq thumb_id
end
it 'has expected additional values' do
expect(thumb_object.format).to eq img_mimetype
expect(thumb_object.service).to eq image_v2_service
end
end
describe 'full size per purl code' do
let(:full_id) { "#{img_id}/full/full/0/default.jpg" }
let(:image_object) {
img = IIIF::V3::Presentation::ImageResource.new
img['id'] = full_id
img.format = img_mimetype
img.height = height
img.width = width
img.service = image_v2_service
img
}
describe 'world visible' do
it 'validates' do
expect{image_object.validate}.not_to raise_error
end
it 'has expected required values' do
expect(image_object.type).to eq 'Image'
expect(image_object.id).to eq full_id
end
it 'has expected additional values' do
expect(image_object.format).to eq img_mimetype
expect(image_object.height).to eq height
expect(image_object.width).to eq width
expect(image_object.service).to eq image_v2_service
end
it 'has expected service value' do
img_service_obj = image_object.service
expect(img_service_obj.class).to eq IIIF::V3::Presentation::Service
expect(img_service_obj.keys.size).to eq 4
expect(img_service_obj.id).to eq img_id
expect(img_service_obj['@id']).to eq img_id
expect(img_service_obj.profile).to eq IIIF::V3::Presentation::Service::IIIF_IMAGE_V2_LEVEL1_PROFILE
expect(img_service_obj['@context']).to eq IIIF::V3::Presentation::Service::IIIF_IMAGE_V2_CONTEXT
end
end
describe 'requires login' do
let(:service_label) { 'login message' }
let(:token_service_id) { 'https://example.org/iiif/token' }
let(:login_service) {
IIIF::V3::Presentation::Service.new(
'id' => 'https://example.org/auth/iiif',
'profile' => 'http://iiif.io/api/auth/1/login',
'label' => service_label,
'service' => [{
'id' => token_service_id,
'profile' => 'http://iiif.io/api/auth/1/token'
}]
)
}
let(:image_object_w_login) {
img = image_object
img.service['service'] = [login_service]
img
}
it 'validates' do
expect{image_object_w_login.validate}.not_to raise_error
end
it 'has expected service value' do
img_service_obj = image_object_w_login.service
expect(img_service_obj.class).to eq IIIF::V3::Presentation::Service
expect(img_service_obj.keys.size).to eq 5
expect(img_service_obj.id).to eq img_id
expect(img_service_obj['@id']).to eq img_id
expect(img_service_obj.profile).to eq IIIF::V3::Presentation::Service::IIIF_IMAGE_V2_LEVEL1_PROFILE
expect(img_service_obj['@context']).to eq IIIF::V3::Presentation::Service::IIIF_IMAGE_V2_CONTEXT
expect(img_service_obj.service.class).to eq Array
expect(img_service_obj.service.size).to eq 1

login_service_obj = img_service_obj.service.first
expect(login_service_obj.keys.size).to eq 4
expect(login_service.id).to eq 'https://example.org/auth/iiif'
expect(login_service.profile).to eq IIIF::V3::Presentation::Service::IIIF_AUTHENTICATION_V1_LOGIN_PROFILE
expect(login_service.label).to eq service_label
expect(login_service.service.class).to eq Array
expect(login_service.service.size).to eq 1

token_service_obj = login_service_obj.service.first
expect(token_service_obj['id']).to eq token_service_id
expect(token_service_obj['profile']).to eq IIIF::V3::Presentation::Service::IIIF_AUTHENTICATION_V1_TOKEN_PROFILE
end
end
end
end
describe 'image examples from http://prezi3.iiif.io/api/presentation/3.0' do
let(:image_object) {
IIIF::V3::Presentation::ImageResource.new({
'id' => "#{img_id}/full/full/0/default.jpg",
'type' => 'dctypes:Image',
'format' => img_mimetype,
'height' => height,
'width' => width,
'service' => image_v2_service
})
}
describe 'simpler' do
it 'validates' do
expect{image_object.validate}.not_to raise_error
end
it 'has expected required values' do
expect(image_object.id).to eq "#{img_id}/full/full/0/default.jpg"
expect(image_object.type).to eq 'dctypes:Image'
end
it 'has expected additional values' do
expect(image_object.format).to eq img_mimetype
expect(image_object.height).to eq height
expect(image_object.width).to eq width
expect(image_object.service).to eq image_v2_service
end
end
describe 'height and width in service' do
# {
# "id": "http://example.org/images/book1-page2/full/1500,2000/0/default.jpg",
# "type": "dctypes:Image",
# "format": "image/jpeg",
# "height":2000,
# "width":1500,
# "service": {
# "@context": "http://iiif.io/api/image/2/context.json",
# "id": "http://example.org/images/book1-page2",
# "profile": "http://iiif.io/api/image/2/level1.json",
# "height":8000,
# "width":6000,
# "tiles": [{"width": 512, "scaleFactors": [1,2,4,8,16]}]
# }
# }
let(:img_obj) {
img = image_object
img.service['height'] = 6666
img.service['width'] = 9999
img.service['tiles'] = [{"width" => 512, "scaleFactors" => [1,2,4,8,16]}]
img
}
it 'validates' do
expect{img_obj.validate}.not_to raise_error
end
it 'has expected service value' do
service_obj = img_obj.service
expect(service_obj.class).to eq IIIF::V3::Presentation::Service
expect(service_obj.keys.size).to eq 7
expect(service_obj['height']).to eq 6666
expect(service_obj['width']).to eq 9999
expect(service_obj['tiles']).to eq [{"width" => 512, "scaleFactors" => [1,2,4,8,16]}]
end
end
end
end
end
Loading

0 comments on commit 7164dc7

Please sign in to comment.