triannon-client 0.1.0 → 0.2.0.pre.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.env_example +1 -1
  3. data/.travis.yml +1 -2
  4. data/README.md +12 -3
  5. data/bin/test.sh +8 -9
  6. data/lib/triannon-client.rb +8 -3
  7. data/lib/triannon-client/triannon_client.rb +180 -0
  8. 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 +4088 -0
  9. 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 +4088 -0
  10. 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 +4088 -0
  11. 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 +4088 -0
  12. 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 +4088 -0
  13. 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 +4088 -0
  14. 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 +4088 -0
  15. 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 +4088 -0
  16. 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 +4088 -0
  17. 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 +4088 -0
  18. 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 +4088 -0
  19. 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 +4088 -0
  20. 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 +4088 -0
  21. 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 +4946 -0
  22. 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/n-quads_.yml +4088 -0
  23. 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/n-triples_.yml +4088 -0
  24. 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_json_.yml +4088 -0
  25. 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_n3_.yml +4088 -0
  26. 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 +2565 -0
  27. 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/trig_.yml +4088 -0
  28. 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/trix_.yml +4088 -0
  29. 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/turtle_.yml +4088 -0
  30. 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-ld_json_.yml +4088 -0
  31. 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-trig_.yml +4088 -0
  32. 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 +2566 -0
  33. 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/n3_.yml +4088 -0
  34. 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/rdf_n3_.yml +4088 -0
  35. 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/rdf_turtle_.yml +4088 -0
  36. 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 +2566 -0
  37. 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/x-nquads_.yml +4088 -0
  38. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_accepting_JSON-LD_content.yml +2502 -0
  39. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_accepting_a_default_JSON-LD_content.yml +2502 -0
  40. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_using_a_default_JSON-LD_content.yml +2502 -0
  41. 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/ld_json_.yml +2502 -0
  42. 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 +2502 -0
  43. 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 +2502 -0
  44. 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 +2502 -0
  45. 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 +2502 -0
  46. 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 +2502 -0
  47. 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 +2502 -0
  48. 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 +2502 -0
  49. 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 +2502 -0
  50. 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 +2502 -0
  51. 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 +2502 -0
  52. 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 +2502 -0
  53. 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 +2502 -0
  54. 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 +2502 -0
  55. 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 +2502 -0
  56. 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 +2502 -0
  57. 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 +2502 -0
  58. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_optional_content_type_parameter.yml +2502 -0
  59. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_content_type/requests_an_open_annotation_by_ID_with_turtle_content_type_parameter.yml +2502 -0
  60. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/checks_the_annotation_ID.yml +2561 -0
  61. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/logs_exceptions.yml +2502 -0
  62. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/raises_an_argument_error_with_a_nil_ID.yml +2502 -0
  63. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/raises_an_argument_error_with_an_empty_string_ID.yml +2502 -0
  64. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/raises_an_argument_error_with_an_integer_ID.yml +2502 -0
  65. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/returns_an_EMPTY_RDF_graph_for_a_500_server_response.yml +2502 -0
  66. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/returns_an_EMPTY_RDF_graph_with_a_valid_ID_for_NO_annotation_on_the_server.yml +3623 -0
  67. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/with_no_content_type/returns_an_RDF_graph_with_a_valid_ID_for_an_annotation_on_the_server.yml +4946 -0
  68. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/checks_the_annotation_ID.yml +2502 -0
  69. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/logs_exceptions.yml +2502 -0
  70. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/raises_an_argument_error_with_a_nil_ID.yml +2502 -0
  71. 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 +2502 -0
  72. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_annotation/without_content_type/raises_an_argument_error_with_an_integer_ID.yml +2502 -0
  73. 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 +2502 -0
  74. 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 +2502 -0
  75. 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 +3328 -0
  76. 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 +4946 -0
  77. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_iiif_annotation/requests_an_open_annotation_by_ID_using_a_IIIF_profile.yml +2746 -0
  78. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_iiif_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml +2746 -0
  79. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_oa_annotation/requests_an_open_annotation_by_ID_using_an_OA_profile.yml +4946 -0
  80. data/spec/fixtures/vcr_cassettes/TriannonClient/GET_annotation_by_ID_/_get_oa_annotation/returns_an_RDF_Graph_of_an_open_annotation.yml +4946 -0
  81. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/deletes_an_open_annotation_that_exists.yml +2548 -0
  82. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/fails_to_delete_an_open_annotation_that_does_NOT_exist.yml +123 -0
  83. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_false_for_a_500_response_to_a_DELETE_request.yml +64 -0
  84. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_true_for_a_200_response_to_a_DELETE_request.yml +64 -0
  85. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_true_for_a_202_response_to_a_DELETE_request.yml +64 -0
  86. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/returns_true_for_a_204_response_to_a_DELETE_request.yml +64 -0
  87. data/spec/fixtures/vcr_cassettes/TriannonClient/_delete_annotation/validates_the_annotation_ID.yml +64 -0
  88. data/spec/fixtures/vcr_cassettes/TriannonClient/_get_annotations/returns_an_RDF_Graph.yml +295 -0
  89. data/spec/fixtures/vcr_cassettes/TriannonClient/_get_annotations/returns_an_RDF_Graph_that_contains_an_AnnotationList.yml +295 -0
  90. data/spec/fixtures/vcr_cassettes/TriannonClient/_get_annotations/returns_an_annotation_list_with_an_annotation_created_by_a_prior_POST.yml +2795 -0
  91. data/spec/fixtures/vcr_cassettes/TriannonClient/_post_annotation/does_not_raise_an_error_when_submitting_a_valid_open_annotation.yml +2502 -0
  92. data/spec/fixtures/vcr_cassettes/TriannonClient/_post_annotation/returns_a_RestClient_Response_object.yml +2502 -0
  93. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_id/returns_a_String_ID_from_the_RDF_URI_of_an_annotation.yml +2502 -0
  94. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_id/returns_a_String_ID_that_is_not_empty.yml +2502 -0
  95. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_uri/returns_an_RDF_URI_from_an_RDF_Graph_of_an_annotation.yml +2502 -0
  96. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_annotation_uri/returns_an_RDF_URI_that_is_a_valid_URI.yml +2550 -0
  97. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/accepts_a_RestClient_Response_instance.yml +4898 -0
  98. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/raises_ArgumentError_when_given_an_empty_String.yml +2502 -0
  99. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/raises_ArgumentError_when_given_nil.yml +2502 -0
  100. data/spec/fixtures/vcr_cassettes/TriannonClient/response_processing_utilities/_response2graph/returns_an_RDF_Graph.yml +2502 -0
  101. data/spec/lib/triannon-client/triannon_client_spec.rb +502 -0
  102. data/spec/spec_helper.rb +12 -1
  103. data/triannon-client.gemspec +5 -2
  104. metadata +234 -7
  105. data/Gemfile.lock +0 -203
  106. data/lib/triannon-client/triannon-client.rb +0 -135
  107. data/spec/lib/triannon-client/triannon-client_spec.rb +0 -44
