icss 0.1.3 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|