instedd-pigeon 0.1.1

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.
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
+