rdf-tabular 0.3.0 → 0.4.0.beta2
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/README.md +3 -2
- data/VERSION +1 -1
- data/lib/rdf/tabular.rb +0 -1
- data/lib/rdf/tabular/format.rb +16 -0
- data/lib/rdf/tabular/metadata.rb +223 -191
- data/lib/rdf/tabular/reader.rb +84 -133
- data/lib/rdf/tabular/uax35.rb +0 -2
- data/spec/format_spec.rb +34 -0
- data/spec/matchers.rb +3 -78
- data/spec/metadata_spec.rb +150 -80
- data/spec/reader_spec.rb +27 -24
- data/spec/spec_helper.rb +4 -3
- data/spec/suite_helper.rb +1 -1
- data/spec/suite_spec.rb +8 -9
- metadata +109 -60
- data/lib/rdf/tabular/utils.rb +0 -33
data/spec/matchers.rb
CHANGED
@@ -1,66 +1,14 @@
|
|
1
1
|
require 'rdf/isomorphic'
|
2
2
|
require 'rspec/matchers'
|
3
|
-
require 'rdf/rdfa'
|
4
|
-
|
5
|
-
def normalize(graph)
|
6
|
-
case graph
|
7
|
-
when RDF::Queryable then graph
|
8
|
-
when IO, StringIO
|
9
|
-
RDF::Graph.new.load(graph, base_uri: @info.action)
|
10
|
-
else
|
11
|
-
# Figure out which parser to use
|
12
|
-
g = RDF::Repository.new
|
13
|
-
reader_class = detect_format(graph)
|
14
|
-
reader_class.new(graph, base_uri: @info.action).each {|s| g << s}
|
15
|
-
g
|
16
|
-
end
|
17
|
-
end
|
18
3
|
|
19
4
|
Info = Struct.new(:id, :debug, :action, :result, :metadata)
|
20
5
|
|
21
|
-
RSpec::Matchers.define :be_equivalent_graph do |expected, info|
|
22
|
-
match do |actual|
|
23
|
-
@info = if (info.id rescue false)
|
24
|
-
info
|
25
|
-
elsif info.is_a?(Hash)
|
26
|
-
Info.new(info[:id], info[:debug], info[:action], info[:result], info[:metadata])
|
27
|
-
else
|
28
|
-
Info.new(info, info.to_s)
|
29
|
-
end
|
30
|
-
@info.debug = Array(@info.debug).join("\n")
|
31
|
-
@expected = normalize(expected)
|
32
|
-
@actual = normalize(actual)
|
33
|
-
@actual.isomorphic_with?(@expected) rescue false
|
34
|
-
end
|
35
|
-
|
36
|
-
failure_message do |actual|
|
37
|
-
prefixes = {
|
38
|
-
'' => @info.action + '#',
|
39
|
-
oa: "http://www.w3.org/ns/oa#",
|
40
|
-
geo: "http://www.geonames.org/ontology#",
|
41
|
-
}
|
42
|
-
"#{@info.inspect + "\n"}" +
|
43
|
-
if @expected.is_a?(RDF::Enumerable) && @actual.size != @expected.size
|
44
|
-
"Graph entry count differs:\nexpected: #{@expected.size}\nactual: #{@actual.size}\n"
|
45
|
-
elsif @expected.is_a?(Array) && @actual.size != @expected.length
|
46
|
-
"Graph entry count differs:\nexpected: #{@expected.length}\nactual: #{@actual.size}\n"
|
47
|
-
else
|
48
|
-
"Graph differs\n"
|
49
|
-
end +
|
50
|
-
"Expected:\n#{@expected.dump(:ttl, standard_prefixes: true, prefixes: prefixes, literal_shorthand: false)}" +
|
51
|
-
"Results:\n#{@actual.dump(:ttl, standard_prefixes: true, prefixes: prefixes, literal_shorthand: false)}" +
|
52
|
-
(@info.metadata ? "\nMetadata:\n#{@info.metadata.to_json(JSON_STATE)}\n" : "") +
|
53
|
-
(@info.metadata && !@info.metadata.errors.empty? ? "\nMetadata Errors:\n#{@info.metadata.errors.join("\n")}\n" : "") +
|
54
|
-
(@info.debug ? "\nDebug:\n#{@info.debug}" : "")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
6
|
RSpec::Matchers.define :pass_query do |expected, info|
|
59
7
|
match do |actual|
|
60
8
|
@info = if (info.id rescue false)
|
61
9
|
info
|
62
10
|
elsif info.is_a?(Hash)
|
63
|
-
Info.new(info[:id], info[:
|
11
|
+
Info.new(info[:id], info[:logger], info[:action], info.fetch(:result, RDF::Literal::TRUE), info[:metadata])
|
64
12
|
end
|
65
13
|
@info.debug = Array(@info.debug).join("\n")
|
66
14
|
|
@@ -88,7 +36,7 @@ RSpec::Matchers.define :pass_query do |expected, info|
|
|
88
36
|
"\nResults:\n#{@actual.dump(:ttl, standard_prefixes: true, prefixes: {'' => @info.action + '#'}, literal_shorthand: false)}" +
|
89
37
|
(@info.metadata ? "\nMetadata:\n#{@info.metadata.to_json(JSON_STATE)}\n" : "") +
|
90
38
|
(@info.metadata && !@info.metadata.errors.empty? ? "\nMetadata Errors:\n#{@info.metadata.errors.join("\n")}\n" : "") +
|
91
|
-
"\nDebug:\n#{@info.
|
39
|
+
"\nDebug:\n#{@info.logger}"
|
92
40
|
end
|
93
41
|
|
94
42
|
failure_message_when_negated do |actual|
|
@@ -106,29 +54,6 @@ RSpec::Matchers.define :pass_query do |expected, info|
|
|
106
54
|
"\nResults:\n#{@actual.dump(:ttl, standard_prefixes: true, prefixes: {'' => @info.action + '#'}, literal_shorthand: false)}" +
|
107
55
|
(@info.metadata ? "\nMetadata:\n#{@info.metadata.to_json(JSON_STATE)}\n" : "") +
|
108
56
|
(@info.metadata && !@info.metadata.errors.empty? ? "\nMetadata Errors:\n#{@info.metadata.errors.join("\n")}\n" : "") +
|
109
|
-
"\nDebug:\n#{@info.
|
57
|
+
"\nDebug:\n#{@info.logger}"
|
110
58
|
end
|
111
59
|
end
|
112
|
-
|
113
|
-
RSpec::Matchers.define :produce do |expected, info = []|
|
114
|
-
match do |actual|
|
115
|
-
@info = if (info.id rescue false)
|
116
|
-
info
|
117
|
-
elsif info.is_a?(Hash)
|
118
|
-
Info.new(info[:id], info[:debug], info[:action], info[:result], info[:metadata])
|
119
|
-
elsif info.is_a?(Array)
|
120
|
-
Info.new("", info)
|
121
|
-
end
|
122
|
-
@info.debug = Array(@info.debug).join("\n")
|
123
|
-
expect(actual).to eq expected
|
124
|
-
end
|
125
|
-
|
126
|
-
failure_message do |actual|
|
127
|
-
"#{@info.inspect + "\n"}" +
|
128
|
-
"Expected: #{expected.is_a?(String) ? expected : expected.to_json(JSON_STATE)}\n" +
|
129
|
-
"Actual : #{actual.is_a?(String) ? actual : actual.to_json(JSON_STATE)}\n" +
|
130
|
-
(@info.metadata ? "\nMetadata:\n#{@info.metadata.to_json(JSON_STATE)}\n" : "") +
|
131
|
-
(@info.metadata && !@info.metadata.errors.empty? ? "\nMetadata Errors:\n#{@info.metadata.errors.join("\n")}\n" : "") +
|
132
|
-
"Debug:\n#{@info.debug}"
|
133
|
-
end
|
134
|
-
end
|
data/spec/metadata_spec.rb
CHANGED
@@ -3,7 +3,10 @@ $:.unshift "."
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe RDF::Tabular::Metadata do
|
6
|
+
let(:logger) {RDF::Spec.logger}
|
6
7
|
before(:each) do
|
8
|
+
logger.formatter = lambda {|severity, datetime, progname, msg| "#{severity}: #{msg}\n"}
|
9
|
+
|
7
10
|
WebMock.stub_request(:any, %r(.*example.org.*)).
|
8
11
|
to_return(lambda {|request|
|
9
12
|
file = request.uri.to_s.split('/').last
|
@@ -24,7 +27,6 @@ describe RDF::Tabular::Metadata do
|
|
24
27
|
}
|
25
28
|
end
|
26
29
|
})
|
27
|
-
@debug = []
|
28
30
|
end
|
29
31
|
|
30
32
|
shared_examples "inherited properties" do |allowed = true|
|
@@ -96,30 +98,37 @@ describe RDF::Tabular::Metadata do
|
|
96
98
|
if allowed
|
97
99
|
it "validates" do
|
98
100
|
params.fetch(:valid, {}).each do |v|
|
101
|
+
logger.clear
|
99
102
|
subject.send("#{prop}=".to_sym, v)
|
100
|
-
expect(subject
|
101
|
-
expect(
|
103
|
+
expect(subject).to be_valid # Causes re-validation
|
104
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
102
105
|
end
|
103
106
|
end
|
104
107
|
it "invalidates" do
|
105
108
|
params.fetch(:invalid, {}).each do |v|
|
109
|
+
logger.clear
|
106
110
|
subject.send("#{prop}=".to_sym, v)
|
107
|
-
expect(subject
|
108
|
-
expect(
|
111
|
+
expect(subject).to be_valid # Causes re-validation
|
112
|
+
expect(logger.to_s).not_to include "ERROR"
|
113
|
+
expect(logger.to_s).to include "WARN"
|
109
114
|
end
|
110
115
|
end
|
111
116
|
it "errors" do
|
112
117
|
params.fetch(:error, {}).each do |v|
|
118
|
+
logger.clear
|
113
119
|
subject.send("#{prop}=".to_sym, v)
|
114
|
-
expect(subject
|
120
|
+
expect(subject).not_to be_valid # Causes re-validation
|
121
|
+
expect(logger.to_s).to include "ERROR"
|
115
122
|
end
|
116
123
|
end
|
117
124
|
else
|
118
125
|
it "does not allow" do
|
119
126
|
params[:valid].each do |v|
|
127
|
+
logger.clear
|
120
128
|
subject.send("#{prop}=".to_sym, v)
|
121
|
-
expect(subject
|
122
|
-
expect(
|
129
|
+
expect(subject).to be_valid # Causes re-validation
|
130
|
+
expect(logger.to_s).not_to include "ERROR"
|
131
|
+
expect(logger.to_s).to include "WARN"
|
123
132
|
end
|
124
133
|
end
|
125
134
|
end
|
@@ -134,8 +143,10 @@ describe RDF::Tabular::Metadata do
|
|
134
143
|
context "valid JSON-LD" do
|
135
144
|
it "allows defined prefixed names and absolute URIs" do
|
136
145
|
valid.each do |v|
|
146
|
+
logger.clear
|
137
147
|
subject[v.to_sym] = "foo"
|
138
|
-
expect(subject
|
148
|
+
expect(subject).to be_valid # Causes re-validation
|
149
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
139
150
|
end
|
140
151
|
end
|
141
152
|
|
@@ -155,7 +166,8 @@ describe RDF::Tabular::Metadata do
|
|
155
166
|
}.each do |name, value|
|
156
167
|
specify(name) {
|
157
168
|
subject["dc:object"] = value.is_a?(String) ? ::JSON.parse(value) : value
|
158
|
-
expect(subject
|
169
|
+
expect(subject).to be_valid # Causes re-validation
|
170
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
159
171
|
}
|
160
172
|
end
|
161
173
|
end
|
@@ -163,9 +175,11 @@ describe RDF::Tabular::Metadata do
|
|
163
175
|
context "invalid JSON-LD" do
|
164
176
|
it "Does not allow unknown prefxies or unprefixed names" do
|
165
177
|
invalid.each do |v|
|
178
|
+
logger.clear
|
166
179
|
subject[v.to_sym] = "foo"
|
167
|
-
expect(subject
|
168
|
-
expect(
|
180
|
+
expect(subject).to be_valid # Causes re-validation
|
181
|
+
expect(logger.to_s).not_to include "ERROR"
|
182
|
+
expect(logger.to_s).to include "WARN"
|
169
183
|
end
|
170
184
|
end
|
171
185
|
|
@@ -180,7 +194,8 @@ describe RDF::Tabular::Metadata do
|
|
180
194
|
}.each do |name, value|
|
181
195
|
specify(name) {
|
182
196
|
subject["dc:object"] = ::JSON.parse(value)
|
183
|
-
expect(subject
|
197
|
+
expect(subject).not_to be_valid
|
198
|
+
expect(logger.to_s).to include "ERROR"
|
184
199
|
}
|
185
200
|
end
|
186
201
|
end
|
@@ -188,15 +203,16 @@ describe RDF::Tabular::Metadata do
|
|
188
203
|
it "Does not allow defined prefixed names and absolute URIs" do
|
189
204
|
(valid + invalid).each do |v|
|
190
205
|
subject[v.to_sym] = "foo"
|
191
|
-
expect(subject
|
192
|
-
expect(
|
206
|
+
expect(subject).to be_valid # Causes re-validation
|
207
|
+
expect(logger.to_s).not_to include "ERROR"
|
208
|
+
expect(logger.to_s).to include "WARN"
|
193
209
|
end
|
194
210
|
end
|
195
211
|
end
|
196
212
|
end
|
197
213
|
|
198
214
|
describe RDF::Tabular::Column do
|
199
|
-
subject {described_class.new({"name" => "foo"}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"),
|
215
|
+
subject {described_class.new({"name" => "foo"}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"), logger: logger)}
|
200
216
|
specify {is_expected.to be_valid}
|
201
217
|
it_behaves_like("inherited properties")
|
202
218
|
it_behaves_like("common properties")
|
@@ -204,19 +220,23 @@ describe RDF::Tabular::Metadata do
|
|
204
220
|
it "allows valid name" do
|
205
221
|
%w(
|
206
222
|
name abc.123 _col.1
|
207
|
-
).each {|v| expect(described_class.new("name" => v)).to be_valid}
|
223
|
+
).each {|v| expect(described_class.new({"name" => v}, logger: logger)).to be_valid}
|
224
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
208
225
|
end
|
209
226
|
|
210
227
|
it "detects invalid names" do
|
211
228
|
[1, true, nil, "_foo", "_col=1"].each do |v|
|
212
|
-
md = described_class.new("name" => v)
|
213
|
-
expect(md
|
229
|
+
md = described_class.new({"name" => v}, logger: logger)
|
230
|
+
expect(md).to be_valid
|
231
|
+
expect(logger.to_s).not_to include "ERROR"
|
232
|
+
expect(logger.to_s).to include "WARN"
|
214
233
|
end
|
215
234
|
end
|
216
235
|
|
217
236
|
it "allows absence of name" do
|
218
|
-
expect(described_class.new("@type" => "Column")).to be_valid
|
219
|
-
expect(described_class.new("@type" => "Column").name).to eql '_col.0'
|
237
|
+
expect(described_class.new({"@type" => "Column"}, logger: logger)).to be_valid
|
238
|
+
expect(described_class.new({"@type" => "Column"}, logger: logger).name).to eql '_col.0'
|
239
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
220
240
|
end
|
221
241
|
|
222
242
|
its(:type) {is_expected.to eql :Column}
|
@@ -240,19 +260,23 @@ describe RDF::Tabular::Metadata do
|
|
240
260
|
params[:valid].each do |v|
|
241
261
|
subject.send("#{prop}=".to_sym, v)
|
242
262
|
expect(subject).to be_valid
|
263
|
+
expect(logger.to_s).not_to include "ERROR"
|
264
|
+
expect(logger.to_s).not_to include "WARN"
|
243
265
|
end
|
244
266
|
end
|
245
267
|
it "invalidates" do
|
246
268
|
params[:invalid].each do |v|
|
247
269
|
subject.send("#{prop}=".to_sym, v)
|
248
270
|
expect(subject).not_to be_valid
|
271
|
+
expect(logger.to_s).to include "ERROR"
|
249
272
|
end
|
250
273
|
end if params[:invalid]
|
251
274
|
it "warnings" do
|
252
275
|
params[:warning].each do |v|
|
253
276
|
subject.send("#{prop}=".to_sym, v)
|
254
277
|
expect(subject).to be_valid
|
255
|
-
expect(
|
278
|
+
expect(logger.to_s).not_to include "ERROR"
|
279
|
+
expect(logger.to_s).to include "WARN"
|
256
280
|
end
|
257
281
|
end if params[:warning]
|
258
282
|
end
|
@@ -265,13 +289,14 @@ describe RDF::Tabular::Metadata do
|
|
265
289
|
it name do
|
266
290
|
subject.titles = input
|
267
291
|
expect(subject.normalize!.titles).to produce(output)
|
292
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
268
293
|
end
|
269
294
|
end
|
270
295
|
end
|
271
296
|
end
|
272
297
|
|
273
298
|
describe RDF::Tabular::Schema do
|
274
|
-
subject {described_class.new({}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"),
|
299
|
+
subject {described_class.new({}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"), logger: logger)}
|
275
300
|
specify {is_expected.to be_valid}
|
276
301
|
it_behaves_like("inherited properties")
|
277
302
|
it_behaves_like("common properties")
|
@@ -279,31 +304,35 @@ describe RDF::Tabular::Metadata do
|
|
279
304
|
|
280
305
|
describe "columns" do
|
281
306
|
let(:column) {{"name" => "foo"}}
|
282
|
-
subject {described_class.new({"columns" => []}, base: RDF::URI("http://example.org/base"),
|
283
|
-
|
307
|
+
subject {described_class.new({"columns" => []}, base: RDF::URI("http://example.org/base"), logger: logger)}
|
308
|
+
it {is_expected.to be_valid}
|
284
309
|
|
285
310
|
its(:type) {is_expected.to eql :Schema}
|
286
311
|
|
287
312
|
it "allows a valid column" do
|
288
|
-
v = described_class.new({"columns" => [column]}, base: RDF::URI("http://example.org/base"),
|
289
|
-
expect(v
|
313
|
+
v = described_class.new({"columns" => [column]}, base: RDF::URI("http://example.org/base"), logger: logger)
|
314
|
+
expect(v).to be_valid
|
315
|
+
expect(logger.to_s).not_to include "ERROR"
|
290
316
|
end
|
291
317
|
|
292
318
|
it "is invalid with an invalid column" do
|
293
|
-
v = described_class.new({"columns" => [{"name" => "_invalid"}]}, base: RDF::URI("http://example.org/base"),
|
294
|
-
expect(v
|
319
|
+
v = described_class.new({"columns" => [{"name" => "_invalid"}]}, base: RDF::URI("http://example.org/base"), logger: logger)
|
320
|
+
expect(v).to be_valid
|
321
|
+
expect(logger.to_s).not_to include "ERROR"
|
322
|
+
expect(logger.to_s).to include "WARN"
|
295
323
|
end
|
296
324
|
|
297
325
|
it "is invalid with an non-unique columns" do
|
298
|
-
v = described_class.new({"columns" => [column, column]}, base: RDF::URI("http://example.org/base"),
|
299
|
-
expect(v
|
326
|
+
v = described_class.new({"columns" => [column, column]}, base: RDF::URI("http://example.org/base"), logger: logger)
|
327
|
+
expect(v).not_to be_valid
|
328
|
+
expect(logger.to_s).to include "ERROR"
|
300
329
|
end
|
301
330
|
end
|
302
331
|
|
303
332
|
describe "primaryKey" do
|
304
333
|
let(:column) {{"name" => "foo"}}
|
305
334
|
let(:column2) {{"name" => "bar"}}
|
306
|
-
subject {described_class.new({"columns" => [column], "primaryKey" => column["name"]}, base: RDF::URI("http://example.org/base"),
|
335
|
+
subject {described_class.new({"columns" => [column], "primaryKey" => column["name"]}, base: RDF::URI("http://example.org/base"), logger: logger)}
|
307
336
|
specify {is_expected.to be_valid}
|
308
337
|
|
309
338
|
its(:type) {is_expected.to eql :Schema}
|
@@ -311,7 +340,8 @@ describe RDF::Tabular::Metadata do
|
|
311
340
|
it "is valid if referenced column does not exist" do
|
312
341
|
subject[:columns] = []
|
313
342
|
expect(subject).to be_valid
|
314
|
-
expect(
|
343
|
+
expect(logger.to_s).not_to include "ERROR"
|
344
|
+
expect(logger.to_s).to include "WARN"
|
315
345
|
end
|
316
346
|
|
317
347
|
it "is valid with multiple names" do
|
@@ -319,24 +349,26 @@ describe RDF::Tabular::Metadata do
|
|
319
349
|
"columns" => [column, column2],
|
320
350
|
"primaryKey" => [column["name"], column2["name"]]},
|
321
351
|
base: RDF::URI("http://example.org/base"),
|
322
|
-
|
352
|
+
logger: logger)
|
323
353
|
expect(v).to be_valid
|
354
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
324
355
|
end
|
325
356
|
|
326
357
|
it "is valid with multiple names if any column missing" do
|
327
358
|
v = described_class.new({
|
328
359
|
"columns" => [column],
|
329
360
|
"primaryKey" => [column["name"], column2["name"]]},
|
330
|
-
base: RDF::URI("http://example.org/base",
|
331
|
-
|
361
|
+
base: RDF::URI("http://example.org/base"),
|
362
|
+
logger: logger)
|
332
363
|
expect(v).to be_valid
|
333
|
-
expect(
|
364
|
+
expect(logger.to_s).to include "WARN"
|
334
365
|
end
|
335
366
|
end
|
336
367
|
|
337
368
|
describe "foreignKeys" do
|
338
369
|
subject {
|
339
370
|
RDF::Tabular::TableGroup.new({
|
371
|
+
"@context" => 'http://www.w3.org/ns/csvw',
|
340
372
|
tables: [{
|
341
373
|
url: "a",
|
342
374
|
tableSchema: {
|
@@ -352,7 +384,7 @@ describe RDF::Tabular::Metadata do
|
|
352
384
|
foreignKeys: []
|
353
385
|
}
|
354
386
|
}]},
|
355
|
-
base: RDF::URI("http://example.org/base"),
|
387
|
+
base: RDF::URI("http://example.org/base"), logger: logger
|
356
388
|
)
|
357
389
|
}
|
358
390
|
context "valid" do
|
@@ -381,7 +413,9 @@ describe RDF::Tabular::Metadata do
|
|
381
413
|
}.each do |name, fk|
|
382
414
|
it name do
|
383
415
|
subject.tables.first.tableSchema.foreignKeys << fk
|
384
|
-
|
416
|
+
subject.normalize!
|
417
|
+
expect(subject).to be_valid
|
418
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
385
419
|
end
|
386
420
|
end
|
387
421
|
end
|
@@ -434,7 +468,10 @@ describe RDF::Tabular::Metadata do
|
|
434
468
|
}.each do |name, fk|
|
435
469
|
it name do
|
436
470
|
subject.tables.first.tableSchema.foreignKeys << fk
|
437
|
-
|
471
|
+
subject.normalize!
|
472
|
+
subject.inspect
|
473
|
+
expect(subject).not_to be_valid
|
474
|
+
expect(logger.to_s).to include "ERROR"
|
438
475
|
end
|
439
476
|
end
|
440
477
|
end
|
@@ -451,7 +488,7 @@ describe RDF::Tabular::Metadata do
|
|
451
488
|
"scriptFormat" => scriptFormat},
|
452
489
|
context: "http://www.w3.org/ns/csvw",
|
453
490
|
base: RDF::URI("http://example.org/base"),
|
454
|
-
|
491
|
+
logger: logger)
|
455
492
|
}
|
456
493
|
specify {is_expected.to be_valid}
|
457
494
|
it_behaves_like("inherited properties", false)
|
@@ -470,11 +507,13 @@ describe RDF::Tabular::Metadata do
|
|
470
507
|
subject.send("#{prop}=".to_sym, v)
|
471
508
|
expect(subject).to be_valid
|
472
509
|
end
|
510
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
473
511
|
end
|
474
512
|
it "warnings" do
|
475
513
|
params[:warning].each do |v|
|
476
514
|
subject.send("#{prop}=".to_sym, v)
|
477
|
-
expect(subject
|
515
|
+
expect(subject).to be_valid
|
516
|
+
expect(logger.to_s).to include "WARN"
|
478
517
|
end
|
479
518
|
end
|
480
519
|
end
|
@@ -487,13 +526,14 @@ describe RDF::Tabular::Metadata do
|
|
487
526
|
it name do
|
488
527
|
subject.titles = input
|
489
528
|
expect(subject.normalize!.titles).to produce(output)
|
529
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
490
530
|
end
|
491
531
|
end
|
492
532
|
end
|
493
533
|
end
|
494
534
|
|
495
535
|
describe RDF::Tabular::Dialect do
|
496
|
-
subject {described_class.new({}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"),
|
536
|
+
subject {described_class.new({}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"), logger: logger)}
|
497
537
|
specify {is_expected.to be_valid}
|
498
538
|
it_behaves_like("inherited properties", false)
|
499
539
|
it_behaves_like("common properties", false)
|
@@ -502,12 +542,14 @@ describe RDF::Tabular::Metadata do
|
|
502
542
|
described_class.const_get(:DEFAULTS).each do |p, v|
|
503
543
|
context "#{p}" do
|
504
544
|
it "retrieves #{v.inspect} by default" do
|
545
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
505
546
|
expect(subject.send(p)).to eql v
|
506
547
|
end
|
507
548
|
|
508
549
|
it "retrieves set value" do
|
509
550
|
subject[p] = "foo"
|
510
551
|
expect(subject.send(p)).to eql "foo"
|
552
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
511
553
|
end
|
512
554
|
end
|
513
555
|
end
|
@@ -572,26 +614,28 @@ describe RDF::Tabular::Metadata do
|
|
572
614
|
}.each do |name, props|
|
573
615
|
it name do
|
574
616
|
dialect = if props[:dialect]
|
575
|
-
described_class.new(props[:dialect],
|
617
|
+
described_class.new(props[:dialect], logger: logger)
|
576
618
|
else
|
577
619
|
subject
|
578
620
|
end
|
579
621
|
|
580
622
|
result = dialect.embedded_metadata(props[:input], nil, base: RDF::URI("http://example.org/base"))
|
581
|
-
expect(::JSON.parse(result.to_json(JSON_STATE))).to produce(::JSON.parse(props[:result]),
|
623
|
+
expect(::JSON.parse(result.to_json(JSON_STATE))).to produce(::JSON.parse(props[:result]), logger)
|
624
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
582
625
|
end
|
583
626
|
end
|
584
627
|
end
|
585
628
|
end
|
586
629
|
|
587
630
|
describe RDF::Tabular::Table do
|
588
|
-
subject {described_class.new({"url" => "http://example.org/table.csv"}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"),
|
631
|
+
subject {described_class.new({"url" => "http://example.org/table.csv"}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"), logger: logger)}
|
589
632
|
specify {is_expected.to be_valid}
|
590
633
|
it_behaves_like("inherited properties")
|
591
634
|
it_behaves_like("common properties")
|
592
635
|
its(:type) {is_expected.to eql :Table}
|
593
636
|
|
594
637
|
describe "#to_table_group" do
|
638
|
+
it "should be tested"
|
595
639
|
end
|
596
640
|
|
597
641
|
{
|
@@ -626,19 +670,21 @@ describe RDF::Tabular::Metadata do
|
|
626
670
|
params[:valid].each do |v|
|
627
671
|
subject.send("#{prop}=".to_sym, v)
|
628
672
|
expect(subject).to be_valid
|
673
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
629
674
|
end
|
630
675
|
end
|
631
676
|
it "invalidates" do
|
632
677
|
params[:invalid].each do |v|
|
633
678
|
subject.send("#{prop}=".to_sym, v)
|
634
679
|
expect(subject).not_to be_valid
|
680
|
+
expect(logger.to_s).to include("ERROR")
|
635
681
|
end
|
636
682
|
end if params[:invalid]
|
637
683
|
it "warnings" do
|
638
684
|
params[:warning].each do |v|
|
639
685
|
subject.send("#{prop}=".to_sym, v)
|
640
686
|
expect(subject).to be_valid
|
641
|
-
expect(
|
687
|
+
expect(logger.to_s).to include("WARN")
|
642
688
|
end
|
643
689
|
end if params[:warning]
|
644
690
|
end
|
@@ -647,7 +693,7 @@ describe RDF::Tabular::Metadata do
|
|
647
693
|
|
648
694
|
describe RDF::Tabular::TableGroup do
|
649
695
|
let(:table) {{"url" => "http://example.org/table.csv"}}
|
650
|
-
subject {described_class.new({"tables" => [table]}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"),
|
696
|
+
subject {described_class.new({"tables" => [table]}, context: "http://www.w3.org/ns/csvw", base: RDF::URI("http://example.org/base"), logger: logger)}
|
651
697
|
specify {is_expected.to be_valid}
|
652
698
|
|
653
699
|
it_behaves_like("inherited properties")
|
@@ -681,19 +727,21 @@ describe RDF::Tabular::Metadata do
|
|
681
727
|
params[:valid].each do |v|
|
682
728
|
subject.send("#{prop}=".to_sym, v)
|
683
729
|
expect(subject).to be_valid
|
730
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
684
731
|
end
|
685
732
|
end
|
686
733
|
it "invalidates" do
|
687
734
|
params[:invalid].each do |v|
|
688
735
|
subject.send("#{prop}=".to_sym, v)
|
689
736
|
expect(subject).not_to be_valid
|
737
|
+
expect(logger.to_s).to include("ERROR")
|
690
738
|
end
|
691
739
|
end if params[:invalid]
|
692
740
|
it "warnings" do
|
693
741
|
params[:warning].each do |v|
|
694
742
|
subject.send("#{prop}=".to_sym, v)
|
695
743
|
expect(subject).to be_valid
|
696
|
-
expect(
|
744
|
+
expect(logger.to_s).to include("WARN")
|
697
745
|
end
|
698
746
|
end if params[:warning]
|
699
747
|
end
|
@@ -704,19 +752,25 @@ describe RDF::Tabular::Metadata do
|
|
704
752
|
Dir.glob(File.expand_path("../data/*.json", __FILE__)).each do |filename|
|
705
753
|
next if filename =~ /-(atd|standard|minimal|roles).json/
|
706
754
|
context filename do
|
707
|
-
subject {RDF::Tabular::Metadata.open(filename)}
|
708
|
-
|
755
|
+
subject {RDF::Tabular::Metadata.open(filename, logger: logger)}
|
756
|
+
it {is_expected.to be_valid}
|
709
757
|
its(:filenames) {is_expected.to include("file:#{filename}")}
|
710
758
|
end
|
759
|
+
after(:each) do
|
760
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
761
|
+
end
|
711
762
|
end
|
712
763
|
end
|
713
764
|
|
714
765
|
context "parses invalid metadata" do
|
715
766
|
Dir.glob(File.expand_path("../invalid_data/*.json", __FILE__)).each do |filename|
|
716
767
|
context filename do
|
717
|
-
subject {RDF::Tabular::Metadata.open(filename)}
|
768
|
+
subject {RDF::Tabular::Metadata.open(filename, logger: logger)}
|
718
769
|
File.foreach(filename.sub(".json", "-errors.txt")) do |err|
|
719
|
-
|
770
|
+
it {is_expected.not_to be_valid}
|
771
|
+
end
|
772
|
+
after(:each) do
|
773
|
+
expect(logger.to_s).not_to include("ERROR")
|
720
774
|
end
|
721
775
|
end
|
722
776
|
end
|
@@ -726,19 +780,21 @@ describe RDF::Tabular::Metadata do
|
|
726
780
|
let(:table) {{"url" => "http://example.org/table.csv", "@type" => "Table"}}
|
727
781
|
it "loads referenced schema" do
|
728
782
|
table[:tableSchema] = "http://example.org/schema"
|
729
|
-
expect(described_class).to receive(:open).with(table[:tableSchema], kind_of(Hash)).and_return(RDF::Tabular::Schema.new({"@type" => "Schema"}))
|
730
|
-
described_class.
|
783
|
+
expect(described_class).to receive(:open).with(table[:tableSchema], kind_of(Hash)).and_return(RDF::Tabular::Schema.new({"@type" => "Schema"}, base: RDF::URI("http://example.org/base")))
|
784
|
+
allow_any_instance_of(described_class).to receive(:normalize!).and_return(true)
|
785
|
+
described_class.new(table, base: RDF::URI("http://example.org/base"), logger: logger)
|
731
786
|
end
|
732
787
|
it "loads referenced dialect" do
|
733
788
|
table[:dialect] = "http://example.org/dialect"
|
734
789
|
expect(described_class).to receive(:open).with(table[:dialect], kind_of(Hash)).and_return(RDF::Tabular::Dialect.new({}))
|
735
|
-
described_class.
|
790
|
+
allow_any_instance_of(described_class).to receive(:normalize!).and_return(true)
|
791
|
+
described_class.new(table, base: RDF::URI("http://example.org/base"), logger: logger)
|
736
792
|
end
|
737
793
|
end
|
738
794
|
|
739
795
|
context "inherited properties" do
|
740
796
|
let(:table) {{"url" => "http://example.org/table.csv", "tableSchema" => {"@type" => "Schema"}, "@type" => "Table"}}
|
741
|
-
subject {described_class.new(table, base: RDF::URI("http://example.org/base"),
|
797
|
+
subject {described_class.new(table, base: RDF::URI("http://example.org/base"), logger: logger)}
|
742
798
|
|
743
799
|
it "inherits properties from parent" do
|
744
800
|
subject.lang = "en"
|
@@ -757,8 +813,12 @@ describe RDF::Tabular::Metadata do
|
|
757
813
|
Dir.glob(File.expand_path("../data/*.json", __FILE__)).each do |filename|
|
758
814
|
next if filename =~ /-(atd|standard|minimal|roles).json/
|
759
815
|
context filename do
|
760
|
-
subject {RDF::Tabular::Metadata.open(filename,
|
761
|
-
|
816
|
+
subject {RDF::Tabular::Metadata.open(filename, logger: logger)}
|
817
|
+
it {is_expected.to be_valid}
|
818
|
+
it do
|
819
|
+
subject.validate
|
820
|
+
expect(logger.to_s).to be_empty
|
821
|
+
end
|
762
822
|
its(:filenames) {is_expected.to include("file:#{filename}")}
|
763
823
|
end
|
764
824
|
end
|
@@ -778,7 +838,7 @@ describe RDF::Tabular::Metadata do
|
|
778
838
|
":type Schema" => [{}, {type: :Schema}, RDF::Tabular::Schema],
|
779
839
|
":type Column" => [{}, {type: :Column}, RDF::Tabular::Column],
|
780
840
|
":type Dialect" => [{}, {type: :Dialect}, RDF::Tabular::Dialect],
|
781
|
-
"@type TableGroup" => [{"@type" => "TableGroup"}, RDF::Tabular::TableGroup],
|
841
|
+
"@type TableGroup" => [{}, {"@type" => "TableGroup"}, RDF::Tabular::TableGroup],
|
782
842
|
"@type Table" => [{"@type" => "Table"}, RDF::Tabular::Table],
|
783
843
|
"@type Template" => [{"@type" => "Template"}, RDF::Tabular::Transformation],
|
784
844
|
"@type Schema" => [{"@type" => "Schema"}, RDF::Tabular::Schema],
|
@@ -788,9 +848,9 @@ describe RDF::Tabular::Metadata do
|
|
788
848
|
"dialect Table" => [{"dialect" => {}}, RDF::Tabular::Table],
|
789
849
|
"tableSchema Table" => [{"tableSchema" => {}}, RDF::Tabular::Table],
|
790
850
|
"transformations Table" => [{"transformations" => []}, RDF::Tabular::Table],
|
791
|
-
"targetFormat Transformation" => [{"targetFormat" => "foo"}, RDF::Tabular::Transformation],
|
792
|
-
"scriptFormat Transformation" => [{"scriptFormat" => "foo"}, RDF::Tabular::Transformation],
|
793
|
-
"source Transformation" => [{"source" => "
|
851
|
+
"targetFormat Transformation" => [{"targetFormat" => "http://foo"}, RDF::Tabular::Transformation],
|
852
|
+
"scriptFormat Transformation" => [{"scriptFormat" => "http://foo"}, RDF::Tabular::Transformation],
|
853
|
+
"source Transformation" => [{"source" => "json"}, RDF::Tabular::Transformation],
|
794
854
|
"columns Schema" => [{"columns" => []}, RDF::Tabular::Schema],
|
795
855
|
"primaryKey Schema" => [{"primaryKey" => "foo"}, RDF::Tabular::Schema],
|
796
856
|
"foreignKeys Schema" => [{"foreignKeys" => []}, RDF::Tabular::Schema],
|
@@ -804,13 +864,18 @@ describe RDF::Tabular::Metadata do
|
|
804
864
|
"quoteChar Dialect" => [{"quoteChar" => "\""}, RDF::Tabular::Dialect],
|
805
865
|
"skipBlankRows Dialect" => [{"skipBlankRows" => true}, RDF::Tabular::Dialect],
|
806
866
|
"skipColumns Dialect" => [{"skipColumns" => 0}, RDF::Tabular::Dialect],
|
807
|
-
"skipInitialSpace Dialect" => [{"skipInitialSpace" =>
|
867
|
+
"skipInitialSpace Dialect" => [{"skipInitialSpace" => true}, RDF::Tabular::Dialect],
|
808
868
|
"skipRows Dialect" => [{"skipRows" => 1}, RDF::Tabular::Dialect],
|
809
869
|
"trim Dialect" => [{"trim" => true}, RDF::Tabular::Dialect],
|
810
870
|
}.each do |name, args|
|
811
871
|
it name do
|
812
872
|
klass = args.pop
|
813
|
-
|
873
|
+
input, options = args
|
874
|
+
options ||= {}
|
875
|
+
options[:logger] = logger
|
876
|
+
options[:context] ||= 'http://www.w3.org/ns/csvw'
|
877
|
+
expect(described_class.new(input, options)).to be_a(klass)
|
878
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
814
879
|
end
|
815
880
|
end
|
816
881
|
end
|
@@ -841,7 +906,7 @@ describe RDF::Tabular::Metadata do
|
|
841
906
|
"propertyUrl": "https://example.org/countries.csv#name"
|
842
907
|
}]
|
843
908
|
}
|
844
|
-
})), base: RDF::URI("http://example.org/base"),
|
909
|
+
})), base: RDF::URI("http://example.org/base"), logger: logger)
|
845
910
|
}
|
846
911
|
let(:input) {RDF::Util::File.open_file("https://example.org/countries.csv")}
|
847
912
|
|
@@ -889,9 +954,9 @@ describe RDF::Tabular::Metadata do
|
|
889
954
|
|
890
955
|
it "has expected values" do
|
891
956
|
rows = subject.to_enum(:each_row, input).to_a
|
892
|
-
expect(rows[0].values.map(&:to_s)).to produce(%w(AD 42.546245 1.601554 Andorra),
|
893
|
-
expect(rows[1].values.map(&:to_s)).to produce((%w(AE 23.424076 53.847818) << "United Arab Emirates"),
|
894
|
-
expect(rows[2].values.map(&:to_s)).to produce(%w(AF 33.93911 67.709953 Afghanistan),
|
957
|
+
expect(rows[0].values.map(&:to_s)).to produce(%w(AD 42.546245 1.601554 Andorra), logger)
|
958
|
+
expect(rows[1].values.map(&:to_s)).to produce((%w(AE 23.424076 53.847818) << "United Arab Emirates"), logger)
|
959
|
+
expect(rows[2].values.map(&:to_s)).to produce(%w(AF 33.93911 67.709953 Afghanistan), logger)
|
895
960
|
end
|
896
961
|
|
897
962
|
context "URL expansion" do
|
@@ -939,7 +1004,7 @@ describe RDF::Tabular::Metadata do
|
|
939
1004
|
},
|
940
1005
|
}.each do |name, props|
|
941
1006
|
context name do
|
942
|
-
let(:md) {RDF::Tabular::Table.new(subject.merge(props[:md]), base: RDF::URI("http://example.org/base")).normalize!}
|
1007
|
+
let(:md) {RDF::Tabular::Table.new(subject.merge(props[:md]), base: RDF::URI("http://example.org/base"), logger: logger).normalize!}
|
943
1008
|
let(:cells) {md.to_enum(:each_row, input).to_a.first.values}
|
944
1009
|
let(:aboutUrls) {props[:aboutUrl].map {|u| u.is_a?(String) ? md.url.join(u) : u}}
|
945
1010
|
let(:propertyUrls) {props[:propertyUrl].map {|u| u.is_a?(String) ? md.url.join(u) : u}}
|
@@ -996,7 +1061,7 @@ describe RDF::Tabular::Metadata do
|
|
996
1061
|
}
|
997
1062
|
}))
|
998
1063
|
raw["dialect"] = props[:dialect]
|
999
|
-
described_class.new(raw, base: RDF::URI("http://example.org/base"),
|
1064
|
+
described_class.new(raw, base: RDF::URI("http://example.org/base"), logger: logger)
|
1000
1065
|
}
|
1001
1066
|
let(:rows) {subject.to_enum(:each_row, input).to_a}
|
1002
1067
|
let(:rowOffset) {props[:dialect].fetch(:skipRows, 0) + props[:dialect].fetch(:headerRowCount, 1)}
|
@@ -1289,7 +1354,7 @@ describe RDF::Tabular::Metadata do
|
|
1289
1354
|
datatype: props.dup.delete_if {|k, v| [:value, :valid, :result].include?(k)}
|
1290
1355
|
}]
|
1291
1356
|
}
|
1292
|
-
},
|
1357
|
+
}, logger: logger)
|
1293
1358
|
}
|
1294
1359
|
subject {md.to_enum(:each_row, "#{value}\n").to_a.first.values.first}
|
1295
1360
|
|
@@ -1322,8 +1387,10 @@ describe RDF::Tabular::Metadata do
|
|
1322
1387
|
datatype: base
|
1323
1388
|
}]
|
1324
1389
|
}
|
1325
|
-
}
|
1326
|
-
|
1390
|
+
},
|
1391
|
+
logger: logger)
|
1392
|
+
expect(subject).to be_valid
|
1393
|
+
expect(logger.to_s).to include("WARN")
|
1327
1394
|
end
|
1328
1395
|
end
|
1329
1396
|
end
|
@@ -1354,7 +1421,6 @@ describe RDF::Tabular::Metadata do
|
|
1354
1421
|
|
1355
1422
|
'#0.0#E#0' => {base: "double", re: /^(?<prefix>[+-]?)(?<numeric_part>\d{1,}\.\d{1,2}E[+-]?\d{1,2})(?<suffix>)$/},
|
1356
1423
|
'#0.0#E+#0' => {base: "double", re: /^(?<prefix>[+-]?)(?<numeric_part>\d{1,}\.\d{1,2}E\+\d{1,2})(?<suffix>)$/},
|
1357
|
-
'#0.0#E#0%' => {base: "double", re: /^(?<prefix>[+-]?)(?<numeric_part>\d{1,}\.\d{1,2}E[+-]?\d{1,2}%)(?<suffix>)$/},
|
1358
1424
|
'#0.0#E#0%' => {base: "double", re: /^(?<prefix>[+-]?)(?<numeric_part>\d{1,}\.\d{1,2}E[+-]?\d{1,2})(?<suffix>%)$/},
|
1359
1425
|
|
1360
1426
|
# Grouping
|
@@ -1401,7 +1467,7 @@ describe RDF::Tabular::Metadata do
|
|
1401
1467
|
datatype: {"base" => props[:base], "format" => {"pattern" => pattern}}
|
1402
1468
|
}]
|
1403
1469
|
}
|
1404
|
-
},
|
1470
|
+
}, logger: logger)
|
1405
1471
|
}
|
1406
1472
|
describe "valid" do
|
1407
1473
|
Array(props[:valid]).each do |num|
|
@@ -1429,6 +1495,7 @@ describe RDF::Tabular::Metadata do
|
|
1429
1495
|
{
|
1430
1496
|
"string with no language" => [
|
1431
1497
|
%({
|
1498
|
+
"@context": "http://www.w3.org/ns/csvw",
|
1432
1499
|
"dc:title": "foo"
|
1433
1500
|
}),
|
1434
1501
|
%({
|
@@ -1438,7 +1505,7 @@ describe RDF::Tabular::Metadata do
|
|
1438
1505
|
],
|
1439
1506
|
"string with language" => [
|
1440
1507
|
%({
|
1441
|
-
"@context": {"@language": "en"},
|
1508
|
+
"@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}],
|
1442
1509
|
"dc:title": "foo"
|
1443
1510
|
}),
|
1444
1511
|
%({
|
@@ -1448,6 +1515,7 @@ describe RDF::Tabular::Metadata do
|
|
1448
1515
|
],
|
1449
1516
|
"relative URL" => [
|
1450
1517
|
%({
|
1518
|
+
"@context": "http://www.w3.org/ns/csvw",
|
1451
1519
|
"dc:source": {"@id": "foo"}
|
1452
1520
|
}),
|
1453
1521
|
%({
|
@@ -1457,7 +1525,7 @@ describe RDF::Tabular::Metadata do
|
|
1457
1525
|
],
|
1458
1526
|
"array of values" => [
|
1459
1527
|
%({
|
1460
|
-
"@context": {"@language": "en"},
|
1528
|
+
"@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}],
|
1461
1529
|
"dc:title": [
|
1462
1530
|
"foo",
|
1463
1531
|
{"@value": "bar"},
|
@@ -1487,9 +1555,10 @@ describe RDF::Tabular::Metadata do
|
|
1487
1555
|
],
|
1488
1556
|
}.each do |name, (input, result)|
|
1489
1557
|
it name do
|
1490
|
-
a = RDF::Tabular::Table.new(input, base: "http://example.com/A")
|
1491
|
-
b = RDF::Tabular::Table.new(result, base: "http://example.com/A")
|
1558
|
+
a = RDF::Tabular::Table.new(input, base: "http://example.com/A", logger: logger)
|
1559
|
+
b = RDF::Tabular::Table.new(result, base: "http://example.com/A", logger: logger)
|
1492
1560
|
expect(a.normalize!).to eq b
|
1561
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
1493
1562
|
end
|
1494
1563
|
end
|
1495
1564
|
end
|
@@ -1685,6 +1754,7 @@ describe RDF::Tabular::Metadata do
|
|
1685
1754
|
b = described_class.new(::JSON.parse(props[:B]))
|
1686
1755
|
if props[:R]
|
1687
1756
|
expect {a.verify_compatible!(b)}.not_to raise_error
|
1757
|
+
expect(logger.to_s).not_to match(/ERROR|WARN/)
|
1688
1758
|
else
|
1689
1759
|
expect {a.verify_compatible!(b)}.to raise_error(RDF::Tabular::Error)
|
1690
1760
|
end
|