instedd-pigeon 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/.gitignore +25 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +140 -0
  6. data/Rakefile +1 -0
  7. data/app/assets/images/pigeon/android_local_gateway_preview.png +0 -0
  8. data/app/assets/images/pigeon/android_local_gateway_qr.png +0 -0
  9. data/app/assets/images/pigeon/other_local_gateway_preview.png +0 -0
  10. data/app/assets/javascripts/pigeon/qst-server-wizard.js.coffee +58 -0
  11. data/app/assets/javascripts/pigeon/template.js.coffee +43 -0
  12. data/app/assets/javascripts/pigeon/twitter-template.js.coffee +38 -0
  13. data/app/assets/javascripts/pigeon/wizard.js.coffee +95 -0
  14. data/app/assets/javascripts/pigeon.js +2 -0
  15. data/app/assets/stylesheets/pigeon.css.sass +13 -0
  16. data/app/controllers/pigeon/twitter_controller.rb +44 -0
  17. data/app/helpers/.gitkeep +0 -0
  18. data/app/helpers/pigeon/channel_helper.rb +93 -0
  19. data/app/helpers/pigeon/renderer/base.rb +172 -0
  20. data/app/helpers/pigeon/renderer/channel_renderer.rb +58 -0
  21. data/app/helpers/pigeon/renderer.rb +8 -0
  22. data/app/helpers/pigeon/tag_helper.rb +26 -0
  23. data/app/helpers/pigeon/template_helper.rb +20 -0
  24. data/app/helpers/pigeon/text_helper.rb +16 -0
  25. data/app/models/.gitkeep +0 -0
  26. data/app/models/pigeon/channel.rb +220 -0
  27. data/app/models/pigeon/channel_attribute.rb +64 -0
  28. data/app/models/pigeon/channel_schema.rb +113 -0
  29. data/app/models/pigeon/nested_attribute.rb +23 -0
  30. data/app/models/pigeon/nested_scopes.rb +34 -0
  31. data/app/models/pigeon/nuntium_channel.rb +92 -0
  32. data/app/models/pigeon/verboice_channel.rb +82 -0
  33. data/app/views/pigeon/twitter/callback.html.erb +6 -0
  34. data/config/routes.rb +4 -0
  35. data/config/schemas/nuntium/nuntium.yml +210 -0
  36. data/config/schemas/nuntium/qst-server.yml +180 -0
  37. data/config/schemas/nuntium/twitter.yml +56 -0
  38. data/config/schemas/verboice/verboice.yml +76 -0
  39. data/lib/pigeon/engine.rb +30 -0
  40. data/lib/pigeon/errors.rb +28 -0
  41. data/lib/pigeon/initializer.rb +13 -0
  42. data/lib/pigeon/nuntium.rb +10 -0
  43. data/lib/pigeon/verboice.rb +10 -0
  44. data/lib/pigeon/version.rb +3 -0
  45. data/lib/pigeon.rb +25 -0
  46. data/pigeon.gemspec +24 -0
  47. data/spec/data/test_schemas.yml +21 -0
  48. data/spec/dummy/README.rdoc +261 -0
  49. data/spec/dummy/Rakefile +7 -0
  50. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  51. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  52. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  53. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  54. data/spec/dummy/app/mailers/.gitkeep +0 -0
  55. data/spec/dummy/app/models/.gitkeep +0 -0
  56. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  57. data/spec/dummy/config/application.rb +59 -0
  58. data/spec/dummy/config/boot.rb +10 -0
  59. data/spec/dummy/config/database.yml +25 -0
  60. data/spec/dummy/config/environment.rb +5 -0
  61. data/spec/dummy/config/environments/development.rb +37 -0
  62. data/spec/dummy/config/environments/production.rb +67 -0
  63. data/spec/dummy/config/environments/test.rb +37 -0
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/spec/dummy/config/initializers/inflections.rb +15 -0
  66. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  67. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  68. data/spec/dummy/config/initializers/session_store.rb +8 -0
  69. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/dummy/config/locales/en.yml +5 -0
  71. data/spec/dummy/config/routes.rb +3 -0
  72. data/spec/dummy/config.ru +4 -0
  73. data/spec/dummy/lib/assets/.gitkeep +0 -0
  74. data/spec/dummy/log/.gitkeep +0 -0
  75. data/spec/dummy/public/404.html +26 -0
  76. data/spec/dummy/public/422.html +26 -0
  77. data/spec/dummy/public/500.html +25 -0
  78. data/spec/dummy/public/favicon.ico +0 -0
  79. data/spec/dummy/script/rails +6 -0
  80. data/spec/helpers/pigeon/channel_helper_spec.rb +173 -0
  81. data/spec/helpers/pigeon/renderer/base_spec.rb +109 -0
  82. data/spec/helpers/pigeon/renderer/channel_renderer_spec.rb +61 -0
  83. data/spec/helpers/pigeon/tag_helper_spec.rb +36 -0
  84. data/spec/helpers/pigeon/template_helper_spec.rb +57 -0
  85. data/spec/models/pigeon/channel_attribute_spec.rb +98 -0
  86. data/spec/models/pigeon/channel_schema_spec.rb +63 -0
  87. data/spec/models/pigeon/channel_spec.rb +205 -0
  88. data/spec/models/pigeon/nuntium_channel_spec.rb +53 -0
  89. data/spec/spec_helper.rb +43 -0
  90. data/spec/support/active_model_lint.rb +15 -0
  91. data/spec/support/test_schemas.rb +12 -0
  92. metadata +254 -0
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ module Renderer
5
+ describe "ChannelRenderer" do
6
+ before(:each) do
7
+ @channel = Channel.new foo: '42'
8
+ @renderer = ChannelRenderer.new @channel
9
+ end
10
+
11
+ it "should handle @field commands" do
12
+ @renderer.render(['@field', 'foo']).should have_tag('input', with: {
13
+ name: 'foo', value: '42'
14
+ })
15
+ end
16
+
17
+ it "should handle @label commands" do
18
+ @renderer.render(['@label', 'foo']).should have_tag('label', with: {
19
+ :for => 'foo' }, text: 'Foo')
20
+ end
21
+
22
+ it "should handle @attr commands" do
23
+ @renderer.render(['@attr', 'foo']).should have_tag('div') do
24
+ with_tag 'label', with: { :for => 'foo' }
25
+ with_tag 'input', with: { :name => 'foo', :value => '42' }
26
+ end
27
+ end
28
+
29
+ it "should handle @hidden commands" do
30
+ @renderer.render(['@hidden', 'foo']).should have_tag('input', with: {
31
+ name: 'foo', type: 'hidden'
32
+ })
33
+ end
34
+
35
+ it "should accept options for attribute commands" do
36
+ @renderer.render(['@attr', { "class" => "field" }, 'foo']).should \
37
+ have_tag('div', with: { 'class' => 'field' }) do
38
+ with_tag 'label'
39
+ with_tag 'input'
40
+ end
41
+ end
42
+
43
+ context "with a scope" do
44
+ before(:each) do
45
+ @channel = Channel.new foo: '42'
46
+ @renderer = ChannelRenderer.new @channel, 'channel_data'
47
+ end
48
+
49
+ it "should add a scope attribute to @template and @wizard commands" do
50
+ @renderer.render(['@template']).should have_tag('div', with: {
51
+ "data-scope" => "channel_data"
52
+ })
53
+ @renderer.render(['@wizard']).should have_tag('div', with: {
54
+ "data-scope" => "channel_data"
55
+ })
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ # Specs in this file have access to a helper object that includes
4
+ # the TagHelper. For example:
5
+ #
6
+ # describe TagHelper do
7
+ # describe "string concat" do
8
+ # it "concats two strings with spaces" do
9
+ # helper.concat_strings("this","that").should == "this that"
10
+ # end
11
+ # end
12
+ # end
13
+ module Pigeon
14
+ describe TagHelper do
15
+ describe "pigeon_schema_options" do
16
+ before(:each) do
17
+ @schemas = NuntiumChannel.schemas
18
+ end
19
+
20
+ it "returns a list of schemas appropiate for options_for_select" do
21
+ options = helper.pigeon_schema_options(@schemas)
22
+ options.count.should eq(@schemas.count)
23
+ options.all? { |o|
24
+ o.respond_to?(:first) && o.respond_to?(:last)
25
+ }.should be_true
26
+ end
27
+
28
+ it "prefixes values with given string" do
29
+ options = helper.pigeon_schema_options(@schemas, 'foo/')
30
+ options.all? { |o|
31
+ o.last.starts_with? 'foo/'
32
+ }.should be_true
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ describe TemplateHelper do
5
+ describe "pigeon_render_template" do
6
+ it "should render static templates" do
7
+ helper.pigeon_render_template(["div"]).should eq("<div></div>")
8
+ end
9
+
10
+ it "should delegate commands to the given block" do
11
+ out = helper.pigeon_render_template(["@x"]) do |args|
12
+ args.first.should eq("@x")
13
+ "x marks the spot"
14
+ end
15
+ out.should eq("x marks the spot")
16
+ end
17
+
18
+ it "should render unhandled commands as an empty string" do
19
+ helper.pigeon_render_template(["@x"]).should eq("")
20
+ end
21
+ end
22
+
23
+ describe "pigeon_render_channel_template" do
24
+ before(:each) do
25
+ @schema = ChannelSchema.from_hash 'nuntium', test_schema_hash('foobar')
26
+ @channel = Channel.new schema: @schema
27
+ end
28
+
29
+ it "should render the given template with attributes from the channel" do
30
+ helper.pigeon_render_channel_template(@channel, ['@field', 'ticket_code'], nil).
31
+ should have_tag('input', with: { name: 'ticket_code' })
32
+ end
33
+
34
+ it "should render the channel's schema template by default" do
35
+ out = helper.pigeon_render_channel_template(@channel, nil, nil)
36
+ out.should have_tag('input', with: { name: 'ticket_code' })
37
+ out.should have_tag('input', with: { name: 'configuration[user]' })
38
+ end
39
+
40
+ it "should delegate unknown commands to the given block" do
41
+ helper.pigeon_render_channel_template(@channel, ['@x']) do |args|
42
+ args.first.should eq('@x')
43
+ 'XXX'
44
+ end.should eq('XXX')
45
+ end
46
+
47
+ it "should by default use the 'channel' scope" do
48
+ helper.pigeon_render_channel_template(@channel, ['@field', 'ticket_code']). should have_tag('input', with: { name: 'channel[ticket_code]' })
49
+ end
50
+
51
+ it "should wrap channel's attributes in the given scope" do
52
+ helper.pigeon_render_channel_template(@channel, ['@field', 'ticket_code'], 'foo'). should have_tag('input', with: { name: 'foo[ticket_code]' })
53
+ end
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ describe ChannelAttribute do
5
+ it "should require a name" do
6
+ lambda { ChannelAttribute.new nil, 'bar' }.should raise_error(ArgumentError)
7
+ lambda { ChannelAttribute.new '', 'bar' }.should raise_error(ArgumentError)
8
+ end
9
+
10
+ it "should require a type" do
11
+ lambda { ChannelAttribute.new 'foo', nil }.should raise_error(ArgumentError)
12
+ end
13
+
14
+ it "should validate type" do
15
+ lambda { ChannelAttribute.new 'foo', 'bar' }.should raise_error(ArgumentError)
16
+ end
17
+
18
+ it "should set label and humanized name by default" do
19
+ @attr = ChannelAttribute.new 'foo', :string
20
+ @attr.label.should_not be_blank
21
+ @attr.humanized_name.should_not be_blank
22
+ end
23
+
24
+ it "should humanize label and humanized name by default" do
25
+ @attr = ChannelAttribute.new 'some_field', :string
26
+ @attr.label.should eq('Some field')
27
+ @attr.humanized_name.should eq('Some field')
28
+ end
29
+
30
+ it "should set label from humanized name if not given" do
31
+ @attr = ChannelAttribute.new 'foo', :string, humanized_name: 'bar'
32
+ @attr.label.should eq('bar')
33
+ @attr.humanized_name.should eq('bar')
34
+ end
35
+
36
+ it "should set humanized name from label if not given" do
37
+ @attr = ChannelAttribute.new 'foo', :string, label: 'bar'
38
+ @attr.label.should eq('bar')
39
+ @attr.humanized_name.should eq('bar')
40
+ end
41
+
42
+ it "should initialize options to empty array" do
43
+ @attr = ChannelAttribute.new 'foo', :enum
44
+ @attr.options.should_not be_nil
45
+ end
46
+
47
+ it "should have a scope" do
48
+ @attr = ChannelAttribute.new 'foo', :string
49
+ @attr.should respond_to(:scope)
50
+ @attr.should respond_to(:scope=)
51
+ end
52
+
53
+ it "should compute its scoped name" do
54
+ @foo = ChannelAttribute.new 'foo', :string
55
+ @bar = ChannelAttribute.new 'bar', :string
56
+
57
+ @bar.scoped_name.should eq('bar')
58
+ @bar.scoped_name('bling').should eq('bling[bar]')
59
+
60
+ @bar.scope = @foo
61
+ @bar.scoped_name.should eq('foo[bar]')
62
+ @bar.scoped_name('bling').should eq('bling[foo][bar]')
63
+ end
64
+
65
+ describe "build_default" do
66
+ it "should create a valid string attribute by default" do
67
+ attr = ChannelAttribute.build_default('foo')
68
+ attr.should_not be_nil
69
+ attr.should be_a(ChannelAttribute)
70
+ attr.type.should eq(:string)
71
+ attr.name.should eq('foo')
72
+ end
73
+
74
+ it "should create a boolean attribute if the value is boolean" do
75
+ ChannelAttribute.build_default('foo', true).type.should eq(:boolean)
76
+ ChannelAttribute.build_default('foo', false).type.should eq(:boolean)
77
+ end
78
+
79
+ it "should create an integer attribute if the value is an integer number" do
80
+ ChannelAttribute.build_default('foo', 10).type.should eq(:integer)
81
+ end
82
+
83
+ it "should build a scope if the attribute name is scoped" do
84
+ attr = ChannelAttribute.build_default('foo[bar]')
85
+ attr.name.should eq('bar')
86
+ attr.scoped_name.should eq('foo[bar]')
87
+ attr.scoped_name('baz').should eq('baz[foo][bar]')
88
+ end
89
+
90
+ it "should build a recursive scope if the attribute name is deeply nested" do
91
+ attr = ChannelAttribute.build_default('baz[foo][bar]')
92
+ attr.name.should eq('bar')
93
+ attr.scoped_name.should eq('baz[foo][bar]')
94
+ attr.scoped_name('outer').should eq('outer[baz][foo][bar]')
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ describe ChannelSchema do
5
+ before(:each) do
6
+ @schema = ChannelSchema.from_hash 'nuntium', test_schema_hash('foobar')
7
+ end
8
+
9
+ context "on initialization" do
10
+ it "should validate the presence of type" do
11
+ lambda do
12
+ ChannelSchema.new '', 'foo'
13
+ end.should raise_error(ArgumentError)
14
+ end
15
+
16
+ it "should validate the presence of kind" do
17
+ lambda do
18
+ ChannelSchema.new 'foo', ''
19
+ end.should raise_error(ArgumentError)
20
+ end
21
+ end
22
+
23
+ describe "from_hash" do
24
+ it "should set the type and kind" do
25
+ @schema.type.should eq('nuntium')
26
+ @schema.kind.should eq('foobar')
27
+ end
28
+ end
29
+
30
+ it "should return only first level attributes as known_attributes" do
31
+ @schema.known_attributes.sort.should eq(%w(protocol ticket_code configuration).sort)
32
+ end
33
+
34
+ it "should list user attributes including nested ones" do
35
+ @schema.user_attributes.sort.should eq(%w(ticket_code configuration[user] configuration[password] configuration[port] configuration[send_offline]).sort)
36
+ end
37
+
38
+ it "should build a hash with default values, including nested attributes" do
39
+ values = @schema.default_values
40
+ values.count.should eq(2)
41
+ values.keys.sort.should eq(%w(configuration protocol).sort)
42
+ values['protocol'].should eq('foobar')
43
+ values['configuration'].should be_a_kind_of(Hash)
44
+ values['configuration']['port'].should eq(5222)
45
+ end
46
+
47
+ it "should find shallow attributes" do
48
+ @schema.find_attribute('protocol').should_not be_nil
49
+ @schema.find_attribute('protocol').name.should eq('protocol')
50
+ end
51
+
52
+ it "should find nested attributes" do
53
+ @schema.find_attribute('configuration[port]').should_not be_nil
54
+ @schema.find_attribute('configuration[port]').name.should eq('port')
55
+ end
56
+
57
+ it "nested attributes should have a scope" do
58
+ @schema.find_attribute('configuration[port]').scope.should_not be_nil
59
+ @schema.find_attribute('configuration[port]').scoped_name.
60
+ should eq('configuration[port]')
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ describe Channel do
5
+ it_behaves_like "ActiveModel"
6
+
7
+ describe "common attributes" do
8
+ before(:each) do
9
+ @channel = Channel.new
10
+ end
11
+
12
+ it "should respond to type" do
13
+ @channel.should respond_to(:type)
14
+ end
15
+
16
+ ['name', 'kind'].each do |name|
17
+ it "should respond to #{name}" do
18
+ @channel.should respond_to(name.to_sym)
19
+ @channel.should respond_to("#{name}=".to_sym)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "default instantiation" do
25
+ before(:each) do
26
+ @channel = Channel.new
27
+ end
28
+
29
+ it "should be of nil type" do
30
+ @channel.type.should be_nil
31
+ end
32
+
33
+ it "should not be persisted" do
34
+ @channel.should_not be_persisted
35
+ end
36
+ end
37
+
38
+ describe "with attributes" do
39
+ before(:each) do
40
+ @attributes = { kind: 'foo', name: 'bar', other: true }
41
+ @channel = Channel.new @attributes
42
+ end
43
+
44
+ it "should set each attribute" do
45
+ @attributes.each do |k,v|
46
+ @channel.send(k.to_sym).should eq(v)
47
+ end
48
+ end
49
+
50
+ it "should expose attributes through []" do
51
+ @channel['kind'].should eq(@attributes[:kind])
52
+ @channel['name'].should eq(@attributes[:name])
53
+ end
54
+
55
+ it "should allow writing attributes through []" do
56
+ @channel['other'] = false
57
+ @channel.other.should be_false
58
+ end
59
+ end
60
+
61
+ describe "with nested attributes" do
62
+ before(:each) do
63
+ @config = { foo: 42, bar: 'baz' }
64
+ @channel = Channel.new configuration: @config
65
+ end
66
+
67
+ it "should dup nested values" do
68
+ @config.each do |k,v|
69
+ @channel.configuration[k].should be(@config[k])
70
+ end
71
+ @channel.configuration.should_not be(@config)
72
+ end
73
+
74
+ it "should have indifferent access" do
75
+ @config.each do |k,v|
76
+ @channel.configuration[k.to_s].should be(@config[k])
77
+ @channel.configuration[k.to_sym].should be(@config[k])
78
+ end
79
+ end
80
+
81
+ it "load should merge hashes" do
82
+ @channel.send(:load, { configuration: { hello: 'world' }})
83
+ @channel.configuration[:foo].should eq(@config[:foo])
84
+ @channel.configuration[:bar].should eq(@config[:bar])
85
+ @channel.configuration[:hello].should eq('world')
86
+ end
87
+ end
88
+
89
+ describe "validations" do
90
+ before(:each) do
91
+ @valid_attributes = { name: 'foo', kind: 'bar' }
92
+ @channel = Channel.new @valid_attributes
93
+ end
94
+
95
+ it "should be valid with valid attributes" do
96
+ @channel.should be_valid
97
+ end
98
+
99
+ it "should validate presence of name" do
100
+ @channel.name = nil
101
+ @channel.should_not be_valid
102
+ end
103
+
104
+ it "should validate presence of kind" do
105
+ @channel.kind = nil
106
+ @channel.should_not be_valid
107
+ end
108
+ end
109
+
110
+ describe "types and schemas" do
111
+ it "should find defined types" do
112
+ %w(nuntium verboice).each do |type|
113
+ Channel.find_type(type).should_not be_nil
114
+ Channel.find_type(type.to_sym).should_not be_nil
115
+ Channel.find_type(type).type.to_s.should eq(type)
116
+ end
117
+ end
118
+
119
+ it "should return nil for undefined types" do
120
+ Channel.find_type('foobar').should be_nil
121
+ end
122
+
123
+ context "when initialized with a schema" do
124
+ before(:each) do
125
+ @schema = ChannelSchema.from_hash 'nuntium', test_schema_hash('foobar')
126
+ end
127
+
128
+ it "should set the schema" do
129
+ @channel = Channel.new schema: @schema
130
+ @channel.schema.should be(@schema)
131
+ end
132
+
133
+ it "should set the kind if none is given" do
134
+ @channel = Channel.new schema: @schema
135
+ @channel.kind.should eq(@schema.kind)
136
+ end
137
+
138
+ it "should not override kind if one is given" do
139
+ @channel = Channel.new schema: @schema, kind: 'dont_override'
140
+ @channel.kind.should eq('dont_override')
141
+ end
142
+
143
+ it "should not set the schema as an attribute" do
144
+ @channel = Channel.new schema: @schema
145
+ @channel.attributes[:schema].should be_nil
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "read and write attributes" do
151
+ before(:each) do
152
+ @channel = Channel.new foo: 42, bar: { baz: 1, pepe: 'hi' }
153
+ end
154
+
155
+ it "should read shallow and nested attributes" do
156
+ @channel.read_attribute('foo').should eq(@channel.foo)
157
+ @channel.read_attribute('bar[baz]').should eq(@channel.bar['baz'])
158
+ @channel.read_attribute('bar[pepe]').should eq(@channel.bar['pepe'])
159
+ end
160
+
161
+ it "should write shallow and nested attributes" do
162
+ @channel.write_attribute('foo', 33)
163
+ @channel.foo.should eq(33)
164
+
165
+ @channel.write_attribute('bar[pepe]', 'bye')
166
+ @channel.bar['pepe'].should eq('bye')
167
+ end
168
+
169
+ it "should return nil when reading unexisting attribute" do
170
+ @channel.read_attribute('fnord').should be_nil
171
+ @channel.read_attribute('fnord[foo]').should be_nil
172
+ @channel.read_attribute('foo[fnord]').should be_nil
173
+ @channel.read_attribute('bar[fnord]').should be_nil
174
+ end
175
+
176
+ it "should ignore writes to unexisting attributes" do
177
+ @channel.write_attribute('fnord[foo]', 5).should be_nil
178
+ @channel.write_attribute('foo[fnord]', 5).should be_nil
179
+ @channel.write_attribute('bar[fnord][blah]', 5).should be_nil
180
+ end
181
+ end
182
+
183
+ describe "attributes assignment" do
184
+ before(:each) do
185
+ @channel = Channel.new foo: 42, bar: { baz: 1, pepe: 'hi' }
186
+ end
187
+
188
+ it "should assign shallow attributes" do
189
+ @channel.assign_attributes(foo: 123)
190
+ @channel.foo.should eq(123)
191
+ end
192
+
193
+ it "should assign nested attributes" do
194
+ @channel.assign_attributes(bar: { baz: 42 })
195
+ @channel.bar[:baz].should eq(42)
196
+ end
197
+
198
+ it "should assign scoped attributes" do
199
+ @channel.assign_attributes('bar[baz]' => 42)
200
+ @channel.bar[:baz].should eq(42)
201
+ end
202
+ end
203
+ end
204
+ end
205
+
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ module Pigeon
4
+ describe NuntiumChannel do
5
+ describe "basic attributes" do
6
+ before(:each) do
7
+ @channel = NuntiumChannel.new
8
+ end
9
+
10
+ it "should be of nuntium type" do
11
+ @channel.type.should be(:nuntium)
12
+ end
13
+
14
+ [:protocol, :enabled, :direction, :priority].each do |attr|
15
+ it "should respond to #{attr} methods" do
16
+ @channel.should respond_to(attr)
17
+ @channel.should respond_to("#{attr}=")
18
+ end
19
+ end
20
+
21
+ it "should have default values" do
22
+ @channel.protocol.should_not be_nil
23
+ @channel.enabled.should be_true
24
+ @channel.direction.should eq("bidirectional")
25
+ @channel.priority.should eq(100)
26
+ end
27
+ end
28
+
29
+ it "should load static schemas" do
30
+ NuntiumChannel.schemas.should_not be_empty
31
+ NuntiumChannel.find_schema('pop3').should_not be_nil
32
+ end
33
+
34
+ describe "when initialized with kind" do
35
+ before(:each) do
36
+ @channel = NuntiumChannel.new kind: 'xmpp'
37
+ end
38
+
39
+ it "should find schema" do
40
+ @channel.schema.should_not be_nil
41
+ end
42
+
43
+ it "should set schema's default values" do
44
+ @channel.protocol.should eq('xmpp')
45
+ end
46
+
47
+ it "should set nested default schema values" do
48
+ @channel.configuration['port'].should eq(5222)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,43 @@
1
+ # Configure Rails Envinronment
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
4
+
5
+ require 'rspec/rails'
6
+
7
+ ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../')
8
+
9
+ # Requires supporting ruby files with custom matchers and macros, etc,
10
+ # in spec/support/ and its subdirectories.
11
+ Dir[File.join(ENGINE_RAILS_ROOT, "spec/support/**/*.rb")].each {|f| require f }
12
+
13
+ TEST_DATA_PATH = File.join(File.dirname(__FILE__), 'data')
14
+
15
+ RSpec.configure do |config|
16
+ # ## Mock Framework
17
+ #
18
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
19
+ #
20
+ # config.mock_with :mocha
21
+ # config.mock_with :flexmock
22
+ # config.mock_with :rr
23
+
24
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
25
+ config.fixture_path = "#{ENGINE_RAILS_ROOT}/spec/fixtures"
26
+
27
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
28
+ # examples within a transaction, remove the following line or assign false
29
+ # instead of true.
30
+ config.use_transactional_fixtures = true
31
+
32
+ # If true, the base class of anonymous controllers will be inferred
33
+ # automatically. This will be the default behavior in future versions of
34
+ # rspec-rails.
35
+ config.infer_base_class_for_anonymous_controllers = false
36
+
37
+ # Run specs in random order to surface order dependencies. If you find an
38
+ # order dependency and want to debug it, you can fix the order by providing
39
+ # the seed, which is printed after each run.
40
+ # --seed 1234
41
+ config.order = "random"
42
+ end
43
+
@@ -0,0 +1,15 @@
1
+ shared_examples_for "ActiveModel" do
2
+ include ActiveModel::Lint::Tests
3
+
4
+ # to_s is to support ruby-1.9
5
+ ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
6
+ example m.gsub('_',' ') do
7
+ send m
8
+ end
9
+ end
10
+
11
+ def model
12
+ subject
13
+ end
14
+ end
15
+
@@ -0,0 +1,12 @@
1
+ def test_schema_list
2
+ YAML::load_file(File.join(TEST_DATA_PATH, 'test_schemas.yml'))
3
+ end
4
+
5
+ def test_schema_hash(key)
6
+ data = test_schema_list
7
+ raise ArgumentError, "#{key} schema not defined for testing" \
8
+ unless data.include?(key)
9
+ data[key]['kind'] = key
10
+ data[key]
11
+ end
12
+