triannon-client 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env_example +16 -2
- data/.rspec +1 -0
- data/README.md +49 -18
- data/Rakefile +15 -2
- data/lib/triannon-client.rb +12 -6
- data/lib/triannon-client/configuration.rb +26 -14
- data/lib/triannon-client/triannon_client.rb +139 -44
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/gets_an_open_annotation_by_ID_with_content_type_application/x-turtle_.yml → CRUD/create_annotation.yml} +192 -132
- data/spec/fixtures/vcr_cassettes/TriannonClientAUTH/with_authentication/behaves_like_authenticate/-_authenticate_returns_true.yml +343 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/POST_401_response_retries_and_logs_RestClient_Exception_message.yml +170 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/POST_403_response_does_not_retry_and_logs_RestClient_Exception_message.yml +170 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/POST_500_response_does_not_retry_and_logs_RestClient_Exception_message.yml +170 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/_get_annotations/returns_an_annotation_list_with_an_annotation_created_by_a_prior_POST.yml → TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/does_not_raise_an_error_when_submitting_a_valid_open_annotation.yml} +203 -319
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/logs_RuntimeError_message.yml +170 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/_post_annotation/with_authentication/behaves_like_create_annotations/returns_a_RestClient_Response_object.yml +170 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/_post_annotation → TriannonClientCREATE/_post_annotation/without_authentication/behaves_like_create_annotations}/does_not_raise_an_error_when_submitting_a_valid_open_annotation.yml +29 -27
- data/spec/fixtures/vcr_cassettes/TriannonClientCREATE/clear_annotations.yml +590 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientDELETE/_delete_annotation/with_authentication/behaves_like_delete_annotations/returns_TRUE_when_deleting_an_annotation_that_does_NOT_exist.yml +349 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientDELETE/_delete_annotation/with_authentication/behaves_like_delete_annotations/returns_TRUE_when_deleting_an_annotation_that_exists.yml +332 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientDELETE/_delete_annotation/with_authentication/behaves_like_delete_annotations/validates_the_annotation_ID.yml +288 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/_delete_annotation/returns_TRUE_when_deleting_an_open_annotation_that_does_NOT_exist.yml → TriannonClientDELETE/_delete_annotation/without_authentication/behaves_like_delete_annotations/returns_TRUE_when_deleting_an_annotation_that_does_NOT_exist.yml} +13 -9
- data/spec/fixtures/vcr_cassettes/TriannonClientDELETE/_delete_annotation/without_authentication/behaves_like_delete_annotations/returns_TRUE_when_deleting_an_annotation_that_exists.yml +127 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/_delete_annotation → TriannonClientDELETE/_delete_annotation/without_authentication/behaves_like_delete_annotations}/validates_the_annotation_ID.yml +7 -5
- data/spec/fixtures/vcr_cassettes/TriannonClientDELETE/clear_annotations.yml +594 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient → TriannonClientREAD/GET}/_get_annotations/returns_an_RDF_Graph.yml +30 -23
- data/spec/fixtures/vcr_cassettes/{TriannonClient → TriannonClientREAD/GET}/_get_annotations/returns_an_RDF_Graph_that_contains_an_AnnotationList.yml +30 -23
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/_get_annotations/returns_an_annotation_list_with_an_annotation_created_by_a_prior_POST.yml +302 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/n-quads_.yml → TriannonClientREAD/GET/_get_iiif_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml} +25 -78
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/n-triples_.yml → TriannonClientREAD/GET/_get_oa_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml} +25 -78
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/_response2graph/accepts_a_RestClient_Response_instance.yml +2399 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/csvm_json_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/n-quads_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/n-triples_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/rdf_json_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/rdf_n3_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/trig_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/trix_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/turtle_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/x-ld_json_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/x-trig_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/csv_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/n3_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/plain_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/rdf_n3_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/rdf_turtle_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/tab-separated-values_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/x-nquads_.yml +1231 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application → TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/gets_an_open_annotation_by_ID_with_content_type_application}/ld_json_.yml +25 -78
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/gets_an_open_annotation_by_ID_with_content_type_application/rdf_xml_.yml +68 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/gets_an_open_annotation_by_ID_with_content_type_application/x-turtle_.yml +69 -0
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_custom_content_type/gets_an_open_annotation_by_ID_with_content_type_text/turtle_.yml +69 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type → TriannonClientREAD/GET/annotation_by_ID/using_default_content_type}/checks_the_annotation_ID.yml +25 -78
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/GET/annotation_by_ID/using_default_content_type/returns_an_EMPTY_RDF_graph_with_a_valid_ID_for_NO_annotation_on_the_server.yml +186 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/rdf_json_.yml → TriannonClientREAD/GET/annotation_by_ID/using_default_content_type/returns_an_RDF_graph_with_a_valid_ID_for_an_annotation_on_the_server.yml} +25 -78
- data/spec/fixtures/vcr_cassettes/TriannonClientREAD/clear_annotations.yml +648 -0
- data/spec/fixtures/vcr_cassettes/{TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/gets_an_open_annotation_by_ID_with_content_type_application/rdf_xml_.yml → TriannonClientREAD/create_annotation.yml} +192 -131
- data/spec/lib/triannon-client/configuration_spec.rb +83 -27
- data/spec/lib/triannon-client/triannon_client_auth_spec.rb +61 -0
- data/spec/lib/triannon-client/triannon_client_class_spec.rb +104 -0
- data/spec/lib/triannon-client/triannon_client_create_spec.rb +119 -0
- data/spec/lib/triannon-client/triannon_client_delete_spec.rb +117 -0
- data/spec/lib/triannon-client/triannon_client_read_spec.rb +342 -0
- data/spec/spec_helper.rb +140 -4
- data/triannon-client.gemspec +1 -1
- metadata +112 -153
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/n-quads_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/n-triples_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/rdf_json_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/rdf_n3_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/trig_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/trix_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/turtle_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/x-ld_json_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_application/x-trig_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/n3_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/rdf_n3_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/rdf_turtle_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/cannot_get_an_open_annotation_by_ID_with_content_type_text/x-nquads_.yml +0 -3995
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/gets_an_open_annotation_by_ID_with_content_type_application/ld_json_.yml +0 -4946
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/gets_an_open_annotation_by_ID_with_content_type_text/turtle_.yml +0 -2566
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/rdf_n3_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/rdf_xml_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/trig_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/trix_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/turtle_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/x-ld_json_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/x-trig_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_application/x-turtle_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_text/n3_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_text/rdf_n3_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_text/rdf_turtle_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_text/turtle_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_content_type_text/x-nquads_.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/logs_exceptions.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/raises_an_argument_error_with_a_nil_ID.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/raises_an_argument_error_with_an_empty_string_ID.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/raises_an_argument_error_with_an_integer_ID.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/requests_an_open_annotation_by_ID_accepting_a_default_JSON-LD_content.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/returns_an_EMPTY_RDF_graph_for_a_500_server_response.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/returns_an_EMPTY_RDF_graph_with_a_valid_ID_for_NO_annotation_on_the_server.yml +0 -2561
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/returns_an_RDF_graph_with_a_valid_ID_for_an_annotation_on_the_server.yml +0 -4946
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_iiif_annotation/requests_an_open_annotation_by_ID_using_a_IIIF_profile.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_iiif_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml +0 -2746
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_oa_annotation/requests_an_open_annotation_by_ID_using_an_OA_profile.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_oa_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml +0 -4946
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/does_not_log_exceptions_for_missing_annotations_404_responses_.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/does_not_log_exceptions_for_missing_annotations_410_responses_.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/logs_exceptions.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_FALSE_for_a_500_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_for_a_200_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_for_a_202_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_for_a_204_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_for_a_404_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_for_a_410_response_to_a_DELETE_request.yml +0 -64
- data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_TRUE_when_deleting_an_open_annotation_that_exists.yml +0 -2549
- data/spec/fixtures/vcr_cassettes/TriannonClient/_post_annotation/logs_exceptions.yml +0 -5355
- data/spec/fixtures/vcr_cassettes/TriannonClient/_post_annotation/logs_exceptions_for_RestClient_Exception.yml +0 -5355
- data/spec/fixtures/vcr_cassettes/TriannonClient/_post_annotation/returns_a_RestClient_Response_object.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_id/returns_a_String_ID_from_the_RDF_URI_of_an_annotation.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_id/returns_a_String_ID_that_is_not_empty.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_uris/returns_an_RDF_URI_that_is_a_valid_URI.yml +0 -2551
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_uris/returns_an_array_of_RDF_URI_from_an_RDF_Graph_of_an_annotation.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/accepts_a_RestClient_Response_instance.yml +0 -4898
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/raises_ArgumentError_when_given_an_empty_String.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/raises_ArgumentError_when_given_nil.yml +0 -2502
- data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/returns_an_RDF_Graph.yml +0 -2502
- data/spec/lib/triannon-client/triannon_client_spec.rb +0 -546
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.shared_examples "authenticate" do |auth_required|
|
4
|
+
|
5
|
+
let(:tc) {
|
6
|
+
if auth_required
|
7
|
+
triannon_config_auth
|
8
|
+
else
|
9
|
+
triannon_config_no_auth
|
10
|
+
end
|
11
|
+
TriannonClient::TriannonClient.new
|
12
|
+
}
|
13
|
+
|
14
|
+
def check_header
|
15
|
+
headers = tc.site.headers
|
16
|
+
expect(headers).to include(:Authorization)
|
17
|
+
expect(headers[:Authorization]).to match(/Bearer/)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "- #authenticate returns #{auth_required}" do
|
21
|
+
if auth_required
|
22
|
+
expect(tc.authenticate).to be_truthy
|
23
|
+
check_header
|
24
|
+
else
|
25
|
+
expect(tc.authenticate).to be false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "- #authenticate! returns #{auth_required}" do
|
30
|
+
# Authenticate and then test that authenticate!
|
31
|
+
# will reset and renew the authentication.
|
32
|
+
auth1 = tc.authenticate
|
33
|
+
check_header if auth_required
|
34
|
+
expect(tc.site.headers).to receive(:delete)
|
35
|
+
if auth_required
|
36
|
+
# renew the authentication
|
37
|
+
expect(tc.authenticate!).to be_truthy
|
38
|
+
check_header
|
39
|
+
auth2 = tc.site.headers[:Authorization]
|
40
|
+
expect(auth1).not_to eql(auth2)
|
41
|
+
else
|
42
|
+
expect(tc.authenticate!).to be false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
describe 'TriannonClientAUTH', :vcr do
|
50
|
+
|
51
|
+
context 'without authentication' do
|
52
|
+
auth_required = false # it's not required
|
53
|
+
it_behaves_like 'authenticate', auth_required
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with authentication' do
|
57
|
+
auth_required = true # it must succeed
|
58
|
+
it_behaves_like 'authenticate', auth_required
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# ::TriannonClient::TriannonClient class specs
|
4
|
+
|
5
|
+
describe 'TriannonClientClass' do
|
6
|
+
|
7
|
+
let(:tc) {
|
8
|
+
triannon_config_no_auth # spec_helper
|
9
|
+
TriannonClient::TriannonClient.new
|
10
|
+
}
|
11
|
+
|
12
|
+
describe 'has constants:' do
|
13
|
+
it 'CONTENT_TYPES' do
|
14
|
+
const = TriannonClient::TriannonClient::CONTENT_TYPES
|
15
|
+
expect(const).to be_instance_of Array
|
16
|
+
expect(const).to include('application/ld+json')
|
17
|
+
end
|
18
|
+
it 'PROFILE_TYPE_IIIF' do
|
19
|
+
const = TriannonClient::TriannonClient::PROFILE_IIIF
|
20
|
+
expect(const).to be_instance_of String
|
21
|
+
expect(const).to include('http://iiif.io/api/presentation/2/context.json')
|
22
|
+
end
|
23
|
+
it 'PROFILE_TYPE_OA' do
|
24
|
+
const = TriannonClient::TriannonClient::PROFILE_OA
|
25
|
+
expect(const).to be_instance_of String
|
26
|
+
expect(const).to include('http://www.w3.org/ns/oa-context-20130208.json')
|
27
|
+
end
|
28
|
+
it 'CONTENT_TYPE_IIIF' do
|
29
|
+
const = TriannonClient::TriannonClient::CONTENT_TYPE_IIIF
|
30
|
+
expect(const).to be_instance_of String
|
31
|
+
expect(const).to include('application/ld+json')
|
32
|
+
expect(const).to include('http://iiif.io/api/presentation/2/context.json')
|
33
|
+
end
|
34
|
+
it 'CONTENT_TYPE_OA' do
|
35
|
+
const = TriannonClient::TriannonClient::CONTENT_TYPE_OA
|
36
|
+
expect(const).to be_instance_of String
|
37
|
+
expect(const).to include('application/ld+json')
|
38
|
+
expect(const).to include('http://www.w3.org/ns/oa-context-20130208.json')
|
39
|
+
end
|
40
|
+
it 'JSONLD_TYPE' do
|
41
|
+
const = TriannonClient::TriannonClient::JSONLD_TYPE
|
42
|
+
expect(const).to be_instance_of String
|
43
|
+
expect(const).to eql('application/ld+json')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'public attributes:' do
|
48
|
+
# attribute accessors
|
49
|
+
it 'config' do
|
50
|
+
expect(tc).to respond_to(:config)
|
51
|
+
end
|
52
|
+
it 'site' do
|
53
|
+
expect(tc).to respond_to(:site)
|
54
|
+
end
|
55
|
+
it 'auth' do
|
56
|
+
expect(tc).to respond_to(:auth)
|
57
|
+
end
|
58
|
+
it 'container' do
|
59
|
+
expect(tc).to respond_to(:container)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'public methods:' do
|
64
|
+
# methods
|
65
|
+
it 'authenticate' do
|
66
|
+
expect(tc).to respond_to(:authenticate)
|
67
|
+
end
|
68
|
+
it 'delete_annotation' do
|
69
|
+
expect(tc).to respond_to(:delete_annotation)
|
70
|
+
end
|
71
|
+
it 'get_annotations' do
|
72
|
+
expect(tc).to respond_to(:get_annotations)
|
73
|
+
end
|
74
|
+
it 'get_annotation' do
|
75
|
+
expect(tc).to respond_to(:get_annotation)
|
76
|
+
end
|
77
|
+
it 'get_iiif_annotation' do
|
78
|
+
expect(tc).to respond_to(:get_iiif_annotation)
|
79
|
+
end
|
80
|
+
it 'get_oa_annotation' do
|
81
|
+
expect(tc).to respond_to(:get_oa_annotation)
|
82
|
+
end
|
83
|
+
# utilities
|
84
|
+
it 'response2graph' do
|
85
|
+
expect(tc).to respond_to(:response2graph)
|
86
|
+
end
|
87
|
+
it 'annotation_id' do
|
88
|
+
expect(tc).to respond_to(:annotation_id)
|
89
|
+
end
|
90
|
+
it 'annotation_uris' do
|
91
|
+
expect(tc).to respond_to(:annotation_uris)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'private:' do
|
96
|
+
it 'check_id' do
|
97
|
+
expect(tc).not_to respond_to(:check_id)
|
98
|
+
end
|
99
|
+
it 'check_content_type' do
|
100
|
+
expect(tc).not_to respond_to(:check_content_type)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.shared_examples "create annotations" do |auth_required|
|
4
|
+
|
5
|
+
let(:tc) {
|
6
|
+
if auth_required
|
7
|
+
triannon_config_auth
|
8
|
+
else
|
9
|
+
triannon_config_no_auth
|
10
|
+
end
|
11
|
+
TriannonClient::TriannonClient.new
|
12
|
+
}
|
13
|
+
|
14
|
+
def check_authentication(required)
|
15
|
+
auth = tc.authenticate
|
16
|
+
if required
|
17
|
+
expect(auth).to be_truthy
|
18
|
+
else
|
19
|
+
expect(auth).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:exception_data) { 'post_exception' }
|
24
|
+
let(:exception_post) {
|
25
|
+
{
|
26
|
+
"commit"=>"Create Annotation",
|
27
|
+
"annotation"=>{"data"=>exception_data}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
let(:exception_msg) { 'create_exception' }
|
31
|
+
|
32
|
+
def raise_restclient_exception(status)
|
33
|
+
response = double
|
34
|
+
allow(response).to receive(:is_a?).and_return(RestClient::Response)
|
35
|
+
allow(response).to receive(:headers).and_return(jsonld_content)
|
36
|
+
allow(response).to receive(:body).and_return(exception_msg)
|
37
|
+
allow(response).to receive(:code).and_return(status)
|
38
|
+
exception = RestClient::Exception.new(response)
|
39
|
+
allow_any_instance_of(RestClient::Resource).to receive(:post).with(exception_post).and_raise(exception)
|
40
|
+
if status == 401
|
41
|
+
expect(tc).to receive(:authenticate).once # retry triggers authentication
|
42
|
+
else
|
43
|
+
expect(tc).not_to receive(:authenticate) # no retry
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'does not raise an error when submitting a valid open annotation' do
|
48
|
+
check_authentication(auth_required)
|
49
|
+
response = nil
|
50
|
+
expect do
|
51
|
+
response = tc.post_annotation(jsonld_oa)
|
52
|
+
end.not_to raise_error
|
53
|
+
# Double check the POST by deleting the annotation.
|
54
|
+
# If the POST was successful, the DELETE should work too.
|
55
|
+
graph = tc.response2graph(response)
|
56
|
+
uri = tc.annotation_uris(graph).first
|
57
|
+
id = tc.annotation_id(uri)
|
58
|
+
expect(tc.delete_annotation(id)).to be true
|
59
|
+
end
|
60
|
+
it 'returns a RestClient::Response object' do
|
61
|
+
# The response behaves primarily as a String, so it can not be tested
|
62
|
+
# as an instance of RestClient::Response, but it can be tested to respond
|
63
|
+
# to RestClient::Response methods.
|
64
|
+
check_authentication(auth_required)
|
65
|
+
anno = create_annotation
|
66
|
+
r = anno[:response]
|
67
|
+
expect(r.is_a? RestClient::Response).to be true
|
68
|
+
expect(r).to respond_to(:code)
|
69
|
+
expect(r).to respond_to(:body)
|
70
|
+
expect(r).to respond_to(:headers)
|
71
|
+
end
|
72
|
+
it 'POST 401 response retries and logs RestClient::Exception message' do
|
73
|
+
check_authentication(auth_required)
|
74
|
+
raise_restclient_exception(401)
|
75
|
+
expect(TriannonClient.configuration.logger).to receive(:error).with(/#{exception_msg}/)
|
76
|
+
tc.post_annotation(exception_data)
|
77
|
+
end
|
78
|
+
it 'POST 403 response does not retry and logs RestClient::Exception message' do
|
79
|
+
check_authentication(auth_required)
|
80
|
+
raise_restclient_exception(403)
|
81
|
+
expect(TriannonClient.configuration.logger).to receive(:error).with(/#{exception_msg}/)
|
82
|
+
tc.post_annotation(exception_data)
|
83
|
+
end
|
84
|
+
it 'POST 500 response does not retry and logs RestClient::Exception message' do
|
85
|
+
check_authentication(auth_required)
|
86
|
+
raise_restclient_exception(500)
|
87
|
+
expect(TriannonClient.configuration.logger).to receive(:error).with(/#{exception_msg}/)
|
88
|
+
tc.post_annotation(exception_data)
|
89
|
+
end
|
90
|
+
it 'logs RuntimeError message' do
|
91
|
+
check_authentication(auth_required)
|
92
|
+
exception = RuntimeError.new(exception_msg)
|
93
|
+
allow_any_instance_of(RestClient::Resource).to receive(:post).with(exception_post).and_raise(exception)
|
94
|
+
expect(TriannonClient.configuration.logger).to receive(:error).with(/#{exception_msg}/)
|
95
|
+
tc.post_annotation(exception_data)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
describe 'TriannonClientCREATE', :vcr do
|
101
|
+
|
102
|
+
after :all do
|
103
|
+
clear_annotations('TriannonClientCREATE/clear_annotations')
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#post_annotation" do
|
107
|
+
|
108
|
+
context 'without authentication' do
|
109
|
+
auth_required = false # it's not required
|
110
|
+
it_behaves_like 'create annotations', auth_required
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with authentication' do
|
114
|
+
auth_required = true # it must succeed
|
115
|
+
it_behaves_like 'create annotations', auth_required
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.shared_examples "delete annotations" do |auth_required|
|
4
|
+
|
5
|
+
let(:tc) {
|
6
|
+
if auth_required
|
7
|
+
triannon_config_auth
|
8
|
+
else
|
9
|
+
triannon_config_no_auth
|
10
|
+
end
|
11
|
+
TriannonClient::TriannonClient.new
|
12
|
+
}
|
13
|
+
|
14
|
+
def test_delete_for_response_code(anno_id, status, result)
|
15
|
+
response = double
|
16
|
+
allow(response).to receive(:is_a?).and_return(RestClient::Response)
|
17
|
+
allow(response).to receive(:headers).and_return(jsonld_content)
|
18
|
+
allow(response).to receive(:body).and_return('delete_annotation')
|
19
|
+
allow(response).to receive(:code).and_return(status)
|
20
|
+
exception = RestClient::Exception.new(response)
|
21
|
+
if [401, 404, 410, 500].include? status
|
22
|
+
allow_any_instance_of(RestClient::Resource).to receive(:delete).and_raise(exception)
|
23
|
+
if status == 401
|
24
|
+
expect(tc).to receive(:authenticate).once # retry triggers auth
|
25
|
+
else
|
26
|
+
expect(tc).not_to receive(:authenticate) # no retry
|
27
|
+
end
|
28
|
+
else
|
29
|
+
allow_any_instance_of(RestClient::Resource).to receive(:delete).and_return(response)
|
30
|
+
expect(tc).not_to receive(:authenticate) # no retry
|
31
|
+
end
|
32
|
+
expect(tc.delete_annotation(anno_id)).to be result
|
33
|
+
end
|
34
|
+
it "DELETE 200 response returns true" do
|
35
|
+
test_delete_for_response_code('200_is_true', 200, true)
|
36
|
+
end
|
37
|
+
it "DELETE 202 response returns true" do
|
38
|
+
test_delete_for_response_code('202_is_true', 202, true)
|
39
|
+
end
|
40
|
+
it "DELETE 204 response returns true" do
|
41
|
+
test_delete_for_response_code('204_is_true', 204, true)
|
42
|
+
end
|
43
|
+
it "DELETE 401 response initiates a retry with authentication" do
|
44
|
+
test_delete_for_response_code('401_is_retry', 401, false)
|
45
|
+
end
|
46
|
+
it "DELETE 404 response returns true" do
|
47
|
+
test_delete_for_response_code('404_is_true', 404, true)
|
48
|
+
end
|
49
|
+
it "DELETE 410 response returns true" do
|
50
|
+
test_delete_for_response_code('410_is_true', 410, true)
|
51
|
+
end
|
52
|
+
it "DELETE 500 response returns false" do
|
53
|
+
test_delete_for_response_code('500_is_false', 500, false)
|
54
|
+
end
|
55
|
+
it 'DELETE 404|410 does not log exceptions' do
|
56
|
+
expect(tc.config.logger).not_to receive(:error)
|
57
|
+
test_delete_for_response_code('404_is_true', 404, true)
|
58
|
+
test_delete_for_response_code('410_is_true', 410, true)
|
59
|
+
end
|
60
|
+
it 'DELETE 500 logs exceptions' do
|
61
|
+
expect(tc.config.logger).to receive(:error)
|
62
|
+
test_delete_for_response_code('500_is_false', 500, false)
|
63
|
+
end
|
64
|
+
it 'validates the annotation ID' do
|
65
|
+
expect(tc).to receive(:check_id)
|
66
|
+
tc.delete_annotation('checking_anno_id')
|
67
|
+
end
|
68
|
+
it 'raises ArgumentError for an invalid annotation ID' do
|
69
|
+
expect_any_instance_of(RestClient::Resource).not_to receive(:delete)
|
70
|
+
expect { tc.delete_annotation('') }.to raise_error(ArgumentError)
|
71
|
+
expect { tc.delete_annotation(nil) }.to raise_error(ArgumentError)
|
72
|
+
end
|
73
|
+
it 'uses RestClient::Resource.delete to DELETE a valid annotation ID' do
|
74
|
+
expect_any_instance_of(RestClient::Resource).to receive(:delete)
|
75
|
+
tc.delete_annotation(SecureRandom.uuid)
|
76
|
+
end
|
77
|
+
it 'returns TRUE when deleting an annotation that exists' do
|
78
|
+
anno = create_annotation
|
79
|
+
expect( tc.delete_annotation(anno[:id]) ).to be true
|
80
|
+
graph = tc.get_annotation(anno[:id])
|
81
|
+
graph_is_empty(graph)
|
82
|
+
end
|
83
|
+
it 'returns TRUE when deleting an annotation that does NOT exist' do
|
84
|
+
id = 'anno_does_not_exist'
|
85
|
+
graph = tc.get_annotation(id)
|
86
|
+
graph_is_empty(graph)
|
87
|
+
expect( tc.delete_annotation(id) ).to be true
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
describe 'TriannonClientDELETE', :vcr do
|
94
|
+
|
95
|
+
# before :all do
|
96
|
+
# # create a new annotation and call all the response processing utils.
|
97
|
+
# @anno = create_annotation('TriannonClientDELETE/create_annotation')
|
98
|
+
# end
|
99
|
+
|
100
|
+
after :all do
|
101
|
+
clear_annotations('TriannonClientDELETE/clear_annotations')
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#delete_annotation" do
|
105
|
+
|
106
|
+
context 'without authentication' do
|
107
|
+
auth_required = false # it's not required
|
108
|
+
it_behaves_like 'delete annotations', auth_required
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with authentication' do
|
112
|
+
auth_required = true # it must succeed
|
113
|
+
it_behaves_like 'delete annotations', auth_required
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,342 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# ::TriannonClient::TriannonClient GET specs
|
4
|
+
# The GET requests do not require authentication.
|
5
|
+
|
6
|
+
describe 'TriannonClientREAD', :vcr do
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
# create a new annotation and call all the response processing utils.
|
10
|
+
@anno = create_annotation('TriannonClientREAD/create_annotation')
|
11
|
+
end
|
12
|
+
|
13
|
+
after :all do
|
14
|
+
clear_annotations('TriannonClientREAD/clear_annotations')
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:tc) {
|
18
|
+
# triannon_config_auth
|
19
|
+
TriannonClient::TriannonClient.new
|
20
|
+
}
|
21
|
+
|
22
|
+
def request_anno_with_content_type(content_type)
|
23
|
+
expect_any_instance_of(RestClient::Resource).to receive(:get).with(hash_including(:accept => content_type) )
|
24
|
+
tc.get_annotation(@anno[:id], content_type)
|
25
|
+
end
|
26
|
+
|
27
|
+
def gets_anno_with_content_type(content_type)
|
28
|
+
graph = tc.get_annotation(@anno[:id], content_type)
|
29
|
+
graph_contains_open_annotation(graph, @anno[:uris])
|
30
|
+
end
|
31
|
+
|
32
|
+
def cannot_get_anno_with_content_type(content_type)
|
33
|
+
graph = tc.get_annotation(@anno[:id], content_type)
|
34
|
+
graph_is_empty(graph)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
let(:exception_msg) { 'get_exception' }
|
39
|
+
def raise_restclient_exception(status)
|
40
|
+
response = double
|
41
|
+
allow(response).to receive(:is_a?).and_return(RestClient::Response)
|
42
|
+
allow(response).to receive(:headers).and_return(jsonld_content)
|
43
|
+
allow(response).to receive(:body).and_return(exception_msg)
|
44
|
+
allow(response).to receive(:code).and_return(status)
|
45
|
+
exception = RestClient::Exception.new(response)
|
46
|
+
allow_any_instance_of(RestClient::Resource).to receive(:get).with(jsonld_accept).and_raise(exception)
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'GET' do
|
50
|
+
|
51
|
+
describe "#get_annotations" do
|
52
|
+
it 'returns an RDF::Graph' do
|
53
|
+
graph = tc.get_annotations
|
54
|
+
graph_contains_statements(graph)
|
55
|
+
end
|
56
|
+
it 'returns an RDF::Graph that contains an AnnotationList' do
|
57
|
+
graph = tc.get_annotations
|
58
|
+
anno_list_uri = RDF::URI.parse('http://iiif.io/api/presentation/2#AnnotationList')
|
59
|
+
result = graph.query([nil, nil, anno_list_uri])
|
60
|
+
expect(result.size).to eql(1)
|
61
|
+
end
|
62
|
+
it 'returns an annotation list with an annotation created by a prior POST' do
|
63
|
+
graph = tc.get_annotations
|
64
|
+
graph_contains_open_annotation(graph, @anno[:uris])
|
65
|
+
end
|
66
|
+
it '404 response logs exceptions for RestClient::Exception' do
|
67
|
+
raise_restclient_exception(404)
|
68
|
+
expect(tc.config.logger).to receive(:error).with(/404/)
|
69
|
+
tc.get_annotations
|
70
|
+
end
|
71
|
+
it '500 response returns an EMPTY RDF graph' do
|
72
|
+
raise_restclient_exception(500)
|
73
|
+
graph = tc.get_annotations
|
74
|
+
graph_is_empty(graph)
|
75
|
+
end
|
76
|
+
it '500 response logs exceptions for RestClient::Exception' do
|
77
|
+
raise_restclient_exception(500)
|
78
|
+
expect(tc.config.logger).to receive(:error).with(/#{exception_msg}/)
|
79
|
+
tc.get_annotations
|
80
|
+
end
|
81
|
+
it 'logs exceptions for RuntimeError' do
|
82
|
+
exception = RuntimeError.new('get_exception')
|
83
|
+
allow_any_instance_of(RestClient::Resource).to receive(:get).with(jsonld_accept).and_raise(exception)
|
84
|
+
expect(tc.config.logger).to receive(:error).with(/get_exception/)
|
85
|
+
tc.get_annotations
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#get_iiif_annotation" do
|
90
|
+
# the mime type is fixed for this method
|
91
|
+
it 'requests an open annotation by ID, using a IIIF profile' do
|
92
|
+
graph_contains_open_annotation(@anno[:graph], @anno[:uris])
|
93
|
+
content_type = TriannonClient::TriannonClient::CONTENT_TYPE_IIIF
|
94
|
+
expect(tc).to receive(:get_annotation).with(@anno[:id], content_type)
|
95
|
+
tc.get_iiif_annotation(@anno[:id])
|
96
|
+
end
|
97
|
+
it 'returns an RDF::Graph of an open annotation' do
|
98
|
+
graph = tc.get_iiif_annotation(@anno[:id])
|
99
|
+
graph_contains_statements(graph)
|
100
|
+
graph_contains_open_annotation(graph, @anno[:uris])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#get_oa_annotation" do
|
105
|
+
# the mime type is fixed for this method
|
106
|
+
it 'requests an open annotation by ID, using an OA profile' do
|
107
|
+
graph_contains_open_annotation(@anno[:graph], @anno[:uris])
|
108
|
+
content_type = TriannonClient::TriannonClient::CONTENT_TYPE_OA
|
109
|
+
expect(tc).to receive(:get_annotation).with(@anno[:id], content_type)
|
110
|
+
tc.get_oa_annotation(@anno[:id])
|
111
|
+
end
|
112
|
+
it 'returns an RDF::Graph of an open annotation' do
|
113
|
+
graph = tc.get_oa_annotation(@anno[:id])
|
114
|
+
graph_contains_statements(graph)
|
115
|
+
graph_contains_open_annotation(graph, @anno[:uris])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#response2graph' do
|
120
|
+
it 'accepts a RestClient::Response instance' do
|
121
|
+
r = @anno[:response]
|
122
|
+
expect{tc.response2graph(r)}.not_to raise_error
|
123
|
+
end
|
124
|
+
it 'returns an RDF::Graph' do
|
125
|
+
expect(@anno[:graph]).to be_instance_of RDF::Graph
|
126
|
+
graph_contains_statements(@anno[:graph])
|
127
|
+
end
|
128
|
+
it 'raises ArgumentError when given nil' do
|
129
|
+
expect{tc.response2graph(nil)}.to raise_error(ArgumentError)
|
130
|
+
end
|
131
|
+
it 'raises ArgumentError when given an empty String' do
|
132
|
+
expect{tc.response2graph('')}.to raise_error(ArgumentError)
|
133
|
+
end
|
134
|
+
it 'raises ArgumentError when response content-type is unacceptable' do
|
135
|
+
h = {content_type: 'unacceptable'}
|
136
|
+
r = double
|
137
|
+
allow(r).to receive(:is_a?).and_return(RestClient::Response)
|
138
|
+
allow(r).to receive(:headers).and_return(h)
|
139
|
+
expect{tc.response2graph('')}.to raise_error(ArgumentError)
|
140
|
+
end
|
141
|
+
it 'returns an empty RDF::Graph for failure to parse input' do
|
142
|
+
r = double
|
143
|
+
allow(r).to receive(:is_a?).and_return(RestClient::Response)
|
144
|
+
allow(r).to receive(:code).and_return(200)
|
145
|
+
allow(r).to receive(:headers).and_return(jsonld_content)
|
146
|
+
allow(r).to receive(:body).and_return('malformed json')
|
147
|
+
g = tc.response2graph(r)
|
148
|
+
expect(g).to be_instance_of RDF::Graph
|
149
|
+
expect(g).to be_empty
|
150
|
+
h = {content_type: 'application/rdf+xml'}
|
151
|
+
allow(r).to receive(:headers).and_return(h)
|
152
|
+
allow(r).to receive(:body).and_return('malformed rdf+xml')
|
153
|
+
g = tc.response2graph(r)
|
154
|
+
expect(g).to be_instance_of RDF::Graph
|
155
|
+
expect(g).to be_empty
|
156
|
+
# h = {content_type: 'application/turtle'}
|
157
|
+
# allow(r).to receive(:headers).and_return(h)
|
158
|
+
# allow(r).to receive(:body).and_return('malformed turtle')
|
159
|
+
# g = tc.response2graph(r)
|
160
|
+
# expect(g).to be_instance_of RDF::Graph
|
161
|
+
# expect(g).to be_empty
|
162
|
+
end
|
163
|
+
it 'logs exceptions and returns an empty RDF::Graph' do
|
164
|
+
r = double
|
165
|
+
allow(r).to receive(:is_a?).and_return(RestClient::Response)
|
166
|
+
allow(r).to receive(:headers).and_return(jsonld_content)
|
167
|
+
allow(r).to receive(:body).and_raise(RuntimeError, 'oops!')
|
168
|
+
expect(tc.config.logger).to receive(:error).with(/oops!/)
|
169
|
+
g = tc.response2graph(r)
|
170
|
+
expect(g).to be_instance_of RDF::Graph
|
171
|
+
expect(g).to be_empty
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#annotation_uris" do
|
178
|
+
it "returns an array of RDF::URI from an RDF::Graph of an annotation" do
|
179
|
+
expect(@anno[:graph]).to be_instance_of RDF::Graph
|
180
|
+
expect(@anno[:uris]).to be_instance_of Array
|
181
|
+
expect(@anno[:uris]).not_to be_empty
|
182
|
+
expect(@anno[:uris].first).to be_instance_of RDF::URI
|
183
|
+
end
|
184
|
+
it "returns an RDF::URI that is a valid URI" do
|
185
|
+
expect(@anno[:uris].first).to match(/\A#{URI::regexp}\z/)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#annotation_id" do
|
190
|
+
it "returns a String ID from the RDF::URI of an annotation" do
|
191
|
+
expect(@anno[:uris].first).to be_instance_of RDF::URI
|
192
|
+
expect(@anno[:id]).to be_instance_of String
|
193
|
+
end
|
194
|
+
it "returns a String ID that is not empty" do
|
195
|
+
expect(@anno[:id]).to be_instance_of String
|
196
|
+
expect(@anno[:id]).not_to be_empty
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "annotation by ID" do
|
201
|
+
|
202
|
+
context 'using default content type' do
|
203
|
+
|
204
|
+
it 'checks the annotation ID' do
|
205
|
+
expect(tc).to receive(:check_id)
|
206
|
+
graph = tc.get_annotation(@anno[:id])
|
207
|
+
graph_contains_statements(graph)
|
208
|
+
end
|
209
|
+
it 'raises an argument error with a nil ID' do
|
210
|
+
expect{tc.get_annotation(nil)}.to raise_error(ArgumentError)
|
211
|
+
end
|
212
|
+
it 'raises an argument error with an integer ID' do
|
213
|
+
expect{tc.get_annotation(0)}.to raise_error(ArgumentError)
|
214
|
+
end
|
215
|
+
it 'raises an argument error with an empty string ID' do
|
216
|
+
expect{tc.get_annotation('')}.to raise_error(ArgumentError)
|
217
|
+
end
|
218
|
+
it 'requests an open annotation by ID, using JSON-LD content' do
|
219
|
+
jsonld = TriannonClient::TriannonClient::JSONLD_TYPE
|
220
|
+
expect_any_instance_of(RestClient::Resource).to receive(:get).with(hash_including(:accept => jsonld) )
|
221
|
+
# does not work using expect(tc.container).to receive(:get) etc.
|
222
|
+
tc.get_annotation(@anno[:id])
|
223
|
+
end
|
224
|
+
it 'returns an RDF graph with a valid ID for an annotation on the server' do
|
225
|
+
graph = tc.get_annotation(@anno[:id])
|
226
|
+
graph_contains_open_annotation(graph, @anno[:uris])
|
227
|
+
end
|
228
|
+
it 'returns an EMPTY RDF graph with a valid ID for NO annotation on the server' do
|
229
|
+
id = SecureRandom.uuid
|
230
|
+
graph = tc.get_annotation(id)
|
231
|
+
graph_is_empty(graph)
|
232
|
+
end
|
233
|
+
it '404 response logs exceptions for RestClient::Exception' do
|
234
|
+
raise_restclient_exception(404)
|
235
|
+
expect(tc.config.logger).to receive(:error).with(/404/)
|
236
|
+
tc.get_annotation('raise_get_exception')
|
237
|
+
end
|
238
|
+
it '500 response returns an EMPTY RDF graph' do
|
239
|
+
raise_restclient_exception(500)
|
240
|
+
graph = tc.get_annotation(@anno[:id])
|
241
|
+
graph_is_empty(graph)
|
242
|
+
end
|
243
|
+
it '500 response logs exceptions for RestClient::Exception' do
|
244
|
+
raise_restclient_exception(500)
|
245
|
+
expect(tc.config.logger).to receive(:error).with(/#{exception_msg}/)
|
246
|
+
tc.get_annotation(@anno[:id])
|
247
|
+
end
|
248
|
+
it 'logs exceptions for RuntimeError' do
|
249
|
+
exception = RuntimeError.new('get_exception')
|
250
|
+
allow_any_instance_of(RestClient::Resource).to receive(:get).with(jsonld_accept).and_raise(exception)
|
251
|
+
expect(tc.config.logger).to receive(:error).with(/get_exception/)
|
252
|
+
tc.get_annotation(@anno[:id])
|
253
|
+
end
|
254
|
+
end # using default content type
|
255
|
+
|
256
|
+
context 'using custom content type' do
|
257
|
+
# Content types could be supported for RDF::Format.content_types.keys,
|
258
|
+
# but not all of them are supported. The supported content types for
|
259
|
+
# triannon are defined in
|
260
|
+
# https://github.com/sul-dlss/triannon/blob/master/config/initializers/mime_types.rb
|
261
|
+
# https://github.com/sul-dlss/triannon/blob/master/app/controllers/triannon/annotations_controller.rb
|
262
|
+
# https://github.com/sul-dlss/triannon/blob/master/app/controllers/triannon/search_controller.rb
|
263
|
+
# The default content type is "application/ld+json" and, at the time of
|
264
|
+
# writing, triannon also supports:
|
265
|
+
# turtle as: ["application/x-turtle", "text/turtle"]
|
266
|
+
# rdf+xml as: ["application/rdf+xml", "text/rdf+xml", "text/rdf"]
|
267
|
+
# json as: ["application/json", "text/x-json", "application/jsonrequest"]
|
268
|
+
# xml as: ["application/xml", "text/xml", "application/x-xml"]
|
269
|
+
# html
|
270
|
+
|
271
|
+
# The client supports any format in RDF::Format.content_types, so the
|
272
|
+
# following are not included (as of July 2015):
|
273
|
+
# "application/json" => true,
|
274
|
+
# "application/jsonrequest" => true,
|
275
|
+
# "text/x-json" => true,
|
276
|
+
# "text/rdf+xml" => true,
|
277
|
+
# "text/rdf" => true,
|
278
|
+
# "application/xml" => true,
|
279
|
+
# "text/xml" => true,
|
280
|
+
# "application/x-xml" => true,
|
281
|
+
|
282
|
+
# html and xhtml are supported by RDF::Format, so they can be used,
|
283
|
+
# but they fail to return a proper RDF::Graph
|
284
|
+
# "text/html"=> true,
|
285
|
+
# "application/xhtml+xml"=> true,
|
286
|
+
|
287
|
+
# content types that work
|
288
|
+
content_types = {
|
289
|
+
"application/ld+json"=> true,
|
290
|
+
"application/rdf+xml"=> true,
|
291
|
+
"text/turtle"=> true,
|
292
|
+
"application/x-turtle"=> true,
|
293
|
+
}
|
294
|
+
# content types that fail
|
295
|
+
content_types.merge!({
|
296
|
+
"application/x-ld+json"=> false,
|
297
|
+
"application/rdf+json"=> false,
|
298
|
+
"text/rdf+turtle"=> false,
|
299
|
+
"application/turtle"=> false,
|
300
|
+
"application/n-triples"=> false,
|
301
|
+
"application/rdf+n3"=> false,
|
302
|
+
"text/n3"=> false,
|
303
|
+
"text/rdf+n3"=> false,
|
304
|
+
"text/plain"=> false,
|
305
|
+
"application/n-quads"=> false,
|
306
|
+
"text/x-nquads"=> false,
|
307
|
+
"application/trig"=> false,
|
308
|
+
"application/x-trig"=> false,
|
309
|
+
"application/trix"=> false,
|
310
|
+
"text/csv"=> false,
|
311
|
+
"text/tab-separated-values"=>false,
|
312
|
+
"application/csvm+json"=>false,
|
313
|
+
})
|
314
|
+
specs = content_types.map do |type,success|
|
315
|
+
request_spec = <<EOS
|
316
|
+
it 'requests an open annotation by ID, with content type "#{type}"' do
|
317
|
+
request_anno_with_content_type('#{type}')
|
318
|
+
end
|
319
|
+
EOS
|
320
|
+
if success
|
321
|
+
get_spec = <<EOS
|
322
|
+
it 'gets an open annotation by ID, with content type "#{type}"' do
|
323
|
+
gets_anno_with_content_type('#{type}')
|
324
|
+
end
|
325
|
+
EOS
|
326
|
+
else
|
327
|
+
get_spec = <<EOS
|
328
|
+
it 'cannot get an open annotation by ID, with content type "#{type}"' do
|
329
|
+
cannot_get_anno_with_content_type('#{type}')
|
330
|
+
end
|
331
|
+
EOS
|
332
|
+
end
|
333
|
+
request_spec + get_spec
|
334
|
+
end
|
335
|
+
eval(specs.join)
|
336
|
+
end # using custom content type
|
337
|
+
|
338
|
+
end # annotation by ID
|
339
|
+
end # GET context
|
340
|
+
|
341
|
+
end
|
342
|
+
|