git_workflow 0.0.5

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 (74) hide show
  1. data/README.markdown +77 -0
  2. data/Rakefile +33 -0
  3. data/bin/git-finish +4 -0
  4. data/bin/git-start +4 -0
  5. data/bin/git-workflow-setup +4 -0
  6. data/features/core_functionality/4049578_need_the_ability_to_start_a_new_branch.feature +15 -0
  7. data/features/core_functionality/4049611_need_the_ability_to_finish_a_specified_branch.feature +17 -0
  8. data/features/core_functionality/4056359_start_with_local_branch_already_present.feature +16 -0
  9. data/features/core_functionality/4056363_finish_the_current_branch.feature +17 -0
  10. data/features/core_functionality/4056389_changes_to_pt_story_name_cause_branch_issues.feature +25 -0
  11. data/features/core_functionality/4135658_control_output_verbosity_using_v_switch.feature +32 -0
  12. data/features/core_functionality/4468313_get_config_value_for_is_producing_an_error_log.feature +43 -0
  13. data/features/extensions/4058326_display_story_description_on_start.feature +14 -0
  14. data/features/git_branching/4135501_allow_branch_start_point_to_be_specified_from_command_line.feature +27 -0
  15. data/features/hooks/4069174_investigate_the_effort_required_to_add_pre_amp_post_hooks.feature +24 -0
  16. data/features/hooks/4199841_need_hooks_for_my_workflow.feature +51 -0
  17. data/features/hooks/4199845_need_hooks_for_sanger_workflow.feature +66 -0
  18. data/features/hooks/4205913_output_from_rake_tests_should_be_seen.feature +19 -0
  19. data/features/hooks/4424828_git_start_is_missing_pt_integration_for_my_hooks.feature +15 -0
  20. data/features/pivotal_tracker_api/4133291_chores_go_straight_to_accepted_not_to_finished.feature +15 -0
  21. data/features/release/4132264_fix_the_libxml_warnings_from_nokogiri.feature +20 -0
  22. data/features/step_definitions/aruba_extensions.rb +4 -0
  23. data/features/step_definitions/configuration_steps.rb +38 -0
  24. data/features/step_definitions/git_steps.rb +102 -0
  25. data/features/step_definitions/misc_steps.rb +3 -0
  26. data/features/step_definitions/pivotal_tracker_steps.rb +43 -0
  27. data/features/step_definitions/project_code_steps.rb +35 -0
  28. data/features/support/aruba.rb +1 -0
  29. data/features/support/hooks/configuration.rb +4 -0
  30. data/features/support/hooks/environment.rb +49 -0
  31. data/features/support/hooks/pivotal_tracker.rb +170 -0
  32. data/lib/git_workflow.rb +5 -0
  33. data/lib/git_workflow/callbacks.rb +16 -0
  34. data/lib/git_workflow/callbacks/pivotal_tracker_support.rb +64 -0
  35. data/lib/git_workflow/callbacks/remote_git_branch_support.rb +9 -0
  36. data/lib/git_workflow/callbacks/styles/debug.rb +58 -0
  37. data/lib/git_workflow/callbacks/styles/default.rb +43 -0
  38. data/lib/git_workflow/callbacks/styles/mine.rb +52 -0
  39. data/lib/git_workflow/callbacks/styles/sanger.rb +48 -0
  40. data/lib/git_workflow/callbacks/test_code_support.rb +29 -0
  41. data/lib/git_workflow/command_line.rb +46 -0
  42. data/lib/git_workflow/commands.rb +4 -0
  43. data/lib/git_workflow/commands/base.rb +31 -0
  44. data/lib/git_workflow/commands/finish.rb +36 -0
  45. data/lib/git_workflow/commands/setup.rb +157 -0
  46. data/lib/git_workflow/commands/start.rb +30 -0
  47. data/lib/git_workflow/configuration.rb +93 -0
  48. data/lib/git_workflow/core_ext.rb +106 -0
  49. data/lib/git_workflow/git.rb +143 -0
  50. data/lib/git_workflow/logger.yaml +27 -0
  51. data/lib/git_workflow/logging.rb +77 -0
  52. data/lib/git_workflow/story.rb +96 -0
  53. data/spec/core_functionality/4056539_support_http_proxy_spec.rb +68 -0
  54. data/spec/core_functionality/4058365_bad_request_on_story_update_spec.rb +13 -0
  55. data/spec/core_functionality/4058394_make_commands_more_verbose_spec.rb +41 -0
  56. data/spec/core_functionality/4058719_error_if_none_of_the_required_configuration_values_are_set_spec.rb +21 -0
  57. data/spec/core_functionality/4058861_git_config_returns_empty_strings_which_should_be_nil_spec.rb +59 -0
  58. data/spec/core_functionality/4172431_add_git_workflow_setup_command_to_make_setup_easier_spec.rb +148 -0
  59. data/spec/core_functionality/4199841_need_callbacks_for_my_workflow_spec.rb +97 -0
  60. data/spec/extensions/4199841_need_callbacks_for_my_workflow_spec.rb +167 -0
  61. data/spec/extensions/4205913_output_from_rake_tests_should_be_seen_spec.rb +34 -0
  62. data/spec/git_branching/4058723_branches_end_in_if_the_last_character_is_invalid_spec.rb +40 -0
  63. data/spec/git_branching/4059824_code_is_not_using_workflow_localbranchconvention_to_decode_branch_names_on_finish_spec.rb +115 -0
  64. data/spec/git_branching/4216087_support_pushing_branches_spec.rb +44 -0
  65. data/spec/hooks/4199845_need_hooks_for_sanger_workflow_spec.rb +27 -0
  66. data/spec/pivotal_tracker_api/4056381_pt_api_token_not_being_passed_in_headers_spec.rb +40 -0
  67. data/spec/pivotal_tracker_api/4056638_library_code_using_localhost_spec.rb +16 -0
  68. data/spec/pivotal_tracker_api/4056661_content_type_header_should_be_text_xml_on_updates_spec.rb +16 -0
  69. data/spec/pivotal_tracker_api/4058718_if_pt_username_is_not_set_use_user_name_spec.rb +26 -0
  70. data/spec/pivotal_tracker_api/4146016_decode_the_xml_encoded_text_of_description_and_name_spec.rb +63 -0
  71. data/spec/shared_examples/configuration.rb +10 -0
  72. data/spec/shared_examples/story.rb +17 -0
  73. data/spec/spec_helper.rb +18 -0
  74. metadata +220 -0
@@ -0,0 +1,27 @@
1
+ log4r_config:
2
+ # Here we define all of the loggers that are going to be used across all of the
3
+ # possible configurations.
4
+ loggers:
5
+ - name: Console
6
+ level: DEBUG
7
+ outputters:
8
+ - normal_information
9
+ - verbose_information
10
+
11
+ # And here are the outputters and with their associated formatters.
12
+ outputters:
13
+ - name: normal_information
14
+ type: StdoutOutputter
15
+ only_at:
16
+ - INFO
17
+ - FATAL
18
+ formatter:
19
+ type: PatternFormatter
20
+ pattern: '%l: %m'
21
+
22
+ - name: verbose_information
23
+ type: StderrOutputter
24
+ level: FATAL
25
+ formatter:
26
+ type: PatternFormatter
27
+ pattern: '%l: %m'
@@ -0,0 +1,77 @@
1
+ require 'log4r'
2
+ require 'log4r/yamlconfigurator'
3
+
4
+ module Log4r
5
+ class Outputter
6
+ def initialize_with_multiple_levels(name, hash = {})
7
+ initialize_without_multiple_levels(name, hash)
8
+ self.only_at(*hash[ :only_at ]) if hash.key?(:only_at)
9
+ end
10
+ alias_method_chain(:initialize, :multiple_levels)
11
+ end
12
+ end
13
+
14
+ module GitWorkflow
15
+ module Logging
16
+ # Causes the loading of the logging information before anything else is done.
17
+ Log4r::YamlConfigurator.load_yaml_file(File.expand_path(File.join(File.dirname(__FILE__), 'logger.yaml')))
18
+
19
+ def self.included(base)
20
+ base.instance_eval do
21
+ extend ClassMethods
22
+
23
+ [ :debug, :info, :error ].each do |level|
24
+ class_eval <<-END_OF_LOGGING_METHOD
25
+ def #{ level }(message, &block)
26
+ self.class.#{ level }(message, &block)
27
+ end
28
+
29
+ def self.#{ level }(message, &block)
30
+ self.log(#{ level.inspect }, message, &block)
31
+ end
32
+ END_OF_LOGGING_METHOD
33
+ end
34
+ end
35
+ end
36
+
37
+ class << self
38
+ def logger=(logger)
39
+ @logger = logger
40
+ end
41
+
42
+ def logger
43
+ @logger ||= default_logger
44
+ end
45
+
46
+ def default_logger
47
+ Log4r::Logger['Console']
48
+ end
49
+ end
50
+
51
+ module ClassMethods
52
+ def logger=(logger)
53
+ @logger = logger
54
+ end
55
+
56
+ def logger
57
+ @logger || GitWorkflow::Logging.logger
58
+ end
59
+
60
+ def log(level, message, &block)
61
+ if block_given?
62
+ begin
63
+ logger.send(level, "(start): #{ message }")
64
+ rc = yield
65
+ logger.send(level, "(finish): #{ message }")
66
+ rc
67
+ rescue => exception
68
+ logger.error("#{ message } (#{ exception.message })")
69
+ raise
70
+ end
71
+ else
72
+ logger.send(level, message)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,96 @@
1
+ require 'rest_client'
2
+ require 'builder'
3
+
4
+ # On MacOSX systems you can have a dodgy LibXML2 which Nokogiri warns about. Hide this warning
5
+ # by setting the following constant:
6
+ I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 = true
7
+ require 'nokogiri'
8
+
9
+ module GitWorkflow
10
+ class Story
11
+ include Logging
12
+
13
+ attr_reader :story_id
14
+ attr_reader :name
15
+ attr_reader :description
16
+
17
+ def initialize(service)
18
+ @service = service
19
+ load_story!
20
+ end
21
+
22
+ def branch_name
23
+ @local_branch_name ||= GitWorkflow::Configuration.instance.local_branch_convention.to(self)
24
+ end
25
+
26
+ def remote_branch_name
27
+ @remote_branch_name ||= GitWorkflow::Configuration.instance.remote_branch_convention.to(self)
28
+ end
29
+
30
+ def start_state
31
+ 'started'
32
+ end
33
+
34
+ def finish_state
35
+ @story_type == 'chore' ? 'accepted' : 'finished'
36
+ end
37
+
38
+ def comment(message)
39
+ _service!(:post, 'notes') do |xml|
40
+ xml.note {
41
+ xml.text(message)
42
+ }
43
+ end
44
+ end
45
+
46
+ def service!(&block)
47
+ _service!(:put) do |xml|
48
+ xml.story {
49
+ xml.owned_by(GitWorkflow::Configuration.instance.username)
50
+ yield(xml) if block_given?
51
+ }
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def _service!(action, subresource = nil, &block)
58
+ xml = Builder::XmlMarkup.new
59
+ yield(xml)
60
+ service = @service
61
+ service = service[subresource] unless subresource.nil?
62
+ service.send(action, xml.target!, :content_type => 'application/xml')
63
+ rescue RestClient::ExceptionWithResponse => exception
64
+ error('Cannot seem to perform operation with PT:')
65
+ error(exception.response)
66
+ raise
67
+ end
68
+
69
+ class XmlWrapper
70
+ def initialize(xml)
71
+ @xml = Nokogiri::XML(xml)
72
+ end
73
+
74
+ def required!(element)
75
+ value = optional(element)
76
+ raise MissingElement, "Missing '#{ element }' in the PT XML" if value.blank?
77
+ value
78
+ end
79
+
80
+ def optional(element)
81
+ values = @xml.xpath("/story/#{ element }/text()")
82
+ values.empty? ? nil : values.first.content
83
+ end
84
+ end
85
+
86
+ def load_story!
87
+ info("Retrieving story information") do
88
+ xml = XmlWrapper.new(@service.get)
89
+ @story_id = xml.required!(:id).to_i
90
+ @story_type = xml.required!(:story_type)
91
+ @name = xml.required!(:name)
92
+ @description = xml.optional(:description)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'git_workflow/callbacks/pivotal_tracker_support'
3
+
4
+ describe GitWorkflow::Callbacks::PivotalTrackerSupport::ClassMethods do
5
+ before(:each) do
6
+ @command = Object.new
7
+ @command.stub!(:debug).with(any_args)
8
+ @command.extend(GitWorkflow::Callbacks::PivotalTrackerSupport::ClassMethods)
9
+ end
10
+
11
+ describe '.value_of_environment_variable' do
12
+ before(:each) do
13
+ ENV['somevariable'] = 'this is the value'
14
+ end
15
+
16
+ after(:each) do
17
+ ENV['somevariable'] = nil
18
+ end
19
+
20
+ it 'returns the value of the environment variable' do
21
+ @command.value_of_environment_variable('somevariable').should == 'this is the value'
22
+ end
23
+ end
24
+
25
+ describe '.enable_http_proxy_if_present' do
26
+ after(:each) do
27
+ @command.enable_http_proxy_if_present
28
+ end
29
+
30
+ it 'uses the $http_proxy environment variable first' do
31
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return('http_proxy value')
32
+ RestClient.should_receive(:proxy=).with('http_proxy value')
33
+ end
34
+
35
+ it 'falls back to $HTTP_PROXY' do
36
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return(nil)
37
+ @command.stub!(:value_of_environment_variable).with('HTTP_PROXY').and_return('HTTP_PROXY value')
38
+ RestClient.should_receive(:proxy=).with('HTTP_PROXY value')
39
+ end
40
+
41
+ it 'does not set the HTTP proxy if neither is set' do
42
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return(nil)
43
+ @command.stub!(:value_of_environment_variable).with('HTTP_PROXY').and_return(nil)
44
+ RestClient.should_receive(:proxy=).with(anything).never
45
+ end
46
+ end
47
+ end
48
+
49
+ describe GitWorkflow::Callbacks::PivotalTrackerSupport do
50
+ before(:each) do
51
+ @command = Class.new.new
52
+ @command.stub!(:debug).with(any_args)
53
+ @command.extend(GitWorkflow::Callbacks::PivotalTrackerSupport)
54
+ end
55
+
56
+ describe '#pivotal_tracker_service' do
57
+ it_should_behave_like 'it needs configuration'
58
+
59
+ it 'enables the HTTP proxy' do
60
+ @command.class.instance_eval do
61
+ should_receive(:enable_http_proxy_if_present).once
62
+ should_receive(:pivotal_tracker_url_for).with('project_id', 'story_id').and_return('url')
63
+ end
64
+ RestClient::Resource.stub!(:new).with(any_args).and_return(:ok)
65
+ @command.pivotal_tracker_service_for('story_id')
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow do
4
+ it_should_behave_like 'it needs configuration'
5
+ it_should_behave_like 'it needs a working Story'
6
+
7
+ describe '#service!' do
8
+ it 'generates valid XML' do
9
+ @service.should_receive(:put).with('<story><owned_by>username</owned_by></story>', anything)
10
+ @story.service!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow::Logging::ClassMethods do
4
+ before(:each) do
5
+ @object = Class.new(Object).new
6
+ @object.class.send(:include, GitWorkflow::Logging::ClassMethods)
7
+
8
+ @logger = mock('Logger')
9
+ @object.logger = @logger
10
+ end
11
+
12
+ describe '#log' do
13
+ it 'displays just the message and the level if no block given' do
14
+ @logger.should_receive(:debug).with('my message')
15
+ @object.log(:debug, 'my message')
16
+ end
17
+
18
+ it 'displays messages around the given block' do
19
+ @logger.should_receive(:debug).with('(start): my message').once
20
+ @logger.should_receive(:debug).with('(finish): my message').once
21
+
22
+ callback = mock('callback')
23
+ callback.should_receive(:called).and_return(:ok)
24
+
25
+ @object.log(:debug, 'my message') do
26
+ callback.called
27
+ end.should == :ok
28
+ end
29
+
30
+ it 'displays errors when block raises' do
31
+ @logger.should_receive(:debug).with('(start): my message').once
32
+ @logger.should_receive(:error).with('my message (Broken)').once
33
+
34
+ lambda do
35
+ @object.log(:debug, 'my message') do
36
+ raise StandardError, 'Broken'
37
+ end
38
+ end.should raise_error(StandardError)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow::Git do
4
+ before(:each) do
5
+ @git, @repository = Class.new, mock('Repository')
6
+ @git.send(:extend, GitWorkflow::Git)
7
+ @git.stub(:repository).and_return(@repository)
8
+ end
9
+
10
+ describe '.get_config_value_for!' do
11
+ it 'returns the value if set' do
12
+ @git.should_receive(:get_config_value_for).with('key').and_return('value')
13
+ @git.get_config_value_for!('key').should == 'value'
14
+ end
15
+
16
+ it 'raises an exception if the value is not set' do
17
+ @git.should_receive(:get_config_value_for).with('key').and_return(nil)
18
+ lambda { @git.get_config_value_for!('key') }.should raise_error(StandardError)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ class GitWorkflow::Git::Repository
4
+ def self.for_testing
5
+ new
6
+ end
7
+ end
8
+
9
+ describe GitWorkflow::Git::Repository do
10
+ before(:each) do
11
+ @repository = described_class.for_testing
12
+ end
13
+
14
+ describe '#config_get' do
15
+ it 'raises ConfigError on command failure' do
16
+ @repository.should_receive(:execute_command).with(anything).and_raise(Execution::CommandFailure.new('command', :failure))
17
+ lambda { @repository.config_get('key') }.should raise_error(GitWorkflow::Git::Repository::ConfigError)
18
+ end
19
+
20
+ context 'when command succeeds' do
21
+ after(:each) do
22
+ @repository.should_receive(:execute_command).with('git config key').and_return(@value)
23
+ @repository.config_get('key').should == @expected
24
+ end
25
+
26
+ it 'returns the value that is set' do
27
+ @value = @expected = 'value'
28
+ end
29
+
30
+ it 'strips whitespace from the value' do
31
+ @value, @expected = ' value ', 'value'
32
+ end
33
+
34
+ it 'returns nil if value is empty' do
35
+ @value, @expected = '', nil
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe GitWorkflow::Git do
42
+ before(:each) do
43
+ @git, @repository = Class.new, mock('Repository')
44
+ @git.send(:extend, GitWorkflow::Git)
45
+ @git.stub(:repository).and_return(@repository)
46
+ end
47
+
48
+ describe '#get_config_value_for' do
49
+ it 'returns whatever is set' do
50
+ @repository.should_receive(:config_get).with('key').and_return(:ok)
51
+ @git.get_config_value_for('key').should == :ok
52
+ end
53
+
54
+ it 'returns nil for failure' do
55
+ @repository.should_receive(:config_get).with('key').and_raise(GitWorkflow::Git::Repository::ConfigError)
56
+ @git.get_config_value_for('key').should == nil
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ class GitWorkflow::Commands::Setup
4
+ public :set_value_through
5
+ public :ask
6
+ public :choose
7
+
8
+ public :enquire_about_name
9
+ public :enquire_about_token
10
+ public :enquire_about_project_id
11
+ public :enquire_about_workflow
12
+ public :enquire_about_branches
13
+ public :choose_branch_convention
14
+
15
+ public :get_config_value_for
16
+ public :set_config_value
17
+ end
18
+
19
+ describe GitWorkflow::Commands::Setup do
20
+ before(:each) do
21
+ @command, @highline = described_class.new([]), mock('HighLine')
22
+ @command.stub(:highline).and_return(@highline)
23
+
24
+ @question = mock('Question')
25
+ @question.stub(:question=).with(anything)
26
+ end
27
+
28
+ describe '#execute' do
29
+ it 'asks the right questions' do
30
+ [ :name, :token, :project_id, :workflow, :branches ].each do |query|
31
+ @command.should_receive(:"enquire_about_#{ query }").ordered
32
+ end
33
+ @command.execute
34
+ end
35
+ end
36
+
37
+ describe '#ask' do
38
+ it 'calls through to set the value' do
39
+ callback = mock('callback')
40
+ callback.should_receive(:called)
41
+
42
+ @command.should_receive(:set_value_through).with(:ask, :setting, 'Dummy', :options).and_yield
43
+ @command.ask(:setting, :options) { callback.called }
44
+ end
45
+ end
46
+
47
+ describe '#choose' do
48
+ it 'calls through to set the value' do
49
+ callback = mock('callback')
50
+ callback.should_receive(:called)
51
+
52
+ @command.should_receive(:set_value_through).with(:choose, :setting, :options).and_yield
53
+ @command.choose(:setting, :options) { callback.called }
54
+ end
55
+ end
56
+
57
+ describe '#set_value_through' do
58
+ before(:each) do
59
+ @question.should_receive(:default=).with(:default)
60
+
61
+ @callback = mock('callback')
62
+ @callback.should_receive(:called).with(@question)
63
+
64
+ @command.should_receive(:get_config_value_for).with(:setting).and_return(:default)
65
+ end
66
+
67
+ it 'unspecified answer type sets value' do
68
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return(:ok)
69
+ @command.should_receive(:set_config_value).with(:setting, :ok)
70
+ @command.set_value_through(:question_user, :setting, :arg1, :arg2) { |question| @callback.called(question) }
71
+ end
72
+
73
+ context 'when answer is optional' do
74
+ after(:each) do
75
+ @command.set_value_through(:question_user, :setting, :arg1, :arg2, :optional => true) { |question| @callback.called(question) }
76
+ end
77
+
78
+ it 'does not set the value if answer is blank' do
79
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return('')
80
+ end
81
+
82
+ it 'sets the value if answer is non-blank' do
83
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return('OK')
84
+ @command.should_receive(:set_config_value).with(:setting, 'OK')
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#enquire_about_name' do
90
+ it 'optionally prompts for the user.name' do
91
+ @command.should_receive(:get_config_value_for).with('user.name').and_return('John Smith')
92
+ @command.should_receive(:ask).with('pt.username', hash_including(:optional => true))
93
+ @command.enquire_about_name
94
+ end
95
+ end
96
+
97
+ describe '#enquire_about_token' do
98
+ it 'prompts for the pt.token' do
99
+ @question.should_receive(:validate=).with(/^[A-Fa-f0-9]{32}$/)
100
+
101
+ @command.should_receive(:ask).with('pt.token').and_yield(@question)
102
+ @command.enquire_about_token
103
+ end
104
+ end
105
+
106
+ describe '#enquire_about_project_id' do
107
+ it 'prompts for the pt.projectid numeric' do
108
+ @question.should_receive(:answer_type=).with(Integer)
109
+
110
+ @command.should_receive(:ask).with('pt.projectid').and_yield(@question)
111
+ @command.enquire_about_project_id
112
+ end
113
+ end
114
+
115
+ describe '#enquire_about_workflow' do
116
+ it 'prompts for the workflow.callbacks value' do
117
+ @command.should_receive(:ask).with('workflow.callbacks')
118
+ @command.enquire_about_workflow
119
+ end
120
+ end
121
+
122
+ describe '#enquire_about_branches' do
123
+ it 'prompts for branch conventions' do
124
+ @command.should_receive(:choose_branch_convention).with(:local)
125
+ @command.should_receive(:choose_branch_convention).with(:remote)
126
+
127
+ @command.enquire_about_branches
128
+ end
129
+ end
130
+
131
+ describe '#choose_branch_convention' do
132
+ it 'works with the correct setting' do
133
+ @command.should_receive(:choose).with('workflow.foobarbranchconvention')
134
+ @command.choose_branch_convention(:foobar)
135
+ end
136
+
137
+ it 'sets up the menu correctly' do
138
+ menu = mock('menu')
139
+ menu.stub(:header=).with(anything)
140
+ menu.should_receive(:prompt=).with(/\bfoobar\b/)
141
+ menu.should_receive(:menu_option).with(/number\b.+title/, '${number}_${name}')
142
+ menu.should_receive(:menu_option).with(/title\b.+number/, '${name}_${number}')
143
+ @command.should_receive(:choose).with(anything).and_yield(menu)
144
+
145
+ @command.choose_branch_convention(:foobar)
146
+ end
147
+ end
148
+ end