hammer_cli 0.0.18 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -314
- data/bin/hammer +45 -6
- data/config/cli.modules.d/module_config_template.yml +4 -0
- data/config/cli_config.template.yml +9 -11
- data/doc/developer_docs.md +1 -0
- data/doc/i18n.md +85 -0
- data/doc/installation.md +321 -0
- data/lib/hammer_cli.rb +3 -0
- data/lib/hammer_cli/abstract.rb +15 -24
- data/lib/hammer_cli/apipie/command.rb +13 -7
- data/lib/hammer_cli/apipie/options.rb +14 -16
- data/lib/hammer_cli/apipie/read_command.rb +6 -1
- data/lib/hammer_cli/apipie/resource.rb +48 -58
- data/lib/hammer_cli/apipie/write_command.rb +5 -1
- data/lib/hammer_cli/completer.rb +77 -21
- data/lib/hammer_cli/connection.rb +44 -0
- data/lib/hammer_cli/exception_handler.rb +15 -4
- data/lib/hammer_cli/exceptions.rb +6 -0
- data/lib/hammer_cli/i18n.rb +95 -0
- data/lib/hammer_cli/logger.rb +3 -3
- data/lib/hammer_cli/main.rb +12 -11
- data/lib/hammer_cli/modules.rb +19 -6
- data/lib/hammer_cli/options/normalizers.rb +42 -7
- data/lib/hammer_cli/options/option_definition.rb +2 -2
- data/lib/hammer_cli/output.rb +1 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +20 -0
- data/lib/hammer_cli/output/adapter/base.rb +49 -78
- data/lib/hammer_cli/output/adapter/csv.rb +5 -5
- data/lib/hammer_cli/output/adapter/table.rb +41 -10
- data/lib/hammer_cli/output/dsl.rb +1 -1
- data/lib/hammer_cli/output/field_filter.rb +21 -0
- data/lib/hammer_cli/output/fields.rb +44 -78
- data/lib/hammer_cli/output/formatters.rb +38 -0
- data/lib/hammer_cli/settings.rb +28 -6
- data/lib/hammer_cli/shell.rb +58 -57
- data/lib/hammer_cli/utils.rb +14 -0
- data/lib/hammer_cli/validator.rb +5 -5
- data/lib/hammer_cli/version.rb +1 -1
- data/locale/Makefile +64 -0
- data/locale/hammer-cli.pot +203 -0
- data/locale/zanata.xml +29 -0
- data/test/unit/apipie/command_test.rb +42 -25
- data/test/unit/apipie/read_command_test.rb +10 -7
- data/test/unit/apipie/write_command_test.rb +9 -8
- data/test/unit/completer_test.rb +206 -21
- data/test/unit/connection_test.rb +68 -0
- data/test/unit/fixtures/apipie/architectures.json +153 -0
- data/test/unit/fixtures/apipie/documented.json +79 -0
- data/test/unit/fixtures/json_input/invalid.json +12 -0
- data/test/unit/fixtures/json_input/valid.json +12 -0
- data/test/unit/history_test.rb +71 -0
- data/test/unit/main_test.rb +9 -0
- data/test/unit/modules_test.rb +22 -6
- data/test/unit/options/field_filter_test.rb +27 -0
- data/test/unit/options/normalizers_test.rb +53 -0
- data/test/unit/output/adapter/base_test.rb +162 -10
- data/test/unit/output/adapter/csv_test.rb +16 -3
- data/test/unit/output/adapter/table_test.rb +97 -13
- data/test/unit/output/dsl_test.rb +74 -6
- data/test/unit/output/fields_test.rb +93 -62
- data/test/unit/output/formatters_test.rb +47 -0
- data/test/unit/settings_test.rb +35 -4
- data/test/unit/utils_test.rb +45 -0
- metadata +85 -4
- data/test/unit/apipie/fake_api.rb +0 -101
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
describe HammerCLI::Output::FieldFilter do
|
4
|
+
|
5
|
+
let(:fields) { [
|
6
|
+
Fields::Field.new(:label => "field"),
|
7
|
+
Fields::Collection.new(:label => "collection"),
|
8
|
+
Fields::Id.new(:label => "id")
|
9
|
+
] }
|
10
|
+
let(:field_labels) { fields.map(&:label).sort }
|
11
|
+
|
12
|
+
it "lets all fields go by default" do
|
13
|
+
f = HammerCLI::Output::FieldFilter.new
|
14
|
+
f.filter(fields).map(&:label).sort.must_equal ["field", "collection", "id"].sort
|
15
|
+
end
|
16
|
+
|
17
|
+
it "filters fields by class" do
|
18
|
+
f = HammerCLI::Output::FieldFilter.new([Fields::Id])
|
19
|
+
f.filter(fields).map(&:label).sort.must_equal ["field", "collection"].sort
|
20
|
+
end
|
21
|
+
|
22
|
+
it "filters fields by superclass" do
|
23
|
+
f = HammerCLI::Output::FieldFilter.new([Fields::ContainerField])
|
24
|
+
f.filter(fields).map(&:label).sort.must_equal ["field", "id"].sort
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -122,6 +122,33 @@ describe HammerCLI::Options::Normalizers do
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
+
describe 'json input' do
|
126
|
+
let(:formatter) { HammerCLI::Options::Normalizers::JSONInput.new }
|
127
|
+
|
128
|
+
it "should return a hash on valid json file" do
|
129
|
+
file = File.join(File.dirname(__FILE__), '../fixtures/json_input/valid.json')
|
130
|
+
formatter.format(file).must_equal({ "units" => [ { "name" => "zip", "version" => "10.0" },
|
131
|
+
{ "name" => "zap", "version" => "9.0" }] })
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should raise exception on invalid json file contents" do
|
135
|
+
file = File.join(File.dirname(__FILE__), '../fixtures/json_input/invalid.json')
|
136
|
+
proc { formatter.format(file) }.must_raise ArgumentError
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return a hash on valid json string" do
|
140
|
+
json_string = '{ "units":[{ "name":"zip", "version":"10.0" }, { "name":"zap", "version":"9.0" }] }'
|
141
|
+
formatter.format(json_string).must_equal({ "units" => [ { "name" => "zip", "version" => "10.0" },
|
142
|
+
{ "name" => "zap", "version" => "9.0" }] })
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should raise exception on invalid json string" do
|
146
|
+
json_string = "{ units:[{ name:zip, version:10.0 }, { name:zap, version:9.0 }] }"
|
147
|
+
proc { formatter.format(json_string) }.must_raise ArgumentError
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
125
152
|
describe 'enum' do
|
126
153
|
|
127
154
|
let(:formatter) { HammerCLI::Options::Normalizers::Enum.new ['a', 'b'] }
|
@@ -144,5 +171,31 @@ describe HammerCLI::Options::Normalizers do
|
|
144
171
|
|
145
172
|
end
|
146
173
|
|
174
|
+
describe 'datetime' do
|
175
|
+
|
176
|
+
let(:formatter) { HammerCLI::Options::Normalizers::DateTime.new }
|
177
|
+
|
178
|
+
it "should raise argument error when the value is nil" do
|
179
|
+
proc { formatter.format(nil) }.must_raise ArgumentError
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should raise argument error when the value is not a date" do
|
183
|
+
proc { formatter.format("not a date") }.must_raise ArgumentError
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should accept and parse iso8601" do
|
187
|
+
formatter.format("1986-01-01T08:30:20").must_equal("1986-01-01T08:30:20+00:00")
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should accept and parse YYYY-MM-DD HH:MM:SS" do
|
191
|
+
formatter.format("1986-01-01 08:30:20").must_equal("1986-01-01T08:30:20+00:00")
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should accept and parse YYYY/MM/DD HH:MM:SS" do
|
195
|
+
formatter.format("1986/01/01 08:30:20").must_equal("1986-01-01T08:30:20+00:00")
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
147
200
|
end
|
148
201
|
|
@@ -2,24 +2,176 @@ require File.join(File.dirname(__FILE__), '../../test_helper')
|
|
2
2
|
|
3
3
|
describe HammerCLI::Output::Adapter::Base do
|
4
4
|
|
5
|
-
let(:
|
5
|
+
let(:context) {{}}
|
6
|
+
let(:adapter) { HammerCLI::Output::Adapter::Base.new(context, HammerCLI::Output::Output.formatters) }
|
6
7
|
|
7
8
|
context "print_collection" do
|
8
9
|
|
9
|
-
let(:
|
10
|
-
let(:
|
11
|
-
|
12
|
-
}
|
10
|
+
let(:id) { Fields::Id.new(:path => [:id], :label => "Id") }
|
11
|
+
let(:name) { Fields::Field.new(:path => [:name], :label => "Name") }
|
12
|
+
let(:unlabeled) { Fields::Field.new(:path => [:name]) }
|
13
|
+
let(:surname) { Fields::Field.new(:path => [:surname], :label => "Surname") }
|
14
|
+
let(:address_city) { Fields::Field.new(:path => [:address, :city], :label => "City") }
|
15
|
+
let(:city) { Fields::Field.new(:path => [:city], :label => "City") }
|
16
|
+
let(:label_address) { Fields::Label.new(:path => [:address], :label => "Address") }
|
17
|
+
let(:contacts) { Fields::Collection.new(:path => [:contacts], :label => "Contacts") }
|
18
|
+
let(:desc) { Fields::Field.new(:path => [:desc], :label => "Description") }
|
19
|
+
let(:contact) { Fields::Field.new(:path => [:contact], :label => "Contact") }
|
20
|
+
let(:params) { Fields::KeyValueList.new(:path => [:params], :label => "Parameters") }
|
21
|
+
let(:params_collection) { Fields::Collection.new(:path => [:params], :label => "Parameters") }
|
22
|
+
let(:param) { Fields::KeyValue.new(:path => nil, :label => nil) }
|
23
|
+
let(:blank) { Fields::Field.new(:path => [:blank], :label => "Blank", :hide_blank => true) }
|
24
|
+
|
13
25
|
let(:data) { HammerCLI::Output::RecordCollection.new [{
|
14
|
-
:
|
26
|
+
:id => 112,
|
27
|
+
:name => "John",
|
28
|
+
:surname => "Doe",
|
29
|
+
:address => {
|
30
|
+
:city => "New York"
|
31
|
+
},
|
32
|
+
:contacts => [
|
33
|
+
{
|
34
|
+
:desc => 'personal email',
|
35
|
+
:contact => 'john.doe@doughnut.com'
|
36
|
+
},
|
37
|
+
{
|
38
|
+
:desc => 'telephone',
|
39
|
+
:contact => '123456789'
|
40
|
+
}
|
41
|
+
],
|
42
|
+
:params => [
|
43
|
+
{
|
44
|
+
:name => 'weight',
|
45
|
+
:value => '83'
|
46
|
+
},
|
47
|
+
{
|
48
|
+
:name => 'size',
|
49
|
+
:value => '32'
|
50
|
+
}
|
51
|
+
]
|
15
52
|
}]}
|
16
53
|
|
17
|
-
it "should print field
|
18
|
-
|
54
|
+
it "should print one field" do
|
55
|
+
fields = [name]
|
56
|
+
expected_output = [
|
57
|
+
"Name: John",
|
58
|
+
"\n"
|
59
|
+
].join("\n")
|
60
|
+
|
61
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "doesn't print label when it's nil" do
|
65
|
+
fields = [unlabeled]
|
66
|
+
expected_output = [
|
67
|
+
"John",
|
68
|
+
"\n"
|
69
|
+
].join("\n")
|
70
|
+
|
71
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "aligns multiple fields" do
|
75
|
+
fields = [name, surname, unlabeled]
|
76
|
+
expected_output = [
|
77
|
+
"Name: John",
|
78
|
+
"Surname: Doe",
|
79
|
+
"John",
|
80
|
+
"\n"
|
81
|
+
].join("\n")
|
82
|
+
|
83
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should field with nested data" do
|
87
|
+
fields = [address_city]
|
88
|
+
expected_output = [
|
89
|
+
"City: New York",
|
90
|
+
"\n"
|
91
|
+
].join("\n")
|
92
|
+
|
93
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should print labeled fields" do
|
97
|
+
label_address.output_definition.append [city]
|
98
|
+
fields = [label_address]
|
99
|
+
|
100
|
+
expected_output = [
|
101
|
+
"Address: ",
|
102
|
+
" City: New York",
|
103
|
+
"\n"
|
104
|
+
].join("\n")
|
105
|
+
|
106
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
it "should print collection" do
|
111
|
+
contacts.output_definition.append [desc, contact]
|
112
|
+
fields = [contacts]
|
113
|
+
|
114
|
+
expected_output = [
|
115
|
+
"Contacts: ",
|
116
|
+
" 1) Description: personal email",
|
117
|
+
" Contact: john.doe@doughnut.com",
|
118
|
+
" 2) Description: telephone",
|
119
|
+
" Contact: 123456789",
|
120
|
+
"\n"
|
121
|
+
].join("\n")
|
122
|
+
|
123
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "hides ids by default" do
|
127
|
+
fields = [id, name]
|
128
|
+
expected_output = [
|
129
|
+
"Name: John",
|
130
|
+
"\n"
|
131
|
+
].join("\n")
|
132
|
+
|
133
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "skips blank values" do
|
137
|
+
fields = [name, blank]
|
138
|
+
expected_output = [
|
139
|
+
"Name: John",
|
140
|
+
"\n"
|
141
|
+
].join("\n")
|
142
|
+
|
143
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
19
144
|
end
|
20
145
|
|
21
|
-
it "should print
|
22
|
-
|
146
|
+
it "should print key -> value" do
|
147
|
+
params_collection.output_definition.append [param]
|
148
|
+
fields = [params_collection]
|
149
|
+
|
150
|
+
expected_output = [
|
151
|
+
"Parameters: ",
|
152
|
+
" 1) weight => 83",
|
153
|
+
" 2) size => 32",
|
154
|
+
"\n"
|
155
|
+
].join("\n")
|
156
|
+
|
157
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
158
|
+
end
|
159
|
+
|
160
|
+
context "show ids" do
|
161
|
+
|
162
|
+
let(:context) { {:show_ids => true} }
|
163
|
+
|
164
|
+
it "shows ids if it's required in the context" do
|
165
|
+
fields = [id, name]
|
166
|
+
expected_output = [
|
167
|
+
"Id: 112",
|
168
|
+
"Name: John",
|
169
|
+
"\n"
|
170
|
+
].join("\n")
|
171
|
+
|
172
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
173
|
+
end
|
174
|
+
|
23
175
|
end
|
24
176
|
|
25
177
|
end
|
@@ -6,8 +6,8 @@ describe HammerCLI::Output::Adapter::CSValues do
|
|
6
6
|
|
7
7
|
context "print_collection" do
|
8
8
|
|
9
|
-
let(:field_name) { Fields::
|
10
|
-
let(:field_started_at) { Fields::
|
9
|
+
let(:field_name) { Fields::Field.new(:path => [:name], :label => "Name") }
|
10
|
+
let(:field_started_at) { Fields::Field.new(:path => [:started_at], :label => "Started At") }
|
11
11
|
let(:fields) {
|
12
12
|
[field_name, field_started_at]
|
13
13
|
}
|
@@ -52,10 +52,23 @@ describe HammerCLI::Output::Adapter::CSValues do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
adapter = HammerCLI::Output::Adapter::CSValues.new({}, { :
|
55
|
+
adapter = HammerCLI::Output::Adapter::CSValues.new({}, { :Field => [ DotFormatter.new ]})
|
56
56
|
out, err = capture_io { adapter.print_collection(fields, data) }
|
57
57
|
out.must_match(/.*-DOT-.*/)
|
58
58
|
end
|
59
|
+
|
60
|
+
it "should not replace nil with empty string before it applies formatters" do
|
61
|
+
class NilFormatter < HammerCLI::Output::Formatters::FieldFormatter
|
62
|
+
def format(data)
|
63
|
+
'NIL' if data.nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
adapter = HammerCLI::Output::Adapter::CSValues.new({}, { :Field => [ NilFormatter.new ]})
|
68
|
+
nil_data = HammerCLI::Output::RecordCollection.new [{ :name => nil }]
|
69
|
+
out, err = capture_io { adapter.print_collection([field_name], nil_data) }
|
70
|
+
out.must_match(/.*NIL.*/)
|
71
|
+
end
|
59
72
|
end
|
60
73
|
end
|
61
74
|
|
@@ -6,12 +6,20 @@ describe HammerCLI::Output::Adapter::Table do
|
|
6
6
|
|
7
7
|
context "print_collection" do
|
8
8
|
|
9
|
-
let(:field_name) { Fields::
|
9
|
+
let(:field_name) { Fields::Field.new(:path => [:fullname], :label => "Name") }
|
10
|
+
let(:field_firstname) { Fields::Field.new(:path => [:firstname], :label => "Firstname") }
|
11
|
+
let(:field_lastname) { Fields::Field.new(:path => [:lastname], :label => "Lastname") }
|
12
|
+
|
10
13
|
let(:fields) {
|
11
14
|
[field_name]
|
12
15
|
}
|
16
|
+
|
13
17
|
let(:data) { HammerCLI::Output::RecordCollection.new [{
|
14
|
-
:
|
18
|
+
:id => 1,
|
19
|
+
:firstname => "John",
|
20
|
+
:lastname => "Doe",
|
21
|
+
:fullname => "John Doe",
|
22
|
+
:long => "SomeVeryLongString"
|
15
23
|
}]}
|
16
24
|
|
17
25
|
it "should print column name " do
|
@@ -40,6 +48,74 @@ describe HammerCLI::Output::Adapter::Table do
|
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
51
|
+
context "column width" do
|
52
|
+
|
53
|
+
it "truncates string when it exceeds maximum width" do
|
54
|
+
first_field = Fields::Field.new(:path => [:long], :label => "Long", :max_width => 10)
|
55
|
+
fields = [first_field, field_lastname]
|
56
|
+
|
57
|
+
expected_output = [
|
58
|
+
"-----------|---------",
|
59
|
+
"LONG | LASTNAME",
|
60
|
+
"-----------|---------",
|
61
|
+
"SomeVer... | Doe ",
|
62
|
+
"-----------|---------",
|
63
|
+
""
|
64
|
+
].join("\n")
|
65
|
+
|
66
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "truncates string when it exceeds width" do
|
70
|
+
first_field = Fields::Field.new(:path => [:long], :label => "Long", :width => 10)
|
71
|
+
fields = [first_field, field_lastname]
|
72
|
+
|
73
|
+
expected_output = [
|
74
|
+
"-----------|---------",
|
75
|
+
"LONG | LASTNAME",
|
76
|
+
"-----------|---------",
|
77
|
+
"SomeVer... | Doe ",
|
78
|
+
"-----------|---------",
|
79
|
+
""
|
80
|
+
].join("\n")
|
81
|
+
|
82
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "sets certain width" do
|
86
|
+
first_field = Fields::Field.new(:path => [:long], :label => "Long", :width => 25)
|
87
|
+
fields = [first_field, field_lastname]
|
88
|
+
|
89
|
+
expected_output = [
|
90
|
+
"--------------------------|---------",
|
91
|
+
"LONG | LASTNAME",
|
92
|
+
"--------------------------|---------",
|
93
|
+
"SomeVeryLongString | Doe ",
|
94
|
+
"--------------------------|---------",
|
95
|
+
""
|
96
|
+
].join("\n")
|
97
|
+
|
98
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "gives preference to width over maximal width" do
|
102
|
+
first_field = Fields::Field.new(:path => [:long], :label => "Long", :width => 25, :max_width => 10)
|
103
|
+
fields = [first_field, field_lastname]
|
104
|
+
|
105
|
+
expected_output = [
|
106
|
+
"--------------------------|---------",
|
107
|
+
"LONG | LASTNAME",
|
108
|
+
"--------------------------|---------",
|
109
|
+
"SomeVeryLongString | Doe ",
|
110
|
+
"--------------------------|---------",
|
111
|
+
""
|
112
|
+
].join("\n")
|
113
|
+
|
114
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
43
119
|
context "formatters" do
|
44
120
|
it "should apply formatters" do
|
45
121
|
class DotFormatter < HammerCLI::Output::Formatters::FieldFormatter
|
@@ -48,28 +124,36 @@ describe HammerCLI::Output::Adapter::Table do
|
|
48
124
|
end
|
49
125
|
end
|
50
126
|
|
51
|
-
adapter = HammerCLI::Output::Adapter::Table.new({}, { :
|
127
|
+
adapter = HammerCLI::Output::Adapter::Table.new({}, { :Field => [ DotFormatter.new ]})
|
52
128
|
out, err = capture_io { adapter.print_collection(fields, data) }
|
53
129
|
out.must_match(/.*-DOT-.*/)
|
54
130
|
end
|
55
131
|
end
|
56
132
|
|
57
133
|
context "sort_columns" do
|
58
|
-
let(:field_firstname) { Fields::DataField.new(:path => [:firstname], :label => "Firstname") }
|
59
|
-
let(:field_lastname) { Fields::DataField.new(:path => [:lastname], :label => "Lastname") }
|
60
134
|
let(:fields) {
|
61
135
|
[field_firstname, field_lastname]
|
62
136
|
}
|
63
|
-
let(:data) { HammerCLI::Output::RecordCollection.new [{
|
64
|
-
:firstname => "John",
|
65
|
-
:lastname => "Doe"
|
66
|
-
}]}
|
67
137
|
|
68
138
|
it "should sort output" do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
"
|
139
|
+
|
140
|
+
table_print_output = [
|
141
|
+
"LASTNAME | FIRSTNAME",
|
142
|
+
"---------|----------",
|
143
|
+
"Doe | John "
|
144
|
+
].join("\n")
|
145
|
+
|
146
|
+
expected_output = [
|
147
|
+
"----------|---------",
|
148
|
+
"FIRSTNAME | LASTNAME",
|
149
|
+
"----------|---------",
|
150
|
+
"John | Doe ",
|
151
|
+
"----------|---------",
|
152
|
+
""
|
153
|
+
].join("\n")
|
154
|
+
|
155
|
+
TablePrint::Printer.any_instance.stubs(:table_print).returns(table_print_output)
|
156
|
+
proc { adapter.print_collection(fields, data) }.must_output(expected_output)
|
73
157
|
end
|
74
158
|
end
|
75
159
|
end
|