taketo 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Gemfile +4 -4
  2. data/Gemfile.lock +11 -11
  3. data/LICENSE.txt +1 -1
  4. data/README.md +12 -4
  5. data/Rakefile +3 -6
  6. data/VERSION +1 -1
  7. data/bin/taketo +48 -27
  8. data/features/commands.feature +45 -0
  9. data/features/config_validation.feature +18 -0
  10. data/features/connect_to_server.feature +43 -1
  11. data/lib/taketo/commands/ssh_command.rb +6 -14
  12. data/lib/taketo/config_validator.rb +43 -0
  13. data/lib/taketo/constructs/command.rb +32 -0
  14. data/lib/taketo/constructs/config.rb +4 -2
  15. data/lib/taketo/constructs/environment.rb +5 -3
  16. data/lib/taketo/constructs/project.rb +4 -2
  17. data/lib/taketo/constructs/server.rb +28 -1
  18. data/lib/taketo/constructs_factory.rb +9 -0
  19. data/lib/taketo/dsl.rb +24 -24
  20. data/lib/taketo/support/key_error.rb +4 -0
  21. data/lib/taketo/support/named_nodes_collection.rb +26 -0
  22. data/lib/taketo/support.rb +2 -0
  23. data/lib/taketo/taketo_argv_parser.rb +48 -0
  24. data/lib/taketo.rb +2 -1
  25. data/spec/lib/{commands → taketo/commands}/ssh_command_spec.rb +8 -14
  26. data/spec/lib/taketo/config_validator_spec.rb +41 -0
  27. data/spec/lib/taketo/constructs/command_spec.rb +22 -0
  28. data/spec/lib/{constructs → taketo/constructs}/config_spec.rb +2 -2
  29. data/spec/lib/{constructs → taketo/constructs}/environment_spec.rb +2 -2
  30. data/spec/lib/{constructs → taketo/constructs}/project_spec.rb +2 -2
  31. data/spec/lib/taketo/constructs/server_spec.rb +84 -0
  32. data/spec/lib/{constructs_factory_spec.rb → taketo/constructs_factory_spec.rb} +14 -1
  33. data/spec/lib/{dsl_spec.rb → taketo/dsl_spec.rb} +45 -7
  34. data/spec/lib/{support → taketo/support}/eval_delegator_spec.rb +1 -1
  35. data/spec/lib/taketo/support/named_nodes_collection_spec.rb +29 -0
  36. data/spec/lib/taketo/taketo_argv_parser_spec.rb +92 -0
  37. data/spec/spec_helper.rb +8 -4
  38. data/spec/support/helpers/dsl_spec_helper.rb +11 -2
  39. metadata +25 -14
  40. data/spec/lib/constructs/server_spec.rb +0 -41
data/lib/taketo/dsl.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'taketo/support'
1
+ require 'taketo/constructs_factory'
2
2
 
3
3
  module Taketo
4
4
  class DSL
5
5
  class ScopeError < StandardError; end
6
-
6
+
7
7
  class << self
8
8
  def define_scope(scope, parent_scope)
9
9
  define_method scope do |name, &block|
@@ -11,7 +11,7 @@ module Taketo
11
11
  raise ScopeError,
12
12
  "#{scope} can't be defined in #{current_scope} scope"
13
13
  end
14
- scope_object = @factory.send("create_#{scope}", name)
14
+ scope_object = @factory.create(scope, name)
15
15
  in_scope(scope, scope_object) do
16
16
  block.call
17
17
  end
@@ -20,7 +20,7 @@ module Taketo
20
20
 
21
21
  def define_attribute(name, parent_scope, &block)
22
22
  define_method name do |attribute|
23
- unless server_scope?
23
+ unless current_scope?(parent_scope)
24
24
  raise ScopeError,
25
25
  "#{name} can't be defined in #{current_scope} scope"
26
26
  end
@@ -31,36 +31,36 @@ module Taketo
31
31
 
32
32
  attr_reader :current_scope_object, :config
33
33
 
34
- def initialize(factory)
34
+ def initialize(factory = Taketo::ConstructsFactory.new)
35
35
  @factory = factory
