hammer_cli 0.8.0 → 0.9.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/config/cli_config.template.yml +2 -2
  3. data/doc/release_notes.md +15 -0
  4. data/lib/hammer_cli/abstract.rb +22 -31
  5. data/lib/hammer_cli/apipie.rb +1 -0
  6. data/lib/hammer_cli/apipie/api_connection.rb +27 -0
  7. data/lib/hammer_cli/apipie/option_builder.rb +3 -3
  8. data/lib/hammer_cli/apipie/resource.rb +1 -26
  9. data/lib/hammer_cli/connection.rb +12 -11
  10. data/lib/hammer_cli/context.rb +4 -2
  11. data/lib/hammer_cli/exception_handler.rb +1 -1
  12. data/lib/hammer_cli/help/builder.rb +58 -0
  13. data/lib/hammer_cli/help/text_builder.rb +79 -0
  14. data/lib/hammer_cli/logger.rb +24 -21
  15. data/lib/hammer_cli/options/normalizers.rb +13 -2
  16. data/lib/hammer_cli/output/adapter/table.rb +2 -0
  17. data/lib/hammer_cli/output/formatters.rb +1 -1
  18. data/lib/hammer_cli/output/utils.rb +43 -0
  19. data/lib/hammer_cli/table_print/column.rb +19 -0
  20. data/lib/hammer_cli/table_print/formatter.rb +18 -0
  21. data/lib/hammer_cli/utils.rb +5 -1
  22. data/lib/hammer_cli/validator.rb +12 -2
  23. data/lib/hammer_cli/version.rb +1 -1
  24. data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
  25. data/locale/ca/hammer-cli.edit.po +26 -15
  26. data/locale/ca/hammer-cli.po +22 -6
  27. data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
  28. data/locale/de/hammer-cli.edit.po +32 -20
  29. data/locale/de/hammer-cli.po +22 -6
  30. data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
  31. data/locale/en/hammer-cli.edit.po +47 -29
  32. data/locale/en/hammer-cli.po +21 -5
  33. data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
  34. data/locale/en_GB/hammer-cli.edit.po +28 -17
  35. data/locale/en_GB/hammer-cli.po +22 -6
  36. data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
  37. data/locale/es/hammer-cli.edit.po +28 -17
  38. data/locale/es/hammer-cli.po +22 -6
  39. data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
  40. data/locale/fr/hammer-cli.edit.po +28 -17
  41. data/locale/fr/hammer-cli.po +22 -6
  42. data/locale/hammer-cli.pot +49 -31
  43. data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
  44. data/locale/it/hammer-cli.edit.po +23 -12
  45. data/locale/it/hammer-cli.po +22 -6
  46. data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
  47. data/locale/ja/hammer-cli.edit.po +28 -17
  48. data/locale/ja/hammer-cli.po +22 -6
  49. data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
  50. data/locale/ko/hammer-cli.edit.po +27 -16
  51. data/locale/ko/hammer-cli.po +22 -6
  52. data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
  53. data/locale/pt_BR/hammer-cli.edit.po +30 -19
  54. data/locale/pt_BR/hammer-cli.po +22 -6
  55. data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
  56. data/locale/ru/hammer-cli.edit.po +28 -17
  57. data/locale/ru/hammer-cli.po +22 -6
  58. data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
  59. data/locale/zh_CN/hammer-cli.edit.po +28 -17
  60. data/locale/zh_CN/hammer-cli.po +22 -6
  61. data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
  62. data/locale/zh_TW/hammer-cli.edit.po +27 -16
  63. data/locale/zh_TW/hammer-cli.po +22 -6
  64. data/man/hammer.1.gz +0 -0
  65. data/test/functional/help_test.rb +87 -0
  66. data/test/test_helper.rb +6 -0
  67. data/test/unit/abstract_test.rb +9 -0
  68. data/test/unit/apipie/api_connection_test.rb +38 -0
  69. data/test/unit/apipie/command_test.rb +6 -46
  70. data/test/unit/connection_test.rb +45 -54
  71. data/test/unit/exception_handler_test.rb +1 -1
  72. data/test/unit/fixtures/apipie/documented.json +1 -1
  73. data/test/unit/help/builder_test.rb +57 -0
  74. data/test/unit/help/text_builder_test.rb +140 -0
  75. data/test/unit/logger_test.rb +19 -0
  76. data/test/unit/options/normalizers_test.rb +12 -0
  77. data/test/unit/output/adapter/table_test.rb +101 -13
  78. data/test/unit/output/formatters_test.rb +6 -3
  79. data/test/unit/validator_test.rb +31 -2
  80. metadata +207 -179
