taketo 0.0.1 → 0.0.2

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