36
36
  @scope = [:config]
37
37
  @config = @current_scope_object = factory.create_config
38
38
  end
39
39
 
40
- def configure(&block)
41
- instance_eval(&block)
40
+ def configure(filename = nil, &block)
41
+ if filename
42
+ filename = filename.to_s
43
+ config_text = File.read(filename)
44
+ instance_eval config_text, filename, 1
45
+ elsif block
46
+ instance_eval(&block)
47
+ else
48
+ raise ArgumentError, "Either filename or block should be provided"
49
+ end
42
50
  @config
43
51
  end
44
52
 
45
53
  define_scope :project, :config
46
54
  define_scope :environment, :project
47
55
  define_scope :server, :environment
56
+ define_scope :command, :server
48
57
 
49
- define_attribute :host, :server do |hostname|
50
- current_scope_object.host = hostname
51
- end
52
-
53
- define_attribute :port, :server do |port_number|
54
- current_scope_object.port = port_number
55
- end
56
-
57
- define_attribute :user, :server do |username|
58
- current_scope_object.username = username
59
- end
60
-
61
- define_attribute :location, :server do |path|
62
- current_scope_object.default_location = path
63
- end
58
+ define_attribute(:host, :server) { |hostname| current_scope_object.host = hostname }
59
+ define_attribute(:port, :server) { |port_number| current_scope_object.port = port_number }
60
+ define_attribute(:user, :server) { |username| current_scope_object.username = username }
61
+ define_attribute(:location, :server) { |path| current_scope_object.default_location = path }
62
+ define_attribute(:env, :server) { |env| current_scope_object.env(env) }
63
+ define_attribute(:execute, :command) { |command| current_scope_object.command = command }
64
64
 
65
65
  private
66
66
 
@@ -72,7 +72,7 @@ module Taketo
72
72
  current_scope == scope
73
73
  end
74
74
 
75
- [:config, :project, :environment, :server].each do |scope|
75
+ [:config, :project, :environment, :server, :command].each do |scope|
76
76
  define_method("#{scope}_scope?") { current_scope == scope }
77
77
  end
78
78
 
@@ -80,7 +80,7 @@ module Taketo
80
80
  parent_scope_object, @current_scope_object = @current_scope_object, new_scope_object
81
81
  @scope << scope
82
82
  yield
83
- parent_scope_object.send("append_#{scope}", current_scope_object)
83
+ parent_scope_object.send("append_#{scope}", current_scope_object)
84
84
  @scope.pop
85
85
  @current_scope_object = parent_scope_object
86
86
  end
@@ -0,0 +1,4 @@
1
+ unless defined? KeyError
2
+ class KeyError < StandardError; end
3
+ end
4
+
@@ -0,0 +1,26 @@
1
+ require 'forwardable'
2
+ require 'taketo/support'
3
+
4
+ module Taketo
5
+ module Support
6
+ class NamedNodesCollection
7
+ include Enumerable
8
+ extend Forwardable
9
+
10
+ def_delegators :@nodes, :each, :<<, :push, :length, :size, :empty?
11
+
12
+ def initialize(nodes = [])
13
+ @nodes = nodes
14
+ end
15
+
16
+ def [](index)
17
+ if index.is_a?(Symbol)
18
+ node = @nodes.detect { |n| n.name == index } or raise KeyError, "Element with name #{index} not found"
19
+ return node
20
+ end
21
+ @nodes[index] or raise KeyError, "Element ##{index} not found"
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -4,4 +4,6 @@ module Taketo
4
4
  end
5
5
 
6
6
  require 'taketo/support/eval_delegator'
7
+ require 'taketo/support/named_nodes_collection'
8
+ require 'taketo/support/key_error'
7
9
 