data/man/hammer.1.gz CHANGED
Binary file
@@ -0,0 +1,87 @@
1
+ require File.join(File.dirname(__FILE__), './test_helper')
2
+
3
+ describe 'help' do
4
+ class CmdWithHelp < HammerCLI::AbstractCommand
5
+ extend_help do |h|
6
+ h.text 'Details about interface settings'
7
+
8
+ h.section 'Available keys for --interface' do |h|
9
+ h.list([
10
+ 'mac',
11
+ 'ip',
12
+ ['type', 'One of interface, bmc, bond'],
13
+ 'name',
14
+ 'subnet_id',
15
+ 'domain_id',
16
+ 'identifier',
17
+ ['managed', 'true/false'],
18
+ ['primary', 'true/false, each managed hosts needs to have one primary interface.'],
19
+ ['provision', 'true/false'],
20
+ ['virtual', 'true/false']
21
+ ])
22
+ h.section 'For virtual interfaces' do |h|
23
+ h.list([
24
+ ['tag', 'VLAN tag, this attribute has precedence over the subnet VLAN ID. Only for virtual interfaces.'],
25
+ ['attached_to', 'Identifier of the interface to which this interface belongs, e.g. eth1.']
26
+ ])
27
+ end
28
+ h.section 'For bonds' do |h|
29
+ h.list([
30
+ ['mode', 'One of balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb, balance-alb'],
31
+ ['attached_devices', 'Identifiers of slave interfaces, e.g. [eth1,eth2]'],
32
+ 'bond_options'
33
+ ])
34
+ end
35
+ h.section 'For BMCs' do |h|
36
+ h.list([
37
+ ['provider', 'always IPMI'],
38
+ 'username',
39
+ 'password'
40
+ ])
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ it 'prints additional help' do
47
+ result = run_cmd(['-h'], {}, CmdWithHelp)
48
+ result.out.must_equal [
49
+ 'Usage:',
50
+ ' hammer [OPTIONS]',
51
+ '',
52
+ 'Options:',
53
+ ' -h, --help print help',
54
+ '',
55
+ 'Details about interface settings',
56
+ '',
57
+ 'Available keys for --interface:',
58
+ ' mac',
59
+ ' ip',
60
+ ' type One of interface, bmc, bond',
61
+ ' name',
62
+ ' subnet_id',
63
+ ' domain_id',
64
+ ' identifier',
65
+ ' managed true/false',
66
+ ' primary true/false, each managed hosts needs to have one primary interface.',
67
+ ' provision true/false',
68
+ ' virtual true/false',
69
+ '',
70
+ ' For virtual interfaces:',
71
+ ' tag VLAN tag, this attribute has precedence over the subnet VLAN ID. Only for virtual interfaces.',
72
+ ' attached_to Identifier of the interface to which this interface belongs, e.g. eth1.',
73
+ '',
74
+ ' For bonds:',
75
+ ' mode One of balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb, balance-alb',
76
+ ' attached_devices Identifiers of slave interfaces, e.g. [eth1,eth2]',
77
+ ' bond_options',
78
+ '',
79
+ ' For BMCs:',
80
+ ' provider always IPMI',
81
+ ' username',
82
+ ' password',
83
+ ''
84
+ ].join("\n")
85
+ end
86
+
87
+ end
data/test/test_helper.rb CHANGED
@@ -18,3 +18,9 @@ require 'hammer_cli/logger'
18
18
 
19
19
  Logging.logger.root.appenders = Logging::Appenders['__test__'] || Logging::Appenders::StringIo.new('__test__')
20
20
 
