icss 0.1.3 → 0.3.2
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.
- data/.watchr +35 -3
- data/CHANGELOG.md +38 -0
- data/Gemfile +19 -14
- data/README.md +296 -0
- data/Rakefile +2 -6
- data/TODO.md +13 -0
- data/VERSION +1 -1
- data/examples/avro_examples/complicated.icss.yaml +14 -13
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +3 -3
- data/examples/license.icss.yaml +7 -0
- data/examples/source1.icss.yaml +4 -0
- data/examples/source2.icss.yaml +4 -0
- data/examples/test_icss.yaml +67 -0
- data/icss.gemspec +103 -43
- data/lib/icss.rb +37 -15
- data/lib/icss/core_types.rb +19 -0
- data/lib/icss/error.rb +4 -0
- data/{init.rb → lib/icss/init.rb} +0 -0
- data/lib/icss/message.rb +124 -66
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +184 -131
- data/lib/icss/protocol/code_asset.rb +18 -0
- data/lib/icss/protocol/data_asset.rb +23 -0
- data/lib/icss/protocol/license.rb +41 -0
- data/lib/icss/protocol/source.rb +37 -0
- data/lib/icss/protocol/target.rb +68 -0
- data/lib/icss/receiver_model.rb +24 -0
- data/lib/icss/receiver_model/active_model_shim.rb +36 -0
- data/lib/icss/receiver_model/acts_as_catalog.rb +170 -0
- data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
- data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
- data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
- data/lib/icss/receiver_model/locale/en.yml +27 -0
- data/lib/icss/receiver_model/to_geo_json.rb +19 -0
- data/lib/icss/receiver_model/tree_merge.rb +34 -0
- data/lib/icss/receiver_model/validations.rb +31 -0
- data/lib/icss/serialization.rb +51 -0
- data/lib/icss/serialization/zaml.rb +443 -0
- data/lib/icss/type.rb +148 -501
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +184 -0
- data/lib/icss/type/record_field.rb +77 -0
- data/lib/icss/type/record_model.rb +49 -0
- data/lib/icss/type/record_schema.rb +54 -0
- data/lib/icss/type/record_type.rb +325 -0
- data/lib/icss/type/simple_types.rb +72 -0
- data/lib/icss/type/structured_schema.rb +288 -0
- data/lib/icss/type/type_factory.rb +144 -0
- data/lib/icss/type/union_schema.rb +41 -0
- data/lib/icss/view_helper.rb +56 -19
- data/notes/named_array.md +32 -0
- data/notes/on_include_vs_extend_etc.rb +176 -0
- data/notes/technical_details.md +278 -0
- data/spec/core_types_spec.rb +119 -0
- data/spec/fixtures/zaml_complex_hash.yaml +35 -0
- data/spec/icss_spec.rb +86 -23
- data/spec/message/message_sample_spec.rb +4 -0
- data/spec/message_spec.rb +139 -0
- data/spec/protocol/license_spec.rb +67 -0
- data/spec/protocol/protocol_catalog_spec.rb +48 -0
- data/spec/protocol/protocol_validations_spec.rb +176 -0
- data/spec/protocol/source_spec.rb +65 -0
- data/spec/protocol_spec.rb +91 -37
- data/spec/receiver_model_spec.rb +111 -0
- data/spec/serialization/zaml_spec.rb +81 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +24 -7
- data/spec/support/icss_test_helper.rb +67 -0
- data/spec/support/load_example_protocols.rb +17 -0
- data/spec/type/base_type_spec.rb +0 -0
- data/spec/type/named_type_spec.rb +75 -0
- data/spec/type/record_field_spec.rb +44 -0
- data/spec/type/record_model_spec.rb +206 -0
- data/spec/type/record_schema_spec.rb +161 -0
- data/spec/type/record_type_spec.rb +155 -0
- data/spec/type/simple_types_spec.rb +121 -0
- data/spec/type/structured_schema_spec.rb +300 -0
- data/spec/type/type_catalog_spec.rb +44 -0
- data/spec/type/type_factory_spec.rb +93 -0
- data/spec/type/union_schema_spec.rb +0 -0
- data/spec/type_spec.rb +63 -0
- metadata +205 -144
- data/CHANGELOG.textile +0 -9
- data/Gemfile.lock +0 -40
- data/README.textile +0 -29
- data/lib/icss/brevity.rb +0 -136
- data/lib/icss/code_asset.rb +0 -16
- data/lib/icss/core_ext.rb +0 -9
- data/lib/icss/data_asset.rb +0 -22
- data/lib/icss/old.rb +0 -96
- data/lib/icss/protocol_set.rb +0 -48
- data/lib/icss/sample_message_call.rb +0 -142
- data/lib/icss/target.rb +0 -72
- data/lib/icss/type/factory.rb +0 -196
- data/lib/icss/validations.rb +0 -16
- data/spec/validations_spec.rb +0 -171
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'icss'
|
3
|
+
|
4
|
+
describe Icss::Meta::Protocol do
|
5
|
+
before do
|
6
|
+
Icss::Meta::Protocol.send :flush_registry
|
7
|
+
Icss::Meta::Protocol._catalog_loaded = true #prevent automatic loading of catalog
|
8
|
+
end
|
9
|
+
let(:protocol){ Icss::Meta::Protocol.receive(:protocol => 'test', :namespace => 'name.space') }
|
10
|
+
|
11
|
+
# Calling receive adds protocol to registry with after_receiver
|
12
|
+
describe :registry do
|
13
|
+
specify { Icss::Meta::Protocol.registry.should include('name.space.test' => protocol) }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#find' do
|
17
|
+
context 'specific protocol name parameters' do
|
18
|
+
before { protocol } # load protocol into registry
|
19
|
+
it('return protocol'){ Icss::Meta::Protocol.find('name.space.test').should == protocol }
|
20
|
+
it('should error if not found'){ lambda{ Icss::Meta::Protocol.find('name.space.not.found') }.should raise_error(Icss::NotFoundError) }
|
21
|
+
it('should error for wildcard name'){ lambda{ Icss::Meta::Protocol.find('name.*.test') }.should raise_error(Icss::NotFoundError) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'wildcard protocol name parameters' do
|
25
|
+
before { protocol } # load protocol into registry
|
26
|
+
context ':all' do
|
27
|
+
it('accepts wilcard names'){ Icss::Meta::Protocol.find(:all, 'name.*').should == [protocol] }
|
28
|
+
it('returns empty array if not found'){ Icss::Meta::Protocol.find(:all, 'not.*.found').should == [] }
|
29
|
+
end
|
30
|
+
|
31
|
+
context ':first' do
|
32
|
+
it('accepts wilcard names'){ Icss::Meta::Protocol.find(:first, 'name.*').should == protocol }
|
33
|
+
it('returns nil if not found'){ Icss::Meta::Protocol.find(:first, 'not.*.found').should be_nil }
|
34
|
+
end
|
35
|
+
|
36
|
+
context ':last' do
|
37
|
+
it('accepts wilcard names'){ Icss::Meta::Protocol.find(:last, 'name.*').should == protocol }
|
38
|
+
it('returns nil if not found'){ Icss::Meta::Protocol.find(:last, 'not.*.found').should be_nil }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
describe '#all, #first, #last' do
|
43
|
+
before { protocol } # load protocol into registry
|
44
|
+
it('#all returns all protocols'){ Icss::Meta::Protocol.all.should == [protocol] }
|
45
|
+
it('#first returns first of all protocols'){ Icss::Meta::Protocol.first.should == protocol }
|
46
|
+
it('#last returns last of all protocols'){ Icss::Meta::Protocol.last.should == protocol }
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'icss'
|
4
|
+
|
5
|
+
def template_icss
|
6
|
+
return <<EOS
|
7
|
+
---
|
8
|
+
namespace: foo.bar
|
9
|
+
protocol: baz
|
10
|
+
|
11
|
+
data_assets:
|
12
|
+
- name: test_data_asset
|
13
|
+
location: data/test_data.tsv
|
14
|
+
type: test_data_record
|
15
|
+
|
16
|
+
messages:
|
17
|
+
search:
|
18
|
+
doc: A testable template message
|
19
|
+
request:
|
20
|
+
- name: test_request
|
21
|
+
type: test_request_record
|
22
|
+
response: test_data_record
|
23
|
+
samples:
|
24
|
+
- request:
|
25
|
+
- first_param: foo
|
26
|
+
second_param: bar
|
27
|
+
|
28
|
+
targets:
|
29
|
+
catalog:
|
30
|
+
- name: test_catalog_entry
|
31
|
+
title: Test Icss
|
32
|
+
description: This is a template Icss to test the error handling of the Icss library.
|
33
|
+
tags:
|
34
|
+
- test
|
35
|
+
- icss
|
36
|
+
- template
|
37
|
+
messages:
|
38
|
+
- search
|
39
|
+
packages:
|
40
|
+
- data_assets:
|
41
|
+
- test_data_asset
|
42
|
+
|
43
|
+
types:
|
44
|
+
- name: test_request_record
|
45
|
+
doc: A template request record
|
46
|
+
type: record
|
47
|
+
fields:
|
48
|
+
- name: first_param
|
49
|
+
doc: The first test parameter
|
50
|
+
type: string
|
51
|
+
- name: second param
|
52
|
+
doc: The second test parameter
|
53
|
+
type: string
|
54
|
+
|
55
|
+
- name: test_complex_data
|
56
|
+
doc: A template complex data type
|
57
|
+
type: record
|
58
|
+
fields:
|
59
|
+
- name: field_one
|
60
|
+
doc: A simple field for a complex data type
|
61
|
+
type: string
|
62
|
+
- name: field_two
|
63
|
+
doc: Another simple field for a complex data type
|
64
|
+
type: string
|
65
|
+
|
66
|
+
- name: test_data_record
|
67
|
+
doc: A template data record
|
68
|
+
type: record
|
69
|
+
fields:
|
70
|
+
- name: simple_data
|
71
|
+
doc: A simple piece of data
|
72
|
+
type: int
|
73
|
+
- name: complex_data
|
74
|
+
doc: A complex piece of data
|
75
|
+
type: test_complex_data
|
76
|
+
|
77
|
+
EOS
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "Icss::Meta::Protocol validations" do
|
81
|
+
before :each do
|
82
|
+
@template = YAML.load(template_icss)
|
83
|
+
end
|
84
|
+
|
85
|
+
after :all do
|
86
|
+
Icss::Meta::TypeFactory.send :remove_instance_variable, :"@default_namespace"
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be able to receive a correctly formatted template Icss" do
|
90
|
+
lambda { @icss =Icss::Meta::Protocol.receive @template }.should_not raise_error
|
91
|
+
@icss.errors.should be_empty
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should contain keys for all fields even if not included in the Icss file" do
|
95
|
+
@icss = Icss::Meta::Protocol.receive @template
|
96
|
+
@icss.keys.map{|k| k.to_s }.sort.should == (@template.keys | %w[code_assets _doc_hints _extra_params tags categories credits doc title]).sort
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should generate an error when the namespace is formatted incorrectly" do
|
100
|
+
@template['namespace'] = '$bad_namespace'
|
101
|
+
Icss::Meta::Protocol.receive(@template).errors.keys.should == [:namespace]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should generate an error when the protocol is formatted incorrectly" do
|
105
|
+
@template['protocol'] = '$bad_protocol'
|
106
|
+
Icss::Meta::Protocol.receive(@template).errors.keys.should == [:protocol]
|
107
|
+
end
|
108
|
+
|
109
|
+
# context "Catalog Target" do
|
110
|
+
#
|
111
|
+
# it "should generate an error when an undefined data_asset is specified" do
|
112
|
+
# @template['targets']['catalog'].first['packages'].first['data_assets'] = ['fake_data_asset']
|
113
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:catalog]
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# it "should generate an error when an undefined message name is specified" do
|
117
|
+
# @template['targets']['catalog'].first['messages'] = ['fake_message']
|
118
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:catalog]
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# context "Data Assets" do
|
124
|
+
#
|
125
|
+
# it "should generate an error when an asset's type is undefined" do
|
126
|
+
# @template['data_assets'].first['type'] = 'fake_data_asset'
|
127
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:data_assets]
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# context "Messages" do
|
133
|
+
#
|
134
|
+
# it "should generate an error when a message's request type is undefined" do
|
135
|
+
# @template['messages']['search']['request'].first['type'] = 'fake_request_type'
|
136
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# it "should generate an error when a message's response type is undefined" do
|
140
|
+
# @template['messages']['search']['response'] = 'fake_response_type'
|
141
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# it "should generate an error when a message's sample request types do not match the request record" do
|
145
|
+
# @template['messages']['search']['samples'].first['request'] = [{ 'foo' => 'bar' }]
|
146
|
+
# Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# end
|
150
|
+
|
151
|
+
context "Types" do
|
152
|
+
|
153
|
+
it "should raise an error when an bad type definition is given for a specific type" do
|
154
|
+
@template['types'].push({
|
155
|
+
'name' => 'fake_type_record',
|
156
|
+
'type' => 'fake'
|
157
|
+
})
|
158
|
+
lambda{ Icss::Meta::Protocol.receive(@template) }.should raise_error(Icss::NotFoundError, /Cannot find.*fake/)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should generate an error when an undefined type definition is given for a specific field" do
|
162
|
+
@template['types'].push({
|
163
|
+
'name' => 'fake_type_record',
|
164
|
+
'type' => 'record',
|
165
|
+
'fields' => [{
|
166
|
+
'name' => 'fake_field',
|
167
|
+
'type' => 'fake_type'
|
168
|
+
}]
|
169
|
+
})
|
170
|
+
lambda{ Icss::Meta::Protocol.receive(@template) }.should raise_error(Icss::NotFoundError, /Cannot find.*fake_type/)
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'icss'
|
3
|
+
|
4
|
+
describe Icss::Meta::Source do
|
5
|
+
before do
|
6
|
+
Icss::Meta::Source.send :flush_registry
|
7
|
+
Icss::Meta::Source._catalog_loaded = true #prevent automatic loading of catalog
|
8
|
+
end
|
9
|
+
let(:source){ Icss::Meta::Source.receive(:source_id => 'sources.test', :title => 'Test source', :description => 'Source description', :url => 'http://test.com') }
|
10
|
+
|
11
|
+
describe '#name' do
|
12
|
+
specify { source.name.should == 'test' }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#fullname' do
|
16
|
+
specify { source.fullname.should == 'sources.test' }
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# Calling receive adds source to registry with after_receiver
|
22
|
+
describe :registry do
|
23
|
+
specify { Icss::Meta::Source.registry.should include('sources.test' => source) }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#find' do
|
27
|
+
context 'specific source name parameters' do
|
28
|
+
before { source } # load source into registry
|
29
|
+
it('return source'){ Icss::Meta::Source.find('sources.test').should == source }
|
30
|
+
it('should error if not found'){ lambda{ Icss::Meta::Source.find('sources.not_found') }.should raise_error(Icss::NotFoundError) }
|
31
|
+
it('should error for wildcard name'){ lambda{ Icss::Meta::Source.find('sources.*.test') }.should raise_error(Icss::NotFoundError) }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'wildcard source name parameters' do
|
35
|
+
before { source } # load source into registry
|
36
|
+
context ':all' do
|
37
|
+
it('accepts wilcard names'){ Icss::Meta::Source.find(:all, 'sources.*').should == [source] }
|
38
|
+
it('returns empty array if not found'){ Icss::Meta::Source.find(:all, 'not.*.found').should == [] }
|
39
|
+
end
|
40
|
+
|
41
|
+
context ':first' do
|
42
|
+
it('accepts wilcard names'){ Icss::Meta::Source.find(:first, 'sources.*').should == source }
|
43
|
+
it('returns nil if not found'){ Icss::Meta::Source.find(:first, 'not.*.found').should be_nil }
|
44
|
+
end
|
45
|
+
|
46
|
+
context ':last' do
|
47
|
+
it('accepts wilcard names'){ Icss::Meta::Source.find(:last, 'sources.*').should == source }
|
48
|
+
it('returns nil if not found'){ Icss::Meta::Source.find(:last, 'not.*.found').should be_nil }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
describe '#all, #first, #last' do
|
53
|
+
before { source } # load source into registry
|
54
|
+
it('#all returns all sources'){ Icss::Meta::Source.all.should == [source] }
|
55
|
+
it('#first returns first of all sources'){ Icss::Meta::Source.first.should == source }
|
56
|
+
it('#last returns last of all sources'){ Icss::Meta::Source.last.should == source }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#to_hash' do
|
60
|
+
it { source.to_hash.should == {:source_id => 'sources.test',
|
61
|
+
:title => 'Test source',
|
62
|
+
:description => 'Source description',
|
63
|
+
:url => 'http://test.com'}}
|
64
|
+
end
|
65
|
+
end
|
data/spec/protocol_spec.rb
CHANGED
@@ -1,26 +1,27 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
require 'icss'
|
3
3
|
|
4
|
-
describe Icss::Protocol do
|
4
|
+
describe Icss::Meta::Protocol do
|
5
|
+
|
5
6
|
let(:simple_icss) do
|
6
|
-
Icss::Protocol.receive_from_file(
|
7
|
+
Icss::Meta::Protocol.receive_from_file(ENV.root_path('examples/chronic.icss.yaml'))
|
7
8
|
end
|
8
9
|
|
9
10
|
it 'loads cleanly' do
|
10
|
-
simple_icss.
|
11
|
-
simple_icss.fullname.should == '
|
11
|
+
simple_icss.basename.should == 'chronic'
|
12
|
+
simple_icss.fullname.should == 'st.time_utils.chronic'
|
12
13
|
end
|
13
14
|
|
14
15
|
describe '#fullname' do
|
15
|
-
it 'has namespace and
|
16
|
-
simple_icss.fullname.should == '
|
16
|
+
it 'has namespace and basename' do
|
17
|
+
simple_icss.fullname.should == 'st.time_utils.chronic'
|
17
18
|
simple_icss.namespace = nil
|
18
19
|
simple_icss.fullname.should == 'chronic'
|
19
20
|
end
|
20
21
|
end
|
21
22
|
describe '#path' do
|
22
23
|
it 'is a / separated version of the name, with no / at start' do
|
23
|
-
simple_icss.path.should == '
|
24
|
+
simple_icss.path.should == 'st/time_utils/chronic'
|
24
25
|
end
|
25
26
|
end
|
26
27
|
describe '#doc' do
|
@@ -31,7 +32,7 @@ describe Icss::Protocol do
|
|
31
32
|
|
32
33
|
describe 'types' do
|
33
34
|
it 'has an array of types' do
|
34
|
-
simple_icss.types.map(&:
|
35
|
+
simple_icss.types.map(&:basename).should == ['chronic_parse_params', 'chronic_parse_response']
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
@@ -41,73 +42,126 @@ describe Icss::Protocol do
|
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'named each message for its key' do
|
44
|
-
simple_icss.messages['parse'].
|
45
|
+
simple_icss.messages['parse'].basename.should == 'parse'
|
45
46
|
simple_icss.receive!({ :messages => { 'foo' => { :request => [] } }})
|
46
|
-
simple_icss.messages['foo'].
|
47
|
+
simple_icss.messages['foo'].basename.should == 'foo'
|
47
48
|
end
|
48
49
|
|
49
50
|
it '#find_message' do
|
50
51
|
msg = simple_icss.find_message(:parse)
|
51
|
-
msg.should be_a(Icss::Message) ; msg.
|
52
|
-
msg = simple_icss.find_message('
|
53
|
-
msg.should be_a(Icss::Message) ; msg.
|
54
|
-
msg = simple_icss.find_message('
|
55
|
-
msg.should be_a(Icss::Message) ; msg.
|
52
|
+
msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
|
53
|
+
msg = simple_icss.find_message('st.time_utils.parse')
|
54
|
+
msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
|
55
|
+
msg = simple_icss.find_message('st/time_utils/parse')
|
56
|
+
msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
60
|
describe 'targets' do
|
60
61
|
it 'has a hash of targets' do
|
61
|
-
simple_icss.targets.keys.should == [
|
62
|
-
simple_icss.targets[
|
63
|
-
simple_icss.targets[
|
62
|
+
simple_icss.targets.keys.should == [:catalog]
|
63
|
+
simple_icss.targets[:catalog].first.should be_a(Icss::CatalogTarget)
|
64
|
+
simple_icss.targets[:catalog].first.basename.should == 'st_time_utils_chronic_parse'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'license' do
|
69
|
+
it 'returns nil if no license_id specified' do
|
70
|
+
simple_icss.license.should be_nil
|
71
|
+
end
|
72
|
+
it 'raises Icss::NotFoundError if license_id specified and not found' do
|
73
|
+
simple_icss.license_id = 'not_found_license'
|
74
|
+
lambda{ simple_icss.license }.should raise_error(Icss::NotFoundError, /Cannot find .*/)
|
75
|
+
end
|
76
|
+
it 'returns the Icss::Meta::License object' do
|
77
|
+
license = Icss::Meta::License.receive_from_file(ENV.root_path('examples/license.icss.yaml'))
|
78
|
+
simple_icss.license_id = 'licenses.example'
|
79
|
+
simple_icss.license.should == license
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
describe 'sources' do
|
86
|
+
it 'returns empty array if no source_ids specified' do
|
87
|
+
simple_icss.sources.should == {}
|
88
|
+
end
|
89
|
+
it 'raises Icss::NotFoundError if license_id specified and not found' do
|
90
|
+
simple_icss.credits = { :role => 'not_found_license' }
|
91
|
+
lambda{ simple_icss.sources }.should raise_error(Icss::NotFoundError, /Cannot find .*/)
|
92
|
+
end
|
93
|
+
it 'returns array of Icss::Meta::Source objects' do
|
94
|
+
source2 = Icss::Meta::Source.receive_from_file(ENV.root_path('examples/source2.icss.yaml'))
|
95
|
+
source1 = Icss::Meta::Source.receive_from_file(ENV.root_path('examples/source1.icss.yaml'))
|
96
|
+
simple_icss.credits = {:main => 'sources.source1', :uploaded => 'sources.source2'}
|
97
|
+
simple_icss.sources.should == { :main => source1, :uploaded => source2 }
|
64
98
|
end
|
65
99
|
end
|
66
|
-
|
67
|
-
# describe 'tree_merge!' do
|
68
|
-
# it 'merges recursively'
|
69
|
-
# end
|
70
100
|
|
71
101
|
describe 'validations' do
|
72
102
|
it 'validates protocol name' do
|
73
103
|
simple_icss.should be_valid
|
74
|
-
simple_icss.protocol = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should
|
75
|
-
simple_icss.protocol = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should
|
104
|
+
simple_icss.protocol = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should include("can't be blank")
|
105
|
+
simple_icss.protocol = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should include("must start with [A-Za-z_] and contain only [A-Za-z0-9_].")
|
76
106
|
end
|
77
107
|
|
78
108
|
it 'validates namespace' do
|
79
109
|
simple_icss.should be_valid
|
80
|
-
simple_icss.namespace = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].should
|
81
|
-
simple_icss.namespace = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].first.should =~ /
|
110
|
+
simple_icss.namespace = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].should include("can't be blank")
|
111
|
+
simple_icss.namespace = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].first.should =~ /Segments that start with.*joined by.*dots/
|
82
112
|
end
|
83
113
|
end
|
84
114
|
|
85
115
|
describe '#to_hash' do
|
86
116
|
it 'roundtrips' do
|
117
|
+
simple_icss.license_id = 'licenses.example'
|
118
|
+
simple_icss.credits = { :original => 'sources.source1' }
|
119
|
+
simple_icss.tags = ['tag1', 'tag2', 'tag3']
|
120
|
+
simple_icss.categories = ['category1', 'category2', 'category3']
|
87
121
|
hsh = simple_icss.to_hash
|
88
122
|
hsh.should == {
|
89
|
-
:namespace=>"
|
123
|
+
:namespace=>"st.time_utils", :protocol=>"chronic",
|
90
124
|
:doc=>"A series of calls hooking into the Chronic ruby gem",
|
125
|
+
:license_id=>"licenses.example",
|
126
|
+
:credits=>{:original=>"sources.source1"},
|
127
|
+
:tags=>['tag1', 'tag2', 'tag3'],
|
128
|
+
:categories=>['category1', 'category2', 'category3'],
|
91
129
|
:types => [
|
92
|
-
{:name=>"chronic_parse_params",
|
130
|
+
{:name=>"st.time_utils.chronic_parse_params",
|
131
|
+
:namespace=>"st.time_utils",
|
132
|
+
:type=>:record,
|
133
|
+
:doc=>"Query API parameters for the /st/time_utils/chronic/parse call",
|
93
134
|
:fields=>[
|
94
|
-
{:name
|
95
|
-
{:name
|
96
|
-
{:name
|
97
|
-
{:name
|
135
|
+
{:name=>:time_str, :type=>:string, :doc=>"The string to parse."},
|
136
|
+
{:name=>:context, :type=>:symbol, :doc=>"<tt>past</tt> or <tt>future</tt> (defaults to <tt>future</tt>)\nIf your string represents a birthday, you can set <tt>context</tt> to <tt>past</tt> and if an ambiguous string is given, it will assume it is in the past. Specify <tt>future</tt> or omit to set a future context."},
|
137
|
+
{:name=>:now, :type=>:time, :doc=>"Time (defaults to Time.now)\nBy setting <tt>:now</tt> to a Time, all computations will be based off of that time instead of Time.now. If set to nil, Chronic will use the current time in UTC. You must supply a date that unambiguously parses with the much-less-generous ruby Time.parse()"},
|
138
|
+
{:name=>:ambiguous_time_range, :type=>:int, :doc=>"Integer or <tt>:none</tt> (defaults to <tt>6</tt> (6am-6pm))\nIf an Integer is given, ambiguous times (like 5:00) will be assumed to be within the range of that time in the AM to that time in the PM. For example, if you set it to <tt>7</tt>, then the parser will look for the time between 7am and 7pm. In the case of 5:00, it would assume that means 5:00pm. If <tt>:none</tt> is given, no assumption will be made, and the first matching instance of that time will be used."}
|
98
139
|
]},
|
99
|
-
{:name=>"chronic_parse_response",
|
140
|
+
{:name=>"st.time_utils.chronic_parse_response",
|
141
|
+
:namespace=>"st.time_utils",
|
142
|
+
:type=>:record,
|
143
|
+
:doc=>"Query API response for the /util/time/chronic/parse call",
|
100
144
|
:fields=>[
|
101
|
-
{:name
|
102
|
-
{:name
|
145
|
+
{:name=>:time, :type=>:string, :doc=>"The UTC parsed time, as a \"ISO 8601 combined date time\":http://en.wikipedia.org/wiki/ISO_8601 string."},
|
146
|
+
{:name=>:epoch_seconds, :type=>:int, :doc=>"The UTC parsed time, as \"epoch seconds\":http://en.wikipedia.org/wiki/Epoch_seconds integer."}
|
103
147
|
]}
|
104
148
|
],
|
105
149
|
:messages => {
|
106
|
-
|
150
|
+
:parse => {
|
151
|
+
:request =>[{:name=>:chronic_parse_params, :type=>"st.time_utils.chronic_parse_params"}],
|
152
|
+
:response =>"st.time_utils.chronic_parse_response",
|
153
|
+
:doc=>"\nChronic is a natural language date/time parser written in pure Ruby. See below\nfor the wide variety of formats Chronic will parse.",
|
154
|
+
:samples =>[{
|
155
|
+
:request=>[{"time_str"=>"one hour ago", "now"=>"2007-03-16T12:09:08Z"}],
|
156
|
+
:response=>{"epoch_seconds"=>1174043348, "time"=>"2007-03-16T11:09:08Z"}, :url=>"?now=2007-03-16T12%3A09%3A08Z&time_str=one%20hour%20ago"},
|
157
|
+
{:request=>[{"time_str"=>"Yesterday", "now"=>"5:06:07T2010-08-08Z"}],
|
158
|
+
:response=>{"epoch_seconds"=>1281182400, "time"=>"2010-08-07T12:00:00Z"}, :url=>"?now=5%3A06%3A07%202010-08-08&time_str=Yesterday"},
|
159
|
+
{:url=>"?time_str=5pm+on+November+4th&context=past"}]
|
160
|
+
},
|
107
161
|
},
|
108
162
|
:data_assets=>[],
|
109
163
|
:code_assets=>[{:location=>"code/chronic_endpoint.rb"}],
|
110
|
-
:targets => {
|
164
|
+
:targets => {:catalog=>[{:name=>"st_time_utils_chronic_parse", :title=>"Utils - Parse Times", :description=>"An API call to parse human-readable date / time strings", :tags=>["apiawesome", "ruby", "gems", "chronic", "time", "date", "util", "parse"], :messages=>["parse"]}]},
|
111
165
|
}
|
112
166
|
end
|
113
167
|
end
|