@@ -0,0 +1,48 @@
1
+ module Taketo
2
+ class ConfigError < StandardError; end
3
+
4
+ class TaketoArgvParser
5
+ def initialize(config, argv)
6
+ @config = config
7
+ @argv = argv
8
+ end
9
+
10
+ def parse
11
+ if all_specified?
12
+ project_name, environment_name, server_name = @argv.shift(3).map(&:to_sym)
13
+
14
+ begin
15
+ return @config.projects[project_name].environments[environment_name].servers[server_name]
16
+ rescue KeyError
17
+ raise ArgumentError,
18
+ "Server #{server_name} in environment #{environment_name} for project #{project_name} does not exist"
19
+ end
20
+ end
21
+
22
+ if @config.projects.one?
23
+ project = @config.projects.first
24
+ if project.environments.one?
25
+ environment = project.environments.first
26
+ if environment.servers.one?
27
+ return environment.servers.first
28
+ elsif environment.servers.length > 1
29
+ if server_name = @argv.shift
30
+ return environment.servers[server_name.to_sym]
31
+ else
32
+ raise ArgumentError, "There are multiple servers for project #{project.name} " \
33
+ "in environment #{environment.name}: #{environment.servers.map(&:name).join(", ")}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def all_specified?
43
+ @argv.size >= 3
44
+ end
45
+
46
+ end
47
+ end
48
+
data/lib/taketo.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  module Taketo
2
2
  version_file = File.expand_path('../VERSION', File.dirname(__FILE__))
3
- VERSION = File.read(version_file).freeze
3
+ VERSION = File.read(version_file).freeze unless defined? VERSION
4
4
  end
5
5
 
6
6
  require 'taketo/support'
7
7
  require 'taketo/dsl'
8
8
  require 'taketo/commands'
9
+ require 'taketo/config_validator'
9
10
 
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
2
  require 'taketo/commands/ssh_command'
3
3
 
4
4
  include Taketo::Commands
@@ -11,33 +11,27 @@ describe "SSH Command" do
11
11
  :port => 22,
12
12
  :username => "deployer",
13
13
  :default_location => "/var/app",
14
- :environment => environment)
14
+ :environment => environment,
15
+ :environment_variables => {})
15
16
  end
17
+ let(:command) { mock(:Command, :render => "the_command") }
16
18
 
17
19
  let(:ssh_command) { SSHCommand.new(server) }
18
20
 
19
21
  it "should compose command based on provided server object" do
20
- ssh_command.render("bash").should == %q[ssh -t -p 22 "deployer"@"1.2.3.4" "cd '/var/app'; RAILS_ENV=staging bash"]
22
+ command.should_receive(:render).with(server).and_return("foobar")
23
+ ssh_command.render(command).should == %q[ssh -t -p 22 deployer@1.2.3.4 "foobar"]
21
24
  end
22
25
 
23
26
  it "should ignore absent parts" do
24
27
  server.stub(:port => nil)
25
28
  server.stub(:username => nil)
26
- ssh_command.render("bash").should == %q[ssh -t "1.2.3.4" "cd '/var/app'; RAILS_ENV=staging bash"]
27
-
28
- server.stub(:default_location => nil)
29
- ssh_command.render("bash").should == %q[ssh -t "1.2.3.4" "RAILS_ENV=staging bash"]
29
+ ssh_command.render(command).should == %q[ssh -t 1.2.3.4 "the_command"]
30
30
  end
31
31
 
32
32
  it "should require host" do
33
33
  server.stub(:host => nil)
34
- expect do
35
- ssh_command.render("bash")
36
- end.to raise_error ArgumentError, /host/
37
- end
38
-
39
- it "should have 'bash' as command default" do
40
- ssh_command.render.should =~ /bash/
34
+ expect { ssh_command.render("bash") }.to raise_error ArgumentError, /host/
41
35
  end
42
36
  end
