convoy 1.0.0

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 (109) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.irbrc +3 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +8 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +22 -0
  9. data/README.md +705 -0
  10. data/Rakefile +1 -0
  11. data/convoy.gemspec +24 -0
  12. data/examples/.my_apprc +24 -0
  13. data/examples/basic +10 -0
  14. data/examples/basic_config_file +16 -0
  15. data/examples/basic_conflicts +17 -0
  16. data/examples/basic_depends_on +25 -0
  17. data/examples/basic_flags +15 -0
  18. data/examples/basic_options +14 -0
  19. data/examples/basic_options_multi +15 -0
  20. data/examples/basic_require_arguments +17 -0
  21. data/examples/basic_texts +21 -0
  22. data/examples/basic_validations +21 -0
  23. data/examples/basic_with_everything +30 -0
  24. data/examples/commands/example_command.rb +13 -0
  25. data/examples/suite_complex +65 -0
  26. data/examples/suite_simple +19 -0
  27. data/examples/suite_with_sub_commands +94 -0
  28. data/lib/convoy.rb +83 -0
  29. data/lib/convoy/action_command/base.rb +85 -0
  30. data/lib/convoy/action_command/escort_utility_command.rb +53 -0
  31. data/lib/convoy/app.rb +127 -0
  32. data/lib/convoy/arguments.rb +20 -0
  33. data/lib/convoy/auto_options.rb +71 -0
  34. data/lib/convoy/error/error.rb +33 -0
  35. data/lib/convoy/formatter/command.rb +87 -0
  36. data/lib/convoy/formatter/commands.rb +37 -0
  37. data/lib/convoy/formatter/cursor_position.rb +29 -0
  38. data/lib/convoy/formatter/default_help_formatter.rb +117 -0
  39. data/lib/convoy/formatter/global_command.rb +17 -0
  40. data/lib/convoy/formatter/option.rb +152 -0
  41. data/lib/convoy/formatter/options.rb +28 -0
  42. data/lib/convoy/formatter/shell_command_executor.rb +49 -0
  43. data/lib/convoy/formatter/stream_output_formatter.rb +88 -0
  44. data/lib/convoy/formatter/string_grid.rb +108 -0
  45. data/lib/convoy/formatter/string_splitter.rb +50 -0
  46. data/lib/convoy/formatter/terminal.rb +30 -0
  47. data/lib/convoy/global_pre_parser.rb +43 -0
  48. data/lib/convoy/logger.rb +75 -0
  49. data/lib/convoy/option_dependency_validator.rb +82 -0
  50. data/lib/convoy/option_parser.rb +155 -0
  51. data/lib/convoy/setup/configuration/generator.rb +75 -0
  52. data/lib/convoy/setup/configuration/instance.rb +34 -0
  53. data/lib/convoy/setup/configuration/loader.rb +43 -0
  54. data/lib/convoy/setup/configuration/locator/base.rb +19 -0
  55. data/lib/convoy/setup/configuration/locator/chaining.rb +29 -0
  56. data/lib/convoy/setup/configuration/locator/descending_to_home.rb +23 -0
  57. data/lib/convoy/setup/configuration/locator/executing_script_directory.rb +15 -0
  58. data/lib/convoy/setup/configuration/locator/specified_directory.rb +21 -0
  59. data/lib/convoy/setup/configuration/merge_tool.rb +38 -0
  60. data/lib/convoy/setup/configuration/reader.rb +36 -0
  61. data/lib/convoy/setup/configuration/writer.rb +46 -0
  62. data/lib/convoy/setup/dsl/action.rb +17 -0
  63. data/lib/convoy/setup/dsl/command.rb +67 -0
  64. data/lib/convoy/setup/dsl/config_file.rb +13 -0
  65. data/lib/convoy/setup/dsl/global.rb +29 -0
  66. data/lib/convoy/setup/dsl/options.rb +81 -0
  67. data/lib/convoy/setup_accessor.rb +206 -0
  68. data/lib/convoy/trollop.rb +861 -0
  69. data/lib/convoy/utils.rb +21 -0
  70. data/lib/convoy/validator.rb +45 -0
  71. data/spec/integration/basic_config_file_spec.rb +126 -0
  72. data/spec/integration/basic_conflicts_spec.rb +47 -0
  73. data/spec/integration/basic_depends_on_spec.rb +275 -0
  74. data/spec/integration/basic_options_spec.rb +41 -0
  75. data/spec/integration/basic_options_with_multi_spec.rb +30 -0
  76. data/spec/integration/basic_spec.rb +38 -0
  77. data/spec/integration/basic_validations_spec.rb +77 -0
  78. data/spec/integration/basic_with_arguments_spec.rb +35 -0
  79. data/spec/integration/basic_with_text_fields_spec.rb +21 -0
  80. data/spec/integration/suite_simple_spec.rb +45 -0
  81. data/spec/integration/suite_sub_command_spec.rb +51 -0
  82. data/spec/lib/convoy/action_command/base_spec.rb +200 -0
  83. data/spec/lib/convoy/formatter/command_spec.rb +238 -0
  84. data/spec/lib/convoy/formatter/global_command_spec.rb +50 -0
  85. data/spec/lib/convoy/formatter/option_spec.rb +300 -0
  86. data/spec/lib/convoy/formatter/shell_command_executor_spec.rb +59 -0
  87. data/spec/lib/convoy/formatter/stream_output_formatter_spec.rb +214 -0
  88. data/spec/lib/convoy/formatter/string_grid_spec.rb +59 -0
  89. data/spec/lib/convoy/formatter/string_splitter_spec.rb +50 -0
  90. data/spec/lib/convoy/formatter/terminal_spec.rb +19 -0
  91. data/spec/lib/convoy/setup/configuration/generator_spec.rb +101 -0
  92. data/spec/lib/convoy/setup/configuration/loader_spec.rb +79 -0
  93. data/spec/lib/convoy/setup/configuration/locator/chaining_spec.rb +81 -0
  94. data/spec/lib/convoy/setup/configuration/locator/descending_to_home_spec.rb +57 -0
  95. data/spec/lib/convoy/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
  96. data/spec/lib/convoy/setup/configuration/locator/specified_directory_spec.rb +33 -0
  97. data/spec/lib/convoy/setup/configuration/merge_tool_spec.rb +41 -0
  98. data/spec/lib/convoy/setup/configuration/reader_spec.rb +41 -0
  99. data/spec/lib/convoy/setup/configuration/writer_spec.rb +75 -0
  100. data/spec/lib/convoy/setup_accessor_spec.rb +226 -0
  101. data/spec/lib/convoy/utils_spec.rb +30 -0
  102. data/spec/spec_helper.rb +29 -0
  103. data/spec/support/integration_helpers.rb +2 -0
  104. data/spec/support/matchers/execute_action_for_command_matcher.rb +21 -0
  105. data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
  106. data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
  107. data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
  108. data/spec/support/shared_contexts/integration_setup.rb +34 -0
  109. metadata +292 -0
@@ -0,0 +1,41 @@
1
+ describe "Convoy basic app with options defined", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
8
+ end
9
+
10
+ app.action do |options, arguments|
11
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "when called with empty option string" do
17
+ let(:option_string) { "" }
18
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
19
+ it("should execute the global action") { expect { subject }.to execute_action_for_command(result, :global) }
20
+ it("option1 have its default value in action") { expect { subject }.to execute_action_with_options(result, :option1 => 'option 1') }
21
+ end
22
+
23
+ context "when called with option string with short code option" do
24
+ let(:option_string) { "-o blah" }
25
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
26
+ it("should execute the global action") { expect { subject }.to execute_action_for_command(result, :global) }
27
+ it("option1 have the value 'blah' in action") { expect { subject }.to execute_action_with_options(result, :option1 => 'blah') }
28
+ end
29
+
30
+ context "when called with option string with long code option" do
31
+ let(:option_string) { "--option1=blah" }
32
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
33
+ it("should execute the global action") { expect { subject }.to execute_action_for_command(result, :global) }
34
+ it("option1 have the value 'blah' in action") { expect { subject }.to execute_action_with_options(result, :option1 => 'blah') }
35
+ end
36
+
37
+ context "when called with option string with unknown option" do
38
+ let(:option_string) { "-k" }
39
+ it("should not exit with code 0") { expect { subject }.not_to exit_with_code(0) }
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ describe "Convoy basic app with multi option", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :multi => true
8
+ end
9
+
10
+ app.action do |options, arguments|
11
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "when called with empty option string" do
17
+ let(:option_string) { "" }
18
+ it("option1 should be an empty array") { expect { subject }.to execute_action_with_options(result, :option1 => []) }
19
+ end
20
+
21
+ context "when called with option1 specified once" do
22
+ let(:option_string) { "-o blah" }
23
+ it("option1 have the value ['blah'] in action") { expect { subject }.to execute_action_with_options(result, :option1 => ['blah']) }
24
+ end
25
+
26
+ context "when called with option1 specified 3 times" do
27
+ let(:option_string) { "-o blah --option1=blah2 -o blah3" }
28
+ it("option1 have the value ['blah', 'blah2', 'blah3'] in action") { expect { subject }.to execute_action_with_options(result, :option1 => ['blah', 'blah2', 'blah3']) }
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+ describe "Convoy basic app with no options defined", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.action do |options, arguments|
7
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
8
+ end
9
+ end
10
+ end
11
+
12
+ context "when called with empty option string" do
13
+ let(:option_string) { "" }
14
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
15
+ it("should execute the global action") { expect { subject }.to execute_action_for_command(result, :global) }
16
+ end
17
+
18
+ context "when called with non-empty option string" do
19
+ let(:option_string) { "hello" }
20
+ it("exit code should be 0") { expect { subject }.to exit_with_code(0) }
21
+ it("should execute the global action") { expect { subject }.to execute_action_for_command(result, :global) }
22
+ end
23
+
24
+ context "gets --help option automatically" do
25
+ let(:option_string) { "--help" }
26
+ it("exit code should be 0") { expect { subject }.to exit_with_code(0) }
27
+ end
28
+
29
+ context "gets --verbosity option automatically" do
30
+ let(:option_string) { "--verbosity=DEBUG" }
31
+ it("exit code should be 0") { expect { subject }.to exit_with_code(0) }
32
+ end
33
+
34
+ context "gets --error-output-format option automatically" do
35
+ let(:option_string) { "--error-output-format=advanced" }
36
+ it("exit code should be 0") { expect { subject }.to exit_with_code(0) }
37
+ end
38
+ end
@@ -0,0 +1,77 @@
1
+ describe "Convoy basic app with validations", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ context "when validation exists for non-existant option" do
5
+ let(:app_configuration) do
6
+ lambda do |app|
7
+ app.options do |opts|
8
+ opts.opt :option1, "Option 1", :short => '-o', :long => '--option1', :type => :string
9
+ opts.validate(:option2, "must be either 'foo' or 'bar'") { |option| ["foo", "bar"].include?(option) }
10
+ end
11
+
12
+ app.action do |options, arguments|
13
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
14
+ end
15
+ end
16
+ end
17
+ let(:option_string) { "-o bar" }
18
+
19
+ it("should exit with code 2") { expect { subject }.to exit_with_code(2) }
20
+ end
21
+
22
+ context "when option has a validation" do
23
+ let(:app_configuration) do
24
+ lambda do |app|
25
+ app.options do |opts|
26
+ opts.opt :option1, "Option 1", :short => '-o', :long => '--option1', :type => :string
27
+ opts.validate(:option1, "must be either 'foo' or 'bar'") { |option| ["foo", "bar"].include?(option) }
28
+ end
29
+
30
+ app.action do |options, arguments|
31
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
32
+ end
33
+ end
34
+ end
35
+
36
+ context "and validation fails" do
37
+ let(:option_string) { "-o baz" }
38
+ it("should exit with code 3") { expect { subject }.to exit_with_code(3) }
39
+ end
40
+
41
+ context "and validation does not fail" do
42
+ let(:option_string) { "-o foo" }
43
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
44
+ end
45
+ end
46
+
47
+ context "when option has multiple validations" do
48
+ let(:app_configuration) do
49
+ lambda do |app|
50
+ app.options do |opts|
51
+ opts.opt :option2, "Option 2", :short => :none, :long => '--option2', :type => :string
52
+ opts.validate(:option2, "must be two words") { |option| option =~ /\w\s\w/ }
53
+ opts.validate(:option2, "must be at least 20 characters long") { |option| option.length >= 20 }
54
+ end
55
+
56
+ app.action do |options, arguments|
57
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
58
+ end
59
+ end
60
+ end
61
+
62
+ context "and one validation fails" do
63
+ let(:option_string) { "--option2='hb'" }
64
+ it("should exit with code 3") { expect { subject }.to exit_with_code(3) }
65
+ end
66
+
67
+ context "and the other validation fails" do
68
+ let(:option_string) { "--option2='h bssfs'" }
69
+ it("should exit with code 3") { expect { subject }.to exit_with_code(3) }
70
+ end
71
+
72
+ context "and both validations pass" do
73
+ let(:option_string) { "--option2='h bssfsfsdfsdfsfsdsf'" }
74
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,35 @@
1
+ require 'readline'
2
+
3
+ describe "Convoy basic app that requires arguments", :integration => true do
4
+ subject { Convoy::App.create(option_string, &app_configuration) }
5
+
6
+ let(:app_configuration) do
7
+ lambda do |app|
8
+ app.requires_arguments
9
+
10
+ app.action do |options, arguments|
11
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "when called with no arguments" do
17
+ let(:option_string) { "" }
18
+
19
+ before do
20
+ Readline.stub(:readline).and_return('1', nil)
21
+ end
22
+
23
+ it("action should receive ['1'] as arguments") { expect { subject }.to execute_action_with_arguments(result, ['1']) }
24
+ end
25
+
26
+ context "when called with one argument" do
27
+ let(:option_string) { "1" }
28
+ it("action should receive ['1'] as arguments") { expect { subject }.to execute_action_with_arguments(result, ['1']) }
29
+ end
30
+
31
+ context "when called with three arguments" do
32
+ let(:option_string) { "1 2 3" }
33
+ it("action should receive ['1', '2', '3'] as arguments") { expect { subject }.to execute_action_with_arguments(result, ['1', '2', '3']) }
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ describe "Convoy basic app with version, description, and summary", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.version "0.1.1"
7
+ app.summary "Sum1"
8
+ app.description "Desc1"
9
+
10
+ app.action do |options, arguments|
11
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "when called" do
17
+ let(:option_string) { "" }
18
+
19
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ describe "Convoy suite app with one level of commands", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
8
+ end
9
+
10
+ app.command :command1, :aliases => [:c1] do |command|
11
+ command.options do |opts|
12
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string
13
+ end
14
+
15
+ command.action do |options, arguments|
16
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
17
+ end
18
+ end
19
+
20
+ app.action do |options, arguments|
21
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
22
+ end
23
+ end
24
+ end
25
+
26
+ context "when calling command with option and global option" do
27
+ let(:option_string) { "-o hello command1 --option2 world" }
28
+
29
+ before do
30
+ begin
31
+ subject
32
+ rescue SystemExit => e
33
+ end
34
+ end
35
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
36
+ it("should have the right command name") { result[:command_name].should == :command1 }
37
+ it("should have have global option set") { result[:options][:global][:options][:option1].should == 'hello' }
38
+ it("should have have command option set") { result[:command_options][:option2].should == 'world' }
39
+ end
40
+
41
+ context "when using command alias" do
42
+ let(:option_string) { "-o hello c1 --option2 world" }
43
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ describe "Convoy suite app with sub commands", :integration => true do
2
+ subject { Convoy::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
8
+ end
9
+
10
+ app.command :command1, :aliases => [:c1] do |command|
11
+ command.options do |opts|
12
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string
13
+ end
14
+
15
+ command.command :sub_command1 do |command|
16
+ command.options do |opts|
17
+ opts.opt :option3, "Option3", :short => :none, :long => '--option3', :type => :string
18
+ end
19
+
20
+ command.action do |options, arguments|
21
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
22
+ end
23
+ end
24
+
25
+ command.action do |options, arguments|
26
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
27
+ end
28
+ end
29
+
30
+ app.action do |options, arguments|
31
+ Convoy::IntegrationTestCommand.new(options, arguments).execute(result)
32
+ end
33
+ end
34
+ end
35
+
36
+ context "when calling sub command with option and command option and global option" do
37
+ let(:option_string) { "-o hello command1 --option2=world sub_command1 --option3=foo" }
38
+
39
+ before do
40
+ begin
41
+ subject
42
+ rescue SystemExit => e
43
+ end
44
+ end
45
+ it("should exit with code 0") { expect { subject }.to exit_with_code(0) }
46
+ it("should have the right command name") { result[:command_name].should == :sub_command1 }
47
+ it("should have have sub command option set") { result[:command_options][:option3].should == 'foo' }
48
+ it("should have have global option set") { result[:options][:global][:options][:option1].should == 'hello' }
49
+ it("should have have command option set") { result[:options][:global][:commands][:command1][:options][:option2].should == 'world' }
50
+ end
51
+ end
@@ -0,0 +1,200 @@
1
+ describe Convoy::SetupAccessor do
2
+ let(:command) { Convoy::TestCommand.new(options, arguments, config) }
3
+ let(:options) { {} }
4
+ let(:arguments) { [] }
5
+ let(:config) { {} }
6
+
7
+ describe "#command_context" do
8
+ subject { command.send(:command_context) }
9
+
10
+ context "when command context already set" do
11
+ before do
12
+ command.instance_variable_set(:"@command_context", [:hello])
13
+ end
14
+
15
+ it { subject.should == [:hello] }
16
+ end
17
+
18
+ context "when command context not yet set" do
19
+ context "and options hash is empty" do
20
+ it { subject.should == [] }
21
+ end
22
+
23
+ context "and options hash is of valid structure" do
24
+ context "and command is global" do
25
+ let(:options) { {:global => {:commands => {}}} }
26
+ it { subject.should == [] }
27
+ end
28
+
29
+ context "and command is child of global" do
30
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}}} }
31
+ it { subject.should == [:command1] }
32
+
33
+ context "and no commands hash for sub command in options" do
34
+ let(:options) { {:global => {:commands => {:command1 => {}}}} }
35
+ it { subject.should == [:command1] }
36
+ end
37
+ end
38
+
39
+ context "and command is grandchild of global" do
40
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}}} }
41
+ it { subject.should == [:command1, :sub_command1] }
42
+ end
43
+
44
+ context "and command is great grandchild of global" do
45
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {:sub_sub_command1 => {:commands => {}}}}}}}}} }
46
+ it { subject.should == [:command1, :sub_command1, :sub_sub_command1] }
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#command_name" do
53
+ subject { command.send(:command_name) }
54
+
55
+ context "when context is global" do
56
+ let(:options) { {:global => {:commands => {}}} }
57
+ it { subject.should == :global }
58
+ end
59
+
60
+ context "when context is of size 1" do
61
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}}} }
62
+ it { subject.should == :command1 }
63
+ end
64
+
65
+ context "when context is of size 2" do
66
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}}} }
67
+ it { subject.should == :sub_command1 }
68
+ end
69
+ end
70
+
71
+ describe "#command_options" do
72
+ subject { command.send(:command_options) }
73
+
74
+ context "when context is global" do
75
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
76
+ it { subject.should == {:hello => :world} }
77
+ end
78
+
79
+ context "when context is of size 1" do
80
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}, :options => {:hello => :world}}}}} }
81
+ it { subject.should == {:hello => :world} }
82
+ end
83
+
84
+ context "when context is of size 2" do
85
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}, :options => {:hello => :world}}}}}}} }
86
+ it { subject.should == {:hello => :world} }
87
+ end
88
+ end
89
+
90
+ describe "#global_options" do
91
+ subject { command.send(:global_options) }
92
+
93
+ context "when context is global" do
94
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
95
+ it { subject.should == {:hello => :world} }
96
+ end
97
+
98
+ context "when context is of size 1" do
99
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
100
+ it { subject.should == {:hello => :world} }
101
+ end
102
+ end
103
+
104
+ describe "#parent_options" do
105
+ subject { command.send(:parent_options) }
106
+
107
+ context "when context is global" do
108
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
109
+ it { subject.should == {} }
110
+ end
111
+
112
+ context "when context is of size 1" do
113
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
114
+ it { subject.should == {:hello => :world} }
115
+ end
116
+
117
+ context "when context is of size 2" do
118
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}, :options => {:hello => :world}}}}} }
119
+ it { subject.should == {:hello => :world} }
120
+ end
121
+ end
122
+
123
+ describe "#grandparent_options" do
124
+ subject { command.send(:grandparent_options) }
125
+
126
+ context "when context is global" do
127
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
128
+ it { subject.should == {} }
129
+ end
130
+
131
+ context "when context is of size 1" do
132
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
133
+ it { subject.should == {} }
134
+ end
135
+
136
+ context "when context is of size 2" do
137
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}, :options => {:hello => :world}}} }
138
+ it { subject.should == {:hello => :world} }
139
+ end
140
+ end
141
+
142
+ describe "#ancestor_options" do
143
+ subject { command.send(:ancestor_options, generation_number) }
144
+
145
+ context "when context is global" do
146
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
147
+
148
+ context "and generation number is 0" do
149
+ let(:generation_number) { 0 }
150
+ it { subject.should == {:hello => :world} }
151
+ end
152
+
153
+ context "and generation number is 1" do
154
+ let(:generation_number) { 1 }
155
+ it { subject.should == {} }
156
+ end
157
+
158
+ context "and generation number is 2" do
159
+ let(:generation_number) { 2 }
160
+ it { subject.should == {} }
161
+ end
162
+
163
+ context "and generation number is 3" do
164
+ let(:generation_number) { 3 }
165
+ it { subject.should == {} }
166
+ end
167
+ end
168
+
169
+ context "when context is of size 1" do
170
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}, :options => {:foo => :bar}}}, :options => {:hello => :world}}} }
171
+
172
+ context "and generation number is 0" do
173
+ let(:generation_number) { 0 }
174
+ it { subject.should == {:foo => :bar} }
175
+ end
176
+
177
+ context "and generation number is 1" do
178
+ let(:generation_number) { 1 }
179
+ it { subject.should == {:hello => :world} }
180
+ end
181
+
182
+ context "and generation number is 2" do
183
+ let(:generation_number) { 2 }
184
+ it { subject.should == {} }
185
+ end
186
+
187
+ context "and generation number is 3" do
188
+ let(:generation_number) { 3 }
189
+ it { subject.should == {} }
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ module Convoy
196
+ class TestCommand < ::Convoy::ActionCommand::Base
197
+ def execute
198
+ end
199
+ end
200
+ end