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.
- data/.gitignore +25 -0
- data/.rvmrc +1 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +140 -0
- data/Rakefile +1 -0
- data/app/assets/images/pigeon/android_local_gateway_preview.png +0 -0
- data/app/assets/images/pigeon/android_local_gateway_qr.png +0 -0
- data/app/assets/images/pigeon/other_local_gateway_preview.png +0 -0
- data/app/assets/javascripts/pigeon/qst-server-wizard.js.coffee +58 -0
- data/app/assets/javascripts/pigeon/template.js.coffee +43 -0
- data/app/assets/javascripts/pigeon/twitter-template.js.coffee +38 -0
- data/app/assets/javascripts/pigeon/wizard.js.coffee +95 -0
- data/app/assets/javascripts/pigeon.js +2 -0
- data/app/assets/stylesheets/pigeon.css.sass +13 -0
- data/app/controllers/pigeon/twitter_controller.rb +44 -0
- data/app/helpers/.gitkeep +0 -0
- data/app/helpers/pigeon/channel_helper.rb +93 -0
- data/app/helpers/pigeon/renderer/base.rb +172 -0
- data/app/helpers/pigeon/renderer/channel_renderer.rb +58 -0
- data/app/helpers/pigeon/renderer.rb +8 -0
- data/app/helpers/pigeon/tag_helper.rb +26 -0
- data/app/helpers/pigeon/template_helper.rb +20 -0
- data/app/helpers/pigeon/text_helper.rb +16 -0
- data/app/models/.gitkeep +0 -0
- data/app/models/pigeon/channel.rb +220 -0
- data/app/models/pigeon/channel_attribute.rb +64 -0
- data/app/models/pigeon/channel_schema.rb +113 -0
- data/app/models/pigeon/nested_attribute.rb +23 -0
- data/app/models/pigeon/nested_scopes.rb +34 -0
- data/app/models/pigeon/nuntium_channel.rb +92 -0
- data/app/models/pigeon/verboice_channel.rb +82 -0
- data/app/views/pigeon/twitter/callback.html.erb +6 -0
- data/config/routes.rb +4 -0
- data/config/schemas/nuntium/nuntium.yml +210 -0
- data/config/schemas/nuntium/qst-server.yml +180 -0
- data/config/schemas/nuntium/twitter.yml +56 -0
- data/config/schemas/verboice/verboice.yml +76 -0
- data/lib/pigeon/engine.rb +30 -0
- data/lib/pigeon/errors.rb +28 -0
- data/lib/pigeon/initializer.rb +13 -0
- data/lib/pigeon/nuntium.rb +10 -0
- data/lib/pigeon/verboice.rb +10 -0
- data/lib/pigeon/version.rb +3 -0
- data/lib/pigeon.rb +25 -0
- data/pigeon.gemspec +24 -0
- data/spec/data/test_schemas.yml +21 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/helpers/pigeon/channel_helper_spec.rb +173 -0
- data/spec/helpers/pigeon/renderer/base_spec.rb +109 -0
- data/spec/helpers/pigeon/renderer/channel_renderer_spec.rb +61 -0
- data/spec/helpers/pigeon/tag_helper_spec.rb +36 -0
- data/spec/helpers/pigeon/template_helper_spec.rb +57 -0
- data/spec/models/pigeon/channel_attribute_spec.rb +98 -0
- data/spec/models/pigeon/channel_schema_spec.rb +63 -0
- data/spec/models/pigeon/channel_spec.rb +205 -0
- data/spec/models/pigeon/nuntium_channel_spec.rb +53 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/active_model_lint.rb +15 -0
- data/spec/support/test_schemas.rb +12 -0
- 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
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|