43
37
 
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require 'taketo/config_validator'
3
+
4
+ include Taketo
5
+
6
+ describe "ConfigValidator" do
7
+ it "should require at least one project" do
8
+ config = stub(:projects => [])
9
+ expect { validator(config).validate! }.to raise_error ConfigError, /projects/i
10
+ end
11
+
12
+ it "should require every project to have at least one environment" do
13
+ project_1 = stub(:Project, :name => :project_1, :environments => [])
14
+ project_2 = stub(:Project, :name => :project_2, :environments => [stub])
15
+
16
+ config = stub(:projects => [project_1, project_2])
17
+ expect { validator(config).validate! }.to raise_error ConfigError, /project_1/i
18
+
19
+ project_1.stub(:environments => { :e => stub })
20
+ expect { validator(config).validate! }.not_to raise_error ConfigError, /project_1/i
21
+ end
22
+
23
+ it "should require every environment to have at least one server" do
24
+ environment_1 = stub(:Environment, :name => :environment_1, :servers => [])
25
+ environment_2 = stub(:Environment, :name => :environment_2, :servers => [stub])
26
+ project_1 = stub(:Project, :name => :project_1, :environments => [environment_1])
27
+ project_2 = stub(:Project, :name => :project_2, :environments => [environment_2])
28
+
29
+ config = stub(:projects => [project_1, project_2])
30
+ expect { validator(config).validate! }.to raise_error ConfigError, /environment_1/i
31
+
32
+ environment_2.stub(:servers => [stub])
33
+ expect { validator(config).validate! }.not_to raise_error ConfigError, /environment_2/i
34
+ end
35
+
36
+ def validator(config)
37
+ Taketo::ConfigValidator.new(config)
38
+ end
39
+ end
40
+
41
+
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
+ require 'taketo/constructs/command'
3
+
4
+ include Taketo
5
+
6
+ describe "Command" do
7
+ let(:cmd) { Taketo::Constructs::Command.new(:the_command) }
8
+
9
+ specify "#command= should set which command to execute" do
10
+ cmd.command= "rails c"
11
+ cmd.command.should == "rails c"
12
+ end
13
+
14
+ describe "#render" do
15
+ it "should pick up server's environment variables and location" do
16
+ server = mock(:Server, :environment_variables => { :FOO => "bar baz" }, :default_location => "/var/apps/the app")
17
+ cmd.command = "rails c"
18
+ cmd.render(server).should == "cd /var/apps/the\\ app; FOO=bar\\ baz rails c"
19
+ end
20
+ end
21
+ end
22
+
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
2
  require 'taketo/constructs/config'
3
3
 
4
4
  include Taketo
@@ -10,7 +10,7 @@ describe "Config" do
10
10
  it "should add project to config's projects collection" do
11
11
  project = stub(:name => :foo)
12
12
  config.append_project(project)
13
- config.projects[:foo].should == project
13
+ config.projects.should include(project)
14
14
  end
15
15
  end
16
16
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
2
  require 'taketo/constructs/environment'
3
3
 
4
4
  include Taketo
@@ -15,7 +15,7 @@ describe "Environment" do
15
15
 
16
16
  it "should add a server to environment's servers collection" do
17
17
  environment.append_server(server)
18
- environment.servers[:foo].should == server
18
+ environment.servers.should include(server)
19
19
  end
20
20
 
21
21
  it "should set environment attribute on a server to self" do
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
2
  require 'taketo/constructs/project'
3
3
 
4
4
  include Taketo
@@ -14,7 +14,7 @@ describe "Project" do
14
14
  it "should add an environment to project's environments collection" do
15
15
  environment = stub(:name => :foo)
16
16
  project.append_environment(environment)