@@ -0,0 +1,502 @@
1
+ require 'spec_helper'
2
+
3
+ # ::TriannonClient::TriannonClient class specs
4
+
5
+ describe TriannonClient, :vcr do
6
+
7
+ before :all do
8
+ Dotenv.load
9
+ @oa_jsonld = '{"@context":"http://iiif.io/api/presentation/2/context.json","@graph":[{"@id":"_:g70349699654640","@type":["dctypes:Text","cnt:ContentAsText"],"chars":"I love this!","format":"text/plain","language":"en"},{"@type":"oa:Annotation","motivation":"oa:commenting","on":"http://purl.stanford.edu/kq131cs7229","resource":"_:g70349699654640"}]}'
10
+ end
11
+
12
+ let(:tc) { TriannonClient::TriannonClient.new }
13
+
14
+ # Note: not using `let` approach for these methods because it
15
+ # makes it very difficult to delete any annotations created by
16
+ # the `tc.post_annotation`; so the `create_annotation` and the
17
+ # `delete_annotation` methods are used in several before/after
18
+ # blocks within describe blocks, as required.
19
+ # let(:post_response) { tc.post_annotation(@oa_jsonld) }
20
+ # let(:anno_graph) { tc.response2graph(post_response) }
21
+ # let(:anno_uri) { tc.annotation_uri(anno_graph) }
22
+ # let(:anno_id) { tc.annotation_id(anno_uri) }
23
+
24
+ def create_annotation
25
+ r = tc.post_annotation(@oa_jsonld)
26
+ g = tc.response2graph(r)
27
+ uri = tc.annotation_uri(g)
28
+ id = tc.annotation_id(uri)
29
+ {
30
+ response: r,
31
+ graph: g,
32
+ uri: uri,
33
+ id: id
34
+ }
35
+ end
36
+
37
+ def delete_annotation(id)
38
+ tc.delete_annotation(id)
39
+ end
40
+
41
+ def graph_has_statements(graph)
42
+ expect(graph).to be_instance_of RDF::Graph
43
+ expect(graph).not_to be_empty
44
+ expect(graph.size).to be > 2
45
+ end
46
+
47
+ def graph_is_empty(graph)
48
+ expect(graph).to be_instance_of RDF::Graph
49
+ expect(graph).to be_empty
50
+ end
51
+
52
+ def graph_contains_open_annotation(graph, uri)
53
+ result = graph.query([nil, RDF.type, RDF::Vocab::OA.Annotation])
54
+ expect(result.size).to be > 0
55
+ expect(result.each_subject.collect{|s| s}).to include(uri)
56
+ end
57
+
58
+ describe 'has constants:' do
59
+ it 'CONTENT_TYPES' do
60
+ const = TriannonClient::TriannonClient::CONTENT_TYPES
61
+ expect(const).to be_instance_of Array
62
+ expect(const).to include('application/ld+json')
63
+ end
64
+ it 'PROFILE_TYPE_IIIF' do
65
+ const = TriannonClient::TriannonClient::PROFILE_IIIF
66
+ expect(const).to be_instance_of String
67
+ expect(const).to include('http://iiif.io/api/presentation/2/context.json')
68
+ end
69
+ it 'PROFILE_TYPE_OA' do
70
+ const = TriannonClient::TriannonClient::PROFILE_OA
71
+ expect(const).to be_instance_of String
72
+ expect(const).to include('http://www.w3.org/ns/oa-context-20130208.json')
73
+ end
74
+ it 'CONTENT_TYPE_IIIF' do
75
+ const = TriannonClient::TriannonClient::CONTENT_TYPE_IIIF
76
+ expect(const).to be_instance_of String
77
+ expect(const).to include('application/ld+json')
78
+ expect(const).to include('http://iiif.io/api/presentation/2/context.json')
79
+ end
80
+ it 'CONTENT_TYPE_OA' do
81
+ const = TriannonClient::TriannonClient::CONTENT_TYPE_OA
82
+ expect(const).to be_instance_of String
83
+ expect(const).to include('application/ld+json')
84
+ expect(const).to include('http://www.w3.org/ns/oa-context-20130208.json')
85
+ end
86
+ it 'JSONLD_TYPE' do
87
+ const = TriannonClient::TriannonClient::JSONLD_TYPE
88
+ expect(const).to be_instance_of String
89
+ expect(const).to eql('application/ld+json')
90
+ end
91
+ end
92
+
93
+ describe 'has public methods:' do
94
+ it 'delete_annotation' do
95
+ expect(tc).to respond_to(:delete_annotation)
96
+ end
97
+ it 'get_annotations' do
98
+ expect(tc).to respond_to(:get_annotations)
99
+ end
100
+ it 'get_annotation' do
101
+ expect(tc).to respond_to(:get_annotation)
102
+ end
103
+ it 'get_iiif_annotation' do
104
+ expect(tc).to respond_to(:get_iiif_annotation)
105
+ end
106
+ it 'get_oa_annotation' do
107
+ expect(tc).to respond_to(:get_oa_annotation)
108
+ end
109
+ it 'site' do
110
+ expect(tc).to respond_to(:site)
111
+ end
112
+ # utilities
113
+ it 'response2graph' do
114
+ expect(tc).to respond_to(:response2graph)
115
+ end
116
+ it 'annotation_id' do
117
+ expect(tc).to respond_to(:annotation_id)
118
+ end
119
+ it 'annotation_uri' do
120
+ expect(tc).to respond_to(:annotation_uri)
121
+ end
122
+ end
123
+
124
+ describe 'has private methods:' do
125
+ it 'check_id' do
126
+ expect(tc).not_to respond_to(:check_id)
127
+ end
128
+ it 'check_content_type' do
129
+ expect(tc).not_to respond_to(:check_content_type)
130
+ end
131
+ end
132
+
133
+ describe "#delete_annotation" do
134
+ def test_delete_for_response_code(status, response)
135
+ allow_any_instance_of(RestClient::Response).to receive(:code).and_return(status)
136
+ expect(tc.delete_annotation('anything_here_is_OK')).to be response
137
+ end
138
+ it "returns false for a 500 response to a DELETE request" do
139
+ test_delete_for_response_code(500, false)
140
+ end
141
+ it "returns true for a 200 response to a DELETE request" do
142
+ test_delete_for_response_code(200, true)
143
+ end
144
+ it "returns true for a 202 response to a DELETE request" do
145
+ test_delete_for_response_code(202, true)
146
+ end
147
+ it "returns true for a 204 response to a DELETE request" do
148
+ test_delete_for_response_code(204, true)
149
+ end
150
+ it 'validates the annotation ID' do
151
+ expect(tc).to receive(:check_id)
152
+ tc.delete_annotation('anything_here_is_OK')
153
+ end
154
+ it 'deletes an open annotation that exists' do
155
+ anno = create_annotation
156
+ expect( tc.delete_annotation(anno[:id]) ).to be true
157
+ graph = tc.get_annotation(anno[:id])
158
+ graph_is_empty(graph)
159
+ end
160
+ it 'fails to delete an open annotation that does NOT exist' do
161
+ id = 'anno_does_not_exist'
162
+ graph = tc.get_annotation(id)
163
+ graph_is_empty(graph)
164
+ expect( tc.delete_annotation(id) ).to be false
165
+ end
166
+ it 'logs exceptions' do
167
+ allow_any_instance_of(RestClient::Resource).to receive(:delete).and_raise('delete_exception')
168
+ expect(TriannonClient.configuration.logger).to receive(:error).with(/delete_exception/)
169
+ tc.delete_annotation('raise_delete_exception')
170
+ end
171
+ it 'quits after detecting an invalid annotation ID' do
172
+ expect_any_instance_of(RestClient::Resource).not_to receive(:delete)
173
+ tc.delete_annotation('') rescue nil
174
+ tc.delete_annotation(nil) rescue nil
175
+ end
176
+ it 'uses RestClient::Resource.delete to DELETE a valid annotation ID' do
177
+ expect_any_instance_of(RestClient::Resource).to receive(:delete)
178
+ tc.delete_annotation(SecureRandom.uuid)
179
+ end
180
+ end
181
+
182
+ describe "#get_annotations" do
183
+ it 'returns an RDF::Graph' do
184
+ graph = tc.get_annotations
185
+ graph_has_statements(graph)
186
+ end
187
+ it 'returns an RDF::Graph that contains an AnnotationList' do
188
+ graph = tc.get_annotations
189
+ anno_list_uri = RDF::URI.parse('http://iiif.io/api/presentation/2#AnnotationList')
190
+ result = graph.query([nil, nil, anno_list_uri])
191
+ expect(result.size).to eql(1)
192
+ end
193
+ it 'returns an annotation list with an annotation created by a prior POST' do
194
+ anno = create_annotation
195
+ graph = tc.get_annotations
196
+ graph_contains_open_annotation(graph, anno[:uri])
197
+ delete_annotation(anno[:id])
198
+ end
199
+ end
200
+
201
+ describe "GET annotation by ID:" do
202
+ before(:example) do
203
+ # create a new annotation and call all the response processing utils.
204
+ @anno = create_annotation
205
+ end
206
+ after(:example) do
207
+ delete_annotation(@anno[:id]) # cleanup after create_annotation
208
+ end
209
+
210
+ describe "#get_annotation" do
211
+ context 'with content_type' do
212
+ # Content types could be supported for RDF::Format.content_types.keys,
213
+ # but not all of them are supported. The supported content types for
214
+ # triannon are defined in
215
+ # https://github.com/sul-dlss/triannon/blob/master/config/initializers/mime_types.rb
216
+ # https://github.com/sul-dlss/triannon/blob/master/app/controllers/triannon/annotations_controller.rb
217
+ # https://github.com/sul-dlss/triannon/blob/master/app/controllers/triannon/search_controller.rb
218
+ # The default content type is "application/ld+json" and, at the time of
219
+ # writing, triannon also supports:
220
+ # turtle as: ["application/x-turtle", "text/turtle"]
221
+ # rdf+xml as: ["application/rdf+xml", "text/rdf+xml", "text/rdf"]
222
+ # json as: ["application/json", "text/x-json", "application/jsonrequest"]
223
+ # xml as: ["application/xml", "text/xml", "application/x-xml"]
224
+ # html
225
+ def request_anno_with_content_type(content_type)
226
+ expect_any_instance_of(RestClient::Resource).to receive(:get).with(hash_including(:accept => content_type) )
227
+ tc.get_annotation(@anno[:id], content_type)
228
+ end
229
+ def gets_anno_with_content_type(content_type)
230
+ graph = tc.get_annotation(@anno[:id], content_type)
231
+ graph_has_statements(graph)
232
+ graph_contains_open_annotation(graph, @anno[:uri])
233
+ end
234
+ def cannot_get_anno_with_content_type(content_type)
235
+ graph = tc.get_annotation(@anno[:id], content_type)
236
+ graph_is_empty(graph)
237
+ end
238
+ # "text/plain",
239
+ # "text/html",
240
+ # "application/xhtml+xml",
241
+ it 'requests an open annotation by ID, with content type "application/ld+json"' do
242
+ request_anno_with_content_type("application/ld+json")
243
+ end
244
+ it 'gets an open annotation by ID, with content type "application/ld+json"' do
245
+ gets_anno_with_content_type("application/ld+json")
246
+ end
247
+ it 'requests an open annotation by ID, with content type "application/x-ld+json"' do
248
+ request_anno_with_content_type("application/x-ld+json")
249
+ end
250
+ it 'cannot get an open annotation by ID, with content type "application/x-ld+json"' do
251
+ cannot_get_anno_with_content_type("application/x-ld+json")
252
+ end
253
+ it 'requests an open annotation by ID, with content type "application/rdf+json"' do
254
+ request_anno_with_content_type("application/rdf+json")
255
+ end
256
+ it 'cannot get an open annotation by ID, with content type "application/rdf+json"' do
257
+ cannot_get_anno_with_content_type("application/rdf+json")
258
+ end
259
+ it 'requests an open annotation by ID, with content type "application/rdf+xml"' do
260
+ request_anno_with_content_type("application/rdf+xml")
261
+ end
262
+ it 'gets an open annotation by ID, with content type "application/rdf+xml"' do
263
+ gets_anno_with_content_type("application/rdf+xml")
264
+ end
265
+ it 'requests an open annotation by ID, with content type "text/turtle"' do
266
+ request_anno_with_content_type("text/turtle")
267
+ end
268
+ it 'gets an open annotation by ID, with content type "text/turtle"' do
269
+ gets_anno_with_content_type("text/turtle")
270
+ end
271
+ it 'requests an open annotation by ID, with content type "text/rdf+turtle"' do
272
+ request_anno_with_content_type("text/rdf+turtle")
273
+ end
274
+ it 'cannot get an open annotation by ID, with content type "text/rdf+turtle"' do
275
+ cannot_get_anno_with_content_type("text/rdf+turtle")
276
+ end
277
+ it 'requests an open annotation by ID, with content type "application/turtle"' do
278
+ request_anno_with_content_type("application/turtle")
279
+ end
280
+ it 'cannot get an open annotation by ID, with content type "application/turtle"' do
281
+ cannot_get_anno_with_content_type("application/turtle")
282
+ end
283
+ it 'requests an open annotation by ID, with content type "application/x-turtle"' do
284
+ request_anno_with_content_type("application/x-turtle")
285
+ end
286
+ it 'gets an open annotation by ID, with content type "application/x-turtle"' do
287
+ gets_anno_with_content_type("application/x-turtle")
288
+ end
289
+ it 'requests an open annotation by ID, with content type "application/n-triples"' do
290
+ request_anno_with_content_type("application/n-triples")
291
+ end
292
+ it 'cannot get an open annotation by ID, with content type "application/n-triples"' do
293
+ cannot_get_anno_with_content_type("application/n-triples")
294
+ end
295
+ it 'requests an open annotation by ID, with content type "application/rdf+n3"' do
296
+ request_anno_with_content_type("application/rdf+n3")
297
+ end
298
+ it 'cannot get an open annotation by ID, with content type "application/rdf+n3"' do
299
+ cannot_get_anno_with_content_type("application/rdf+n3")
300
+ end
301
+ it 'requests an open annotation by ID, with content type "text/n3"' do
302
+ request_anno_with_content_type("text/n3")
303
+ end
304
+ it 'cannot get an open annotation by ID, with content type "text/n3"' do
305
+ cannot_get_anno_with_content_type("text/n3")
306
+ end
307
+ it 'requests an open annotation by ID, with content type "text/rdf+n3"' do
308
+ request_anno_with_content_type("text/rdf+n3")
309
+ end
310
+ it 'cannot get an open annotation by ID, with content type "text/rdf+n3"' do
311
+ cannot_get_anno_with_content_type("text/rdf+n3")
312
+ end
313
+ it 'requests an open annotation by ID, with content type "application/n-quads"' do
314
+ request_anno_with_content_type("application/n-quads")
315
+ end
316
+ it 'cannot get an open annotation by ID, with content type "application/n-quads"' do
317
+ cannot_get_anno_with_content_type("application/n-quads")
318
+ end
319
+ it 'requests an open annotation by ID, with content type "text/x-nquads"' do
320
+ request_anno_with_content_type("text/x-nquads")
321
+ end
322
+ it 'cannot get an open annotation by ID, with content type "text/x-nquads"' do
323
+ cannot_get_anno_with_content_type("text/x-nquads")
324
+ end
325
+ it 'requests an open annotation by ID, with content type "application/trig"' do
326
+ request_anno_with_content_type("application/trig")
327
+ end
328
+ it 'cannot get an open annotation by ID, with content type "application/trig"' do
329
+ cannot_get_anno_with_content_type("application/trig")
330
+ end
331
+ it 'requests an open annotation by ID, with content type "application/x-trig"' do
332
+ request_anno_with_content_type("application/x-trig")
333
+ end
334
+ it 'cannot get an open annotation by ID, with content type "application/x-trig"' do
335
+ cannot_get_anno_with_content_type("application/x-trig")
336
+ end
337
+ it 'requests an open annotation by ID, with content type "application/trix"' do
338
+ request_anno_with_content_type("application/trix")
339
+ end
340
+ it 'cannot get an open annotation by ID, with content type "application/trix"' do
341
+ cannot_get_anno_with_content_type("application/trix")
342
+ end
343
+ end
344
+ context 'without content_type' do
345
+ it 'requests an open annotation by ID, accepting a default JSON-LD content' do
346
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
347
+ content_type = TriannonClient::TriannonClient::JSONLD_TYPE
348
+ expect_any_instance_of(RestClient::Resource).to receive(:get).with(hash_including(:accept => content_type) )
349
+ tc.get_annotation(@anno[:id])
350
+ end
351
+ it 'checks the annotation ID' do
352
+ expect(tc).to receive(:check_id) # tested by #create_annotation
353
+ graph_has_statements(@anno[:graph]) # check #create_annotation worked
354
+ end
355
+ it 'raises an argument error with a nil ID' do
356
+ expect{tc.get_annotation(nil)}.to raise_error(ArgumentError)
357
+ end
358
+ it 'raises an argument error with an integer ID' do
359
+ expect{tc.get_annotation(0)}.to raise_error(ArgumentError)
360
+ end
361
+ it 'raises an argument error with an empty string ID' do
362
+ expect{tc.get_annotation('')}.to raise_error(ArgumentError)
363
+ end
364
+ it 'returns an RDF graph with a valid ID for an annotation on the server' do
365
+ graph = tc.get_annotation(@anno[:id])
366
+ graph_has_statements(graph)
367
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
368
+ end
369
+ it 'returns an EMPTY RDF graph with a valid ID for NO annotation on the server' do
370
+ id = SecureRandom.uuid
371
+ graph = tc.get_annotation(id)
372
+ graph_is_empty(graph)
373
+ end
374
+ it 'returns an EMPTY RDF graph for a 500 server response' do
375
+ response = double
376
+ allow(response).to receive(:is_a?).and_return(RestClient::Response)
377
+ allow(response).to receive(:headers).and_return({content_type: 'application/ld+json'})
378
+ allow(response).to receive(:code).and_return(500)
379
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return(response)
380
+ graph = tc.get_annotation(@anno[:id])
381
+ graph_is_empty(graph)
382
+ end
383
+ it 'logs exceptions' do
384
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_raise('get_exception')
385
+ expect(TriannonClient.configuration.logger).to receive(:error).with(/get_exception/)
386
+ tc.get_annotation('raise_get_exception')
387
+ end
388
+ end
389
+ end
390
+
391
+ describe "#get_iiif_annotation" do
392
+ # the mime type is fixed for this method
393
+ it 'requests an open annotation by ID, using a IIIF profile' do
394
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
395
+ content_type = TriannonClient::TriannonClient::CONTENT_TYPE_IIIF
396
+ expect(tc).to receive(:get_annotation).with(@anno[:id], content_type)
397
+ tc.get_iiif_annotation(@anno[:id])
398
+ end
399
+ it 'returns an RDF::Graph of an open annotation' do
400
+ graph = tc.get_iiif_annotation(@anno[:id])
401
+ graph_has_statements(graph)
402
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
403
+ end
404
+ end
405
+
406
+ describe "#get_oa_annotation" do
407
+ # the mime type is fixed for this method
408
+ it 'requests an open annotation by ID, using an OA profile' do
409
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
410
+ content_type = TriannonClient::TriannonClient::CONTENT_TYPE_OA
411
+ expect(tc).to receive(:get_annotation).with(@anno[:id], content_type)
412
+ tc.get_oa_annotation(@anno[:id])
413
+ end
414
+ it 'returns an RDF::Graph of an open annotation' do
415
+ graph = tc.get_oa_annotation(@anno[:id])
416
+ graph_has_statements(graph)
417
+ graph_contains_open_annotation(@anno[:graph], @anno[:uri])
418
+ end
419
+ end
420
+
421
+ end
422
+
423
+ describe "#post_annotation" do
424
+ it 'does not raise an error when submitting a valid open annotation' do
425
+ response = nil
426
+ expect do
427
+ response = tc.post_annotation(@oa_jsonld)
428
+ end.not_to raise_error
429
+ # Double check the POST by deleting the annotation.
430
+ # If the POST was successful, the DELETE should work too.
431
+ graph = tc.response2graph(response)
432
+ uri = tc.annotation_uri(graph)
433
+ id = tc.annotation_id(uri)
434
+ expect(tc.delete_annotation(id)).to be true
435
+ end
436
+ it 'returns a RestClient::Response object' do
437
+ # The response behaves primarily as a String, so it can not be tested
438
+ # as an instance of RestClient::Response, but it can be tested to respond
439
+ # to RestClient::Response methods.
440
+ anno = create_annotation
441
+ r = anno[:response]
442
+ expect(r.is_a? RestClient::Response).to be true
443
+ expect(r).to respond_to(:code)
444
+ expect(r).to respond_to(:body)
445
+ expect(r).to respond_to(:headers)
446
+ delete_annotation(anno[:id]) # cleanup after create_annotation
447
+ end
448
+ end
449
+
450
+
451
+ describe 'response processing utilities' do
452
+
453
+ before(:example) do
454
+ # create a new annotation and call all the response processing utils.
455
+ @anno = create_annotation
456
+ end
457
+ after(:example) do
458
+ delete_annotation(@anno[:id]) # cleanup after create_annotation
459
+ end
460
+
461
+ describe '#response2graph' do
462
+ it 'accepts a RestClient::Response instance' do
463
+ r = @anno[:response]
464
+ expect{tc.response2graph(r)}.not_to raise_error
465
+ end
466
+ it 'raises ArgumentError when given nil' do
467
+ expect{tc.response2graph(nil)}.to raise_error(ArgumentError)
468
+ end
469
+ it 'raises ArgumentError when given an empty String' do
470
+ expect{tc.response2graph('')}.to raise_error(ArgumentError)
471
+ end
472
+ it 'returns an RDF::Graph' do
473
+ expect(@anno[:graph]).to be_instance_of RDF::Graph
474
+ end
475
+ end
476
+
477
+ describe "#annotation_uri" do
478
+ it "returns an RDF::URI from an RDF::Graph of an annotation" do
479
+ expect(@anno[:graph]).to be_instance_of RDF::Graph
480
+ expect(@anno[:uri]).to be_instance_of RDF::URI
481
+ end
482
+ it "returns an RDF::URI that is a valid URI" do
483
+ expect(@anno[:uri]).to match(/\A#{URI::regexp}\z/)
484
+ delete_annotation(@anno[:id]) # cleanup after create_annotation
485
+ end
486
+ end
487
+
488
+ describe "#annotation_id" do
489
+ it "returns a String ID from the RDF::URI of an annotation" do
490
+ expect(@anno[:uri]).to be_instance_of RDF::URI
491
+ expect(@anno[:id]).to be_instance_of String
492
+ end
493
+ it "returns a String ID that is not empty" do
494
+ expect(@anno[:id]).to be_instance_of String
495
+ expect(@anno[:id].empty?).to be false
496
+ end
497
+ end
498
+
499
+ end
500
+
501
+ end
502
+