21
+ HammerCLI.context[:api_connection].create(:apipie) do
22
+ HammerCLI::Apipie::ApiConnection.new({
23
+ :apidoc_cache_dir => 'test/unit/fixtures/apipie',
24
+ :apidoc_cache_name => 'architectures'
25
+ })
26
+ end
@@ -376,5 +376,14 @@ describe HammerCLI::AbstractCommand do
376
376
  CmdOD2.output_definition.fields.length.must_equal 1
377
377
  end
378
378
 
379
+ it "should allow for multiple validation blocks" do
380
+ class CmdName1 < HammerCLI::AbstractCommand
381
+ validate_options do; end
382
+ validate_options do; end
383
+ end
384
+
385
+ assert_equal 2, CmdName1.validation_blocks.length
386
+ end
387
+
379
388
  end
380
389
 
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(__FILE__), '../../test_helper')
2
+
3
+ describe HammerCLI::Apipie::ApiConnection do
4
+ let(:connection) { HammerCLI::Connection.new }
5
+
6
+ describe '#initialize' do
7
+
8
+ let(:empty_params) {{}}
9
+
10
+ def api_stub(params = {})
11
+ api_stub = stub()
12
+ ApipieBindings::API.expects(:new).with(params).returns(api_stub)
13
+ api_stub
14
+ end
15
+
16
+ it "passes attributes to apipie bindings" do
17
+ params = { :apidoc_cache_name => 'test.example.com' }
18
+
19
+ api_stub(params)
20
+ HammerCLI::Apipie::ApiConnection.new(params)
21
+ end
22
+
23
+ context "with :clear_cache => true" do
24
+ it "clears cache" do
25
+ api_stub.expects(:clean_cache)
26
+ HammerCLI::Apipie::ApiConnection.new(empty_params, :reload_cache => true)
27
+ end
28
+
29
+ it "logs message when logger is available" do
30
+ logger = stub()
31
+ logger.expects(:debug).with('Apipie cache was cleared')
32
+
33
+ api_stub.expects(:clean_cache)
34
+ HammerCLI::Apipie::ApiConnection.new(empty_params, :reload_cache => true, :logger => logger)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -3,17 +3,11 @@ require File.join(File.dirname(__FILE__), '../test_helper')
3
3
 
4
4
  describe HammerCLI::Apipie::Command do
5
5
 
6
- class TestCommand < HammerCLI::Apipie::Command
7
- def self.resource_config
8
- { :apidoc_cache_dir => 'test/unit/fixtures/apipie', :apidoc_cache_name => 'architectures' }
9
- end
10
- end
11
-
12
- class ParentCommand < TestCommand
6
+ class ParentCommand < HammerCLI::Apipie::Command
13
7
  action :show
14
8
  end
15
9
 
16
- class OptionCommand < TestCommand
10
+ class OptionCommand < HammerCLI::Apipie::Command
17
11
  resource :architectures, :create
18
12
 
19
13
  def option_name
@@ -23,10 +17,9 @@ describe HammerCLI::Apipie::Command do
23
17
  def option_operatingsystem_ids
24
18
  nil
25
19
  end
26
-
27
20
  end
28
21
 
29
- class CommandA < TestCommand
22
+ class CommandA < HammerCLI::Apipie::Command
30
23
  resource :architectures, :index
31
24
 
32
25
  class CommandB < ParentCommand
@@ -37,14 +30,10 @@ describe HammerCLI::Apipie::Command do
37
30
  end
38
31
 
39
32
  let(:ctx) { { :adapter => :silent, :interactive => false } }
40
- let(:cmd_class) { TestCommand.dup }
33
+ let(:cmd_class) { HammerCLI::Apipie::Command.dup }
41
34
  let(:cmd) { cmd_class.new("", ctx) }
42
35
  let(:cmd_run) { cmd.run([]) }
43
36
 
44
- before :each do
45
- HammerCLI::Connection.drop_all
46
- end
47
-
48
37
  context "setting resources" do
49
38
 
50
39
  it "should set resource and action together" do
@@ -103,40 +92,11 @@ describe HammerCLI::Apipie::Command do
103
92
  end
104
93
 
105
94
  context "resource defined" do