17
- project.environments[:foo].should == environment
17
+ project.environments.should include(environment)
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,84 @@
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
+ require 'taketo/constructs/server'
3
+
4
+ include Taketo
5
+
6
+ describe "Server" do
7
+ let(:environment) { environment = stub(:Environment, :name => :the_environment) }
8
+ let(:server) { Taketo::Constructs::Server.new(:foo) }
9
+
10
+ it "should have name" do
11
+ server.name.should == :foo
12
+ end
13
+
14
+ it "should set host" do
15
+ server.host = "foo"
16
+ server.host.should == "foo"
17
+ end
18
+
19
+ it "should set port" do
20
+ server.port = "foo"
21
+ server.port.should == "foo"
22
+ end
23
+
24
+ it "should set username" do
25
+ server.username = "foo"
26
+ server.username.should == "foo"
27
+ end
28
+
29
+ it "should set default_location" do
30
+ server.default_location = "foo"
31
+ server.default_location.should == "foo"
32
+ end
33
+
34
+ describe "#environment=" do
35
+ it "should set environment" do
36
+ server.environment = environment
37
+ server.environment.should == environment
38
+ end
39
+
40
+ it "should set RAILS_ENV environment variable" do
41
+ server.environment_variables.should == {}
42
+ server.environment = environment
43
+ server.environment_variables[:RAILS_ENV].should == environment.name.to_s
44
+ end
45
+ end
46
+
47
+ it "should set environment variables" do
48
+ server.env :FOO => "bar"
49
+ server.env :BAR => "baz"
50
+ server.environment_variables.should include(:FOO => "bar", :BAR => "baz")
51
+ end
52
+
53
+ context "Commands" do
54
+ let(:command) { mock(:Command, :name => :foo).as_null_object }
55
+
56
+ describe "#append_command" do
57
+ it "should add a command to servers's commands collection" do
58
+ server.append_command(command)
59
+ server.commands.should include(command)
60
+ end
61
+ end
62
+
63
+ describe "#command_by_name" do
64
+ context "if there is such command" do
65
+ it "should return command object with corresponding name" do
66
+ server.append_command(command)
67
+ server.command_by_name(:foo).should == command
68
+ end
69
+ end
70
+
71
+ context "if there is no such command" do
72
+ it "should yield if block given" do
73
+ expect { |b| server.command_by_name(:bar, &b) }.to yield_control
74
+ end
75
+
76
+ it "should raise CommandNotFoundError if no block given" do
77
+ expect { server.command_by_name(:bar) }.to raise_error(Taketo::Constructs::Server::CommandNotFoundError)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
2
  require 'taketo/constructs_factory'
3
3
 
4
4
  include Taketo
@@ -6,6 +6,14 @@ include Taketo
6
6
  describe "ConstructsFactory" do
7
7
  let(:factory) { Taketo::ConstructsFactory.new }
8
8
 
9
+ specify "#create should delegate to appripriate method according to type" do
10
+ factory.should_receive(:create_config)
11
+ factory.create(:config)
12
+
13
+ factory.should_receive(:create_project).with(:foo)
14
+ factory.create(:project, :foo)
15
+ end
16
+
9
17
  specify "#create_config should create a config object" do
10
18
  factory.create_config.should be_an_instance_of(Taketo::Constructs::Config)
11
19
  end
@@ -24,5 +32,10 @@ describe "ConstructsFactory" do
24
32
  server = factory.create_server(:foo)
25
33
  server.should be_an_instance_of(Taketo::Constructs::Server)
26
34
  end
35
+
36
+ specify "#create_command should create a command object" do
37
+ command = factory.create_command(:foo)
38
+ command.should be_an_instance_of(Taketo::Constructs::Command)
39
+ end
27
40
  end
28
41
 
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
2
  require 'support/helpers/dsl_spec_helper'
3
3
  require 'taketo/dsl'
4
4
 
@@ -19,8 +19,8 @@ describe "DSL" do
19
19
  end
20
20
 
21
21
  it "should create a #{scope_name} and set it as current scope object" do
22
- factory.should_receive("create_#{scope_name}").with(:bar)
23
- dsl(parent_scope, factory.send("create_#{parent_scope_name}")) do |c|
22
+ dsl(parent_scope, factory.create(parent_scope_name)) do |c|
23
+ factory.should_receive(:create).with(scope_name, :bar)
24
24
  c.send(scope_name, :bar) do
25
25
  c.current_scope_object.should == factory.send(scope_name)
26
26
  end
@@ -28,14 +28,14 @@ describe "DSL" do
28
28
  end
29
29
 
30
30
  it "should not leak #{scope_name} as current scope object" do
31
- dsl(parent_scope, factory.send("create_#{parent_scope_name}")) do |c|
31
+ dsl(parent_scope, factory.create(parent_scope_name)) do |c|
32
32
  c.send(scope_name, :bar) {}
33
33
  c.current_scope_object.should_not == factory.send(scope_name)
