rdf-ldp 0.9.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,242 @@
1
+ require 'rspec'
2
+ require 'rdf/spec'
3
+ require 'rdf/spec/matchers'
4
+ require 'timecop'
5
+
6
+ shared_examples 'a Resource' do
7
+ describe '.to_uri' do
8
+ it { expect(described_class.to_uri).to be_a RDF::URI }
9
+ end
10
+
11
+ subject { described_class.new(uri) }
12
+ let(:uri) { RDF::URI 'http://example.org/moomin' }
13
+
14
+ it { is_expected.to be_ldp_resource }
15
+ it { is_expected.to respond_to :container? }
16
+ it { is_expected.to respond_to :rdf_source? }
17
+ it { is_expected.to respond_to :non_rdf_source? }
18
+
19
+ it { subject.send(:set_last_modified) }
20
+
21
+ describe '#exists?' do
22
+ it 'does not exist' do
23
+ expect(subject).not_to exist
24
+ end
25
+
26
+ context 'while existing' do
27
+ before { subject.create(StringIO.new, 'application/n-triples') }
28
+
29
+ subject { described_class.new(uri, repository) }
30
+ let(:repository) { RDF::Repository.new }
31
+
32
+ it 'exists' do
33
+ expect(subject).to exist
34
+ end
35
+
36
+ it 'is different from same URI with trailing /' do
37
+ expect(described_class.new(uri + '/', repository)).not_to exist
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#allowed_methods' do
43
+ it 'responds to all methods returned' do
44
+ subject.allowed_methods.each do |method|
45
+ expect(subject.respond_to?(method.downcase, true)).to be true
46
+ end
47
+ end
48
+
49
+ it 'includes the MUST methods' do
50
+ expect(subject.allowed_methods).to include(:GET, :OPTIONS, :HEAD)
51
+ end
52
+ end
53
+
54
+ describe '#create' do
55
+ it 'accepts two args' do
56
+ expect(described_class.instance_method(:create).arity).to eq 2
57
+ end
58
+
59
+ describe 'modified time' do
60
+ before { Timecop.freeze }
61
+ after { Timecop.return }
62
+
63
+ it 'sets last_modified' do
64
+ subject.create(StringIO.new, 'text/turtle')
65
+ expect(subject.last_modified).to eq DateTime.now
66
+ end
67
+ end
68
+
69
+ it 'adds a type triple to metagraph' do
70
+ subject.create(StringIO.new, 'application/n-triples')
71
+ expect(subject.metagraph)
72
+ .to have_statement RDF::Statement(subject.subject_uri,
73
+ RDF.type,
74
+ described_class.to_uri)
75
+ end
76
+
77
+ it 'yields a transaction' do
78
+ expect { |b| subject.create(StringIO.new, 'application/n-triples', &b) }
79
+ .to yield_with_args(be_kind_of(RDF::Transaction))
80
+ end
81
+
82
+ it 'marks resource as existing' do
83
+ expect { subject.create(StringIO.new, 'application/n-triples') }
84
+ .to change { subject.exists? }.from(false).to(true)
85
+ end
86
+
87
+ it 'returns self' do
88
+ expect(subject.create(StringIO.new, 'application/n-triples'))
89
+ .to eq subject
90
+ end
91
+
92
+ it 'raises Conlict when already exists' do
93
+ subject.create(StringIO.new, 'application/n-triples')
94
+ expect { subject.create(StringIO.new, 'application/n-triples') }
95
+ .to raise_error RDF::LDP::Conflict
96
+ end
97
+ end
98
+
99
+ describe '#update' do
100
+ it 'accepts two args' do
101
+ expect(described_class.instance_method(:update).arity).to eq 2
102
+ end
103
+
104
+ it 'returns self' do
105
+ expect(subject.update(StringIO.new, 'application/n-triples'))
106
+ .to eq subject
107
+ end
108
+
109
+ it 'yields a changeset' do
110
+ expect { |b| subject.update(StringIO.new, 'application/n-triples', &b) }
111
+ .to yield_with_args(be_kind_of(RDF::Transaction))
112
+ end
113
+ end
114
+
115
+ describe '#destroy' do
116
+ it 'accepts no args' do
117
+ expect(described_class.instance_method(:destroy).arity).to eq 0
118
+ end
119
+ end
120
+
121
+ describe '#metagraph' do
122
+ it 'returns a graph' do
123
+ expect(subject.metagraph).to be_a RDF::Graph
124
+ end
125
+
126
+ it 'has the metagraph name for the resource' do
127
+ expect(subject.metagraph.graph_name).to eq subject.subject_uri / '#meta'
128
+ end
129
+ end
130
+
131
+ describe '#etag' do
132
+ before { subject.create(StringIO.new, 'application/n-triples') }
133
+
134
+ it 'has an etag' do
135
+ expect(subject.etag).to be_a String
136
+ end
137
+
138
+ it 'updates etag on change' do
139
+ expect { subject.update(StringIO.new, 'application/n-triples') }
140
+ .to change { subject.etag }
141
+ end
142
+ end
143
+
144
+ describe '#last_modified' do
145
+ it 'returns nil when no dc:modified triple is present' do
146
+ expect(subject.last_modified).to be_nil
147
+ end
148
+
149
+ it 'raises an error when exists without dc:modified triple is present' do
150
+ allow(subject).to receive(:exists?).and_return true
151
+ expect { subject.last_modified }.to raise_error RDF::LDP::RequestError
152
+ end
153
+
154
+ context 'with dc:modified triple' do
155
+ before do
156
+ subject.metagraph.update([subject.subject_uri,
157
+ RDF::Vocab::DC.modified,
158
+ datetime])
159
+ end
160
+
161
+ let(:datetime) { DateTime.now }
162
+
163
+ it 'returns date in `dc:modified`' do
164
+ expect(subject.last_modified).to eq datetime
165
+ end
166
+ end
167
+ end
168
+
169
+ describe '#to_response' do
170
+ it 'returns an object that responds to #each' do
171
+ expect(subject.to_response).to respond_to :each
172
+ end
173
+ end
174
+
175
+ describe '#request' do
176
+ it 'sends the message to itself' do
177
+ expect(subject).to receive(:blah)
178
+ subject.request(:BLAH, 200, {}, {})
179
+ end
180
+
181
+ it 'raises MethodNotAllowed when method is unimplemented' do
182
+ allow(subject).to receive(:not_implemented)
183
+ .and_raise NotImplementedError
184
+ expect { subject.request(:not_implemented, 200, {}, {}) }
185
+ .to raise_error(RDF::LDP::MethodNotAllowed)
186
+ end
187
+
188
+ [:GET, :OPTIONS, :HEAD].each do |method|
189
+ it "responds to #{method}" do
190
+ expect(subject.request(method, 200, {}, {}).size).to eq 3
191
+ end
192
+ end
193
+
194
+ [:PATCH, :POST, :PUT, :DELETE, :TRACE, :CONNECT].each do |method|
195
+ it "responds to or errors on #{method}" do
196
+ g = RDF::Graph.new << [RDF::Node.new, RDF.type, 'moomin']
197
+ env = { 'CONTENT_TYPE' => 'application/n-triples',
198
+ 'rack.input' => StringIO.new(g.dump(:ntriples)) }
199
+
200
+ begin
201
+ response = subject.request(method, 200, {}, env)
202
+ expect(response.size).to eq 3
203
+ rescue => e
204
+ expect(e).to be_a RDF::LDP::RequestError
205
+ end
206
+ end
207
+ end
208
+
209
+ describe 'HTTP headers' do
210
+ before { subject.create(StringIO.new, 'text/turtle') }
211
+ let(:headers) { subject.request(:GET, 200, {}, {})[1] }
212
+
213
+ it 'has ETag' do
214
+ expect(headers['ETag']).to eq subject.etag
215
+ end
216
+
217
+ it 'has Last-Modified' do
218
+ expect(headers['Last-Modified']).to eq subject.last_modified.httpdate
219
+ end
220
+
221
+ it 'has Allow' do
222
+ expect(headers['Allow']).to be_a String
223
+ end
224
+
225
+ it 'has Link' do
226
+ expect(headers['Link']).to be_a String
227
+ end
228
+ end
229
+
230
+ it 'responds to :GET' do
231
+ expect { subject.request(:GET, 200, {}, {}) }.not_to raise_error
232
+ end
233
+
234
+ it 'responds to :HEAD' do
235
+ expect { subject.request(:OPTIONS, 200, {}, {}) }.not_to raise_error
236
+ end
237
+
238
+ it 'responds to :OPTIONS' do
239
+ expect { subject.request(:OPTIONS, 200, {}, {}) }.not_to raise_error
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,6 @@
1
+ require 'rdf/ldp/spec/resource'
2
+ require 'rdf/ldp/spec/rdf_source'
3
+ require 'rdf/ldp/spec/non_rdf_source'
4
+ require 'rdf/ldp/spec/container'
5
+ require 'rdf/ldp/spec/direct_container'
6
+ require 'rdf/ldp/spec/indirect_container'
@@ -63,7 +63,7 @@ module RDF::LDP
63
63
  #
64
64
  # @return [IO] an object conforming to the Ruby IO interface
65
65
  def io(&block)
66
- FileUtils.mkdir_p(path_dir) unless Dir.exists?(path_dir)
66
+ FileUtils.mkdir_p(path_dir) unless Dir.exist?(path_dir)
67
67
  FileUtils.touch(path) unless file_exists?
68
68
 
69
69
  File.open(path, 'r+b', &block)
@@ -72,7 +72,7 @@ module RDF::LDP
72
72
  ##
73
73
  # @return [Boolean] 1 if the file has been deleted, otherwise false
74
74
  def delete
75
- return false unless File.exists?(path)
75
+ return false unless File.exist?(path)
76
76
  File.delete(path)
77
77
  end
78
78
 
@@ -81,7 +81,7 @@ module RDF::LDP
81
81
  ##
82
82
  # @return [Boolean]
83
83
  def file_exists?
84
- File.exists?(path)
84
+ File.exist?(path)
85
85
  end
86
86
 
87
87
  ##
@@ -99,4 +99,4 @@ module RDF::LDP
99
99
  end
100
100
  end
101
101
  end
102
- end
102
+ end
@@ -1,4 +1,11 @@
1
1
  module RDF::LDP
2
+ ##
3
+ # Version Number
4
+ #
5
+ # @example getting a version string
6
+ # RDF::LDP::VERSION # or
7
+ # "#{RDF::LDP::VERSION}"
8
+ #
2
9
  module VERSION
3
10
  FILE = File.expand_path('../../../../VERSION', __FILE__)
4
11
  MAJOR, MINOR, TINY, EXTRA = File.read(FILE).chomp.split('.')
@@ -6,14 +13,20 @@ module RDF::LDP
6
13
 
7
14
  ##
8
15
  # @return [String]
9
- def self.to_s() STRING end
16
+ def self.to_s
17
+ STRING
18
+ end
10
19
 
11
20
  ##
12
21
  # @return [String]
13
- def self.to_str() STRING end
22
+ def self.to_str
23
+ STRING
24
+ end
14
25
 
15
26
  ##
16
27
  # @return [Array(Integer, Integer, Integer)]
17
- def self.to_a() [MAJOR, MINOR, TINY] end
28
+ def self.to_a
29
+ [MAJOR, MINOR, TINY]
30
+ end
18
31
  end
19
32
  end
data/lib/rdf/ldp.rb CHANGED
@@ -19,14 +19,15 @@ module RDF
19
19
  # Rack servers.
20
20
  #
21
21
  # @see RDF::LDP::Resource
22
- # @see http://www.w3.org/TR/ldp/ for the Linked Data platform specification
22
+ # @see https://www.w3.org/TR/ldp/ for the Linked Data platform specification
23
23
  module LDP
24
24
  InteractionModel.register(RDF::LDP::RDFSource, default: true)
25
- InteractionModel.register(RDF::LDP::Container, for: RDF::Vocab::LDP.BasicContainer)
25
+ InteractionModel.register(RDF::LDP::Container,
26
+ for: RDF::Vocab::LDP.BasicContainer)
26
27
  InteractionModel.register(RDF::LDP::DirectContainer)
27
28
  InteractionModel.register(RDF::LDP::IndirectContainer)
28
29
  InteractionModel.register(RDF::LDP::NonRDFSource)
29
-
30
+
30
31
  CONTAINER_CLASSES = {
31
32
  basic: RDF::Vocab::LDP.BasicContainer.freeze,
32
33
  direct: RDF::LDP::DirectContainer.to_uri.freeze,