106
-
107
- before :each do
108
- HammerCLI::Connection.drop_all
109
- ApipieBindings::API.any_instance.stubs(:call).returns([])
110
- cmd.class.resource :architectures, :index
111
- end
112
-
113
95
  it "should perform a call to api when resource is defined" do
114
- ctx[:defaults] = stub(:get_defaults => {})
115
- cmd_run.must_equal 0
116
- end
117
- end
118
-
119
- context "reload apipie cache" do
120
-
121
- before :each do
122
- HammerCLI::Connection.drop_all
123
- ApipieBindings::API.any_instance.stubs(:call).returns([])
124
- end
125
-
126
- it "clears the cache on init when required from config" do
127
- HammerCLI::Settings.load({ :reload_cache => true })
128
- ApipieBindings::API.any_instance.expects(:clean_cache).returns(nil)
96
+ ApipieBindings::API.any_instance.expects(:call).returns([])
129
97
  cmd.class.resource :architectures, :index
130
- HammerCLI::Settings.load({ :reload_cache => false })
131
- end
132
-
133
- it "clears the cache on init when required from CLI" do
134
- HammerCLI::Settings.load({ :_params => { :reload_cache => true }})
135
- ApipieBindings::API.any_instance.expects(:clean_cache).returns(nil)
136
- cmd.class.resource :architectures, :index
137
- HammerCLI::Settings.load({ :_params => { :reload_cache => false }})
98
+ cmd_run.must_equal 0
138
99
  end
139
-
140
100
  end
141
101
 
142
102
  context "options" do
@@ -1,68 +1,59 @@
1
1
  require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  describe HammerCLI::Connection do
4
-
5
- before :each do
6
- # clean up global settings
7
- HammerCLI::Connection.drop_all
8
- HammerCLI::Settings.load({:_params => {:interactive => false}})
9
- end
10
-
11
- let(:connection) { HammerCLI::Connection }
12
-
13
- class Connector < HammerCLI::AbstractConnector
14
-
15
- attr_reader :url
16
-
17
- def initialize(params)
18
- @url = params[:url]
19
- super
4
+ let(:connections) { HammerCLI::Connection.new }
5
+
6
+ describe '#create' do
7
+ it "creates new connection" do
8
+ connections.create(:test) do
9
+ :conn1
10
+ end
11
+ assert_equal :conn1, connections.get(:test)
20
12
  end
21
13
 
22
- end
23
-
24
- it "should return the conection" do
25
- conn = connection.create(:test, {})
26
- conn.must_be_kind_of HammerCLI::AbstractConnector
27
- end
28
-
29
- it "should create the connection only once" do
30
- conn1 = connection.create(:test, {})
31
- conn2 = connection.create(:test, {})
32
- conn1.must_equal conn2
33
- end
14
+ it "doesn't overwrite the connection when called multiple times" do
15
+ connections.create(:test) do
16
+ :conn1
17
+ end
18
+ connections.create(:test) do
19
+ :conn2
20
+ end
21
+ assert_equal :conn1, connections.get(:test)
22
+ end
34
23
 
35
- it "should test the connection" do
36
- connection.exist?(:test).must_equal false
37
- conn1 = connection.create(:test, {})
38
- connection.exist?(:test).must_equal true
39
- end
24
+ it 'writes message to log' do
25
+ logger = stub()
26
+ logger.expects(:debug).with('Registered: test_connection')
40
27
 
41
- it "should get the connection" do
42
- conn1 = connection.create(:test, {})
43
- conn2 = connection.get(:test)
44
- conn1.must_equal conn2
28
+ connections = HammerCLI::Connection.new(logger)
29
+ connections.create(:test_connection) do
30
+ :test_connection
31
+ end
32
+ end
45
33
  end
46
34
 
47
-
48
- it "should be able to drop all" do
49
- conn1 = connection.create(:test, {})
50
- connection.drop_all
51
- conn2 = connection.create(:test, {})
52
- conn1.wont_equal conn2 # TODO
35
+ describe '#drop' do
36
+ it 'drops the connection' do
37
+ connections.create(:test) do
38
+ :conn1
39
+ end
40
+ connections.drop(:test)
41
+ assert_nil connections.get(:test)
42
+ end
53
43
  end