34
34
  end
35
35
  end
36
36
 
37
37
  it "should add a #{scope_name} to the #{parent_scope_name}'s #{scope_name}s collection" do
38
- dsl(parent_scope, factory.send("create_#{parent_scope_name}")) do |c|
38
+ dsl(parent_scope, factory.create(parent_scope_name)) do |c|
39
39
  c.current_scope_object.should_receive("append_#{scope_name}").with(factory.send("create_#{scope_name}", :bar))
40
40
  c.send(scope_name, :bar) {}
41
41
  end
@@ -51,8 +51,8 @@ describe "DSL" do
51
51
  it { should_not be_appropriate_construct(attribute_name, example_value).under(inaproppriate_scope) }
52
52
  end
53
53
 
54
- it "should set #{parent_scope_method.to_s.gsub('=', '')} attribute on current server" do
55
- dsl(parent_scope, factory.send("create_#{parent_scope_name}", :foo)) do |c|
54
+ it "should call #{parent_scope_method} on current #{parent_scope_name}" do
55
+ dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c|
56
56
  factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value)
57
57
  c.send(attribute_name, example_value)
58
58
  end
@@ -83,6 +83,18 @@ describe "DSL" do
83
83
  describe "#location" do
84
84
  it_behaves_like "an attribute", :location, :server, :default_location=, "/var/app/"
85
85
  end
86
+
87
+ describe "#env" do
88
+ it_behaves_like "an attribute", :env, :server, :env, { :FOO => "bar" }
89
+ end
90
+
91
+ describe "#command" do
92
+ it_behaves_like "a scope", :command, :server
93
+
94
+ describe "#execute" do
95
+ it_behaves_like "an attribute", :execute, :command, :command=, "rails c"
96
+ end
97
+ end
86
98
  end
87
99
  end
88
100
  end
@@ -104,5 +116,31 @@ describe "DSL" do
104
116
  end
105
117
  end
106
118
  end
119
+
120
+ describe "#configure" do
121
+ it "should read config from file if filename passed" do
122
+ File.stub(:read => "the config")
123
+ dsl = Taketo::DSL.new(factory)
124
+ dsl.should_receive(:instance_eval) do |config, *args|
125
+ config.should == "the config"
126
+ end
127
+ dsl.configure("path/to/config")
128
+ end
129
+
130
+ it "should be configured from block unless filename specified" do
131
+ dsl = Taketo::DSL.new(factory)
132
+ config = proc { }
133
+ dsl.should_receive(:instance_eval).with(&config)
134
+ dsl.configure &config
135
+ end
136
+
137
+ it "should raise an error if neither config filename nor block passed" do
138
+ expect do
139
+ Taketo::DSL.new(factory).configure
140
+ end.to raise_error ArgumentError, /(config|block)/
141
+ end
142
+
143
+ it "should raise meaningful error if config parse failed"
144
+ end
107
145
  end
108
146
 
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
2
  require 'taketo/support/eval_delegator'
3
3
 
4
4
  class EvalDelegatorContext
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
+ require 'taketo/support/named_nodes_collection'
3
+
4
+ describe "NamedNodesCollection" do
5
+ let(:collection) { Taketo::Support::NamedNodesCollection.new }
6
+ let(:node1) { stub(:name => :foo) }
7
+ let(:node2) { stub(:name => :bar) }
8
+
9
+ it "should be able to initialize with array" do
10
+ Taketo::Support::NamedNodesCollection.new([1, 2, 3]).length.should == 3
11
+ end
12
+
13
+ it "should mimic Array" do
14
+ collection.should be_empty
15
+ collection << node1
16
+ collection.push node2
17
+ collection[0].should == node1
18
+ collection.map(&:name).should == [:foo, :bar]
19
+ collection.length.should == 2
20
+ collection.size.should == 2
21
+ end
22
+
23
+ it "should raise error if element not found" do
24
+ expect { collection[3] }.to raise_error KeyError, /#3/i
25
+ expect { collection[:quux] }.to raise_error KeyError, /name/i
26
+ end
27
+ end
28
+
29
+