54
44
 
55
- it "should drop the connection" do
56
- conn1 = connection.create(:test, {})
57
- connection.drop(:test)
58
- conn2 = connection.create(:test, {})
59
- conn1.wont_equal conn2
60
- end
45
+ describe '#drop_all' do
46
+ it 'drops all connections' do
47
+ connections.create(:test1) do
48
+ :conn1
49
+ end
50
+ connections.create(:test2) do
51
+ :conn3
52
+ end
53
+ connections.drop_all
61
54
 
62
- it "should accept custom connector" do
63
- conn = connection.create(:test, {:url => 'URL'}, :connector => Connector)
64
- conn.must_be_kind_of Connector
65
- conn.url.must_equal 'URL'
55
+ assert_nil connections.get(:test1)
56
+ assert_nil connections.get(:test2)
57
+ end
66
58
  end
67
-
68
59
  end
@@ -14,7 +14,7 @@ describe HammerCLI::ExceptionHandler do
14
14
  let(:cmd) { Class.new(HammerCLI::AbstractCommand).new("command_name") }
15
15
 
16
16
  it "should handle unauthorized" do
17
- output.expects(:print_error).with(heading, "Invalid username or password")
17
+ output.expects(:print_error).with(heading, "Unauthorized")
18
18
  handler.handle_exception(RestClient::Unauthorized.new, :heading => heading)
19
19
  end
20
20
 
@@ -134,7 +134,7 @@
134
134
  "name": "boolean_param",
135
135
  "allow_null": false,
136
136
  "full_name": "documented[boolean_param]",
137
- "validator": "Must be Boolean",
137
+ "validator": "Must be 'true' or 'false' or '1' or '0'",
138
138
  "expected_type": "boolean",
139
139
  "description": "",
140
140
  "required": false
@@ -0,0 +1,57 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper')
2
+
3
+ describe HammerCLI::Help::Builder do
4
+ let(:help) { HammerCLI::Help::Builder.new }
5
+
6
+ describe 'sorting options' do
7
+ it 'prints options alphabetically sorted' do
8
+ options = [
9
+ Clamp::Option::Definition.new(['--zzz-option'], 'OPT_Z', 'Some description'),
10
+ Clamp::Option::Definition.new(['--yyy-option'], 'OPT_Y', 'Some description'),
11
+ Clamp::Option::Definition.new(['--aaa-option'], 'OPT_A', 'Some description'),
12
+ Clamp::Option::Definition.new(['--bbb-option'], 'OPT_B', 'Some description')
13
+ ]
14
+ help.add_list('Options', options)
15
+
16
+ help.string.strip.must_equal [
17
+ 'Options:',
18
+ ' --aaa-option OPT_A Some description',
19
+ ' --bbb-option OPT_B Some description',
20
+ ' --yyy-option OPT_Y Some description',
21
+ ' --zzz-option OPT_Z Some description'
22
+ ].join("\n")
23
+ end
24
+ end
25
+
26
+ describe 'adding text' do
27
+ let(:content_1) {[
28
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
29
+ 'Donec sem dolor, pellentesque sit amet auctor nec, finibus ut elit.'
30
+ ]}
31
+ let(:content_2) {[
32
+ 'Donec et erat in enim pellentesque pretium. Sed egestas sem id lectus ultricies lobortis.',
33
+ 'Etiam posuere, ipsum scelerisque maximus fermentum, libero dui sagittis felis, at molestie erat augue at dui. Ut dapibus rutrum purus a luctus.'
34
+ ]}
35
+
36
+ it 'prints paragraphs without headings' do
37
+ help.add_text(content_1.join("\n"))
38
+ help.string.strip.must_equal content_1.join("\n")
39
+ end
40
+
41
+ it 'prints paragraphs with headings' do
42
+ help.add_text(content_1.join("\n"))
43
+ help.string.strip.must_equal content_1.join("\n")
44
+ end
45
+
46
+ it 'prints multiple paragraphs divided with empty line' do
47
+ help.add_text(content_1.join("\n"))
48
+ help.add_text(content_2.join("\n"))
49
+
50
+ expected_output = content_1 + [''] + content_2
51
+ expected_output = expected_output.join("\n")
52
+
53
+ help.string.strip.must_equal expected_output
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper')
2
+
3
+ describe HammerCLI::Help::TextBuilder do
4
+ let(:help) { HammerCLI::Help::TextBuilder.new }
5
+
6
+ describe '#text' do
7
+ it 'prints text' do
8
+ help.text('Lorem ipsum')
9
+ help.string.must_equal "Lorem ipsum\n"
10
+ end
11
+
12
+ it 'prints multiple blocks with spaces' do
13
+ help.text('Lorem ipsum')
14
+ help.text('Dolor sit amet')
15
+ help.string.must_equal [
16
+ 'Lorem ipsum',
17
+ '',
18
+ 'Dolor sit amet',
19
+ ''
20
+ ].join("\n")
21
+ end
22
+ end
23
+
24
+ describe '#section' do
25
+ it 'prints section heading' do
26
+ help.section('Heading')
27
+ help.string.must_equal "Heading:\n\n"
28
+ end
29
+
30
+ it 'indents section content' do
31
+ help.section('Heading') do |h|
32
+ h.text('Lorem ipsum')
33
+ h.text('Dolor sit amet')
34
+ end
35
+ help.string.must_equal [
36
+ 'Heading:',
37
+ ' Lorem ipsum',
38
+ '',
39
+ ' Dolor sit amet',
40
+ ''
41
+ ].join("\n")
42
+ end
43
+ end
44
+
45
+ describe '#list' do
46
+ it 'prints empty list' do
47
+ help.list([])
48
+ help.string.must_equal ""
49
+ end
50
+
51
+ it 'prints single column list' do
52
+ help.list([
53
+ :a,
54
+ :bb,
55
+ :ccc
56
+ ])
57
+ help.string.must_equal [
58
+ 'a',
59
+ 'bb',
60
+ 'ccc',
61
+ ''
62
+ ].join("\n")
63
+ end
64
+
65
+ it 'prints two column list' do
66
+ help.list([
67
+ [:a, 'This is line A'],
68
+ [:bb, 'This is line B'],
69
+ [:ccc]
70
+ ])
71
+ help.string.must_equal [
72
+ 'a This is line A',
73
+ 'bb This is line B',
74
+ 'ccc',
75
+ ''
76
+ ].join("\n")
77
+ end
78
+
79
+ it 'handles multiple lines in the second column' do
80
+ help.list([
81
+ [:a, "This is line A\nThis is line A part two"],
82
+ [:bb, 'This is line B'],
83
+ [:ccc, 'This is line C']
84
+ ])
85
+ help.string.must_equal [
86
+ 'a This is line A',
87
+ ' This is line A part two',
88
+ 'bb This is line B',
89
+ 'ccc This is line C',
90
+ ''
91
+ ].join("\n")
92
+ end
93
+
94
+ it 'can adjust indentation of the second column' do
95
+ help.list([
96
+ ['a', 'This is line A'],
97
+ ['This line B is too long for the first column', 'This is line B'],
98
+ ['ccc', 'This is line C']
99
+ ])
100
+ help.string.must_equal [
101
+ 'a This is line A',
102
+ 'This line B is too long for the first column This is line B',
103
+ 'ccc This is line C',
104
+ ''
105
+ ].join("\n")
106
+ end
107
+ end
108
+
109
+ describe '#indent' do
110
+ let(:text) {
111
+ [
112
+ 'A',
113
+ 'B',
114
+ '',
115
+ ' C'
116
+ ].join("\n")
117
+ }
118
+
119
+ it 'indents text' do
120
+ expected_result = [
121
+ ' A',
122
+ ' B',
123
+ '',
124
+ ' C'
125
+ ].join("\n")
126
+ help.indent(text).must_equal(expected_result)
127
+ end
128
+
129
+ it 'indents text with custom padding' do
130
+ expected_result = [
131
+ '**A',
132
+ '**B',
133
+ '**',
134
+ '** C'
135
+ ].join("\n")
136
+ help.indent(text, '**').must_equal(expected_result)
137
+ end
138
+ end
139
+ end
140
+