table_print 0.2.3 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'column'
3
+
4
+ include TablePrint
5
+
6
+ describe Column do
7
+ let(:c) {Column.new(:data => ["Once upon a time", "there was a dark and stormy night"], :name => :tagline)}
8
+
9
+ it "remembers its name as a string" do
10
+ c.name.should == "tagline"
11
+ end
12
+
13
+ it "exposes the array of data representing the column" do
14
+ c.data.should == ["Once upon a time", "there was a dark and stormy night"]
15
+ end
16
+
17
+ describe "#add_formatter" do
18
+ it "stores the formatter" do
19
+ f = {}
20
+ c.add_formatter(f)
21
+ c.formatters.should == [f]
22
+ end
23
+ end
24
+
25
+ describe "#formatter=" do
26
+ it "adds the formatters individually" do
27
+ c.should_receive(:add_formatter).twice
28
+ c.formatters = [{}, {}]
29
+ end
30
+ end
31
+
32
+ describe "#display_method" do
33
+ it "stores the column's display method as a string" do
34
+ c = Column.new(:display_method => :boofar)
35
+ c.display_method.should == "boofar"
36
+ end
37
+
38
+ it "doesn't turn a lambda display method into a string" do
39
+ lam = lambda{}
40
+ c = Column.new(:display_method => lam)
41
+ c.display_method.should == lam
42
+ end
43
+
44
+ it "defaults to the column name" do
45
+ c = Column.new(:name => :boofar)
46
+ c.display_method.should == "boofar"
47
+ end
48
+ end
49
+
50
+ describe "#data_width" do
51
+ it "reflects the width of the data set" do
52
+ c.data_width.should == 33
53
+ end
54
+
55
+ it "includes the title in the calculation" do
56
+ c.name = "a horse is a horse of course of course"
57
+ c.data_width.should == 38
58
+ end
59
+ end
60
+
61
+ describe "#width" do
62
+ it "returns the specified width" do
63
+ c.width = 14
64
+ c.width.should == 14
65
+ end
66
+
67
+ it "uses the data_width if no width has been set" do
68
+ c.width.should == 33
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,236 @@
1
+ require 'spec_helper'
2
+ require 'config_resolver'
3
+
4
+ describe TablePrint::ConfigResolver do
5
+
6
+ #it "starts with the specified config" do
7
+ # Sandbox.add_class("Configged")
8
+ # TablePrint::Config.set(Sandbox::Configged, [:title, :author])
9
+ # c = TablePrint::ConfigResolver.new(Object, Object, [:name])
10
+ # c.columns.length.should == 2
11
+ # c.columns.first.name.should == 'title'
12
+ # c.columns.last.name.should == 'author'
13
+ #end
14
+
15
+ describe "#get_and_remove" do
16
+ it "deletes and returns the :except key from an array" do
17
+ c = TablePrint::ConfigResolver.new(Object, [])
18
+ options = [:title, :author, {:except => [:title]}]
19
+ c.get_and_remove(options, :except).should == [:title]
20
+ options.should == [:title, :author]
21
+ end
22
+
23
+ it "deletes and returns the :except key from an array with an :include key" do
24
+ c = TablePrint::ConfigResolver.new(Object, [])
25
+ options = [:title, {:except => [:title]}, {:include => [:author]}]
26
+ c.get_and_remove(options, :except).should == [:title]
27
+ options.should == [:title, {:include => [:author]}]
28
+ end
29
+
30
+ it "deletes and returns the :except key from a hash with an :include key" do
31
+ c = TablePrint::ConfigResolver.new(Object, [])
32
+ options = [:title, {:except => [:title], :include => [:author]}]
33
+ c.get_and_remove(options, :except).should == [:title]
34
+ options.should == [:title, {:include => [:author]}]
35
+ end
36
+
37
+ it "deletes and returns both the :include and :except keys" do
38
+ c = TablePrint::ConfigResolver.new(Object, [])
39
+ options = [:title, {:except => [:title]}, {:include => [:author]}]
40
+ c.get_and_remove(options, :include).should == [:author]
41
+ c.get_and_remove(options, :except).should == [:title]
42
+ options.should == [:title]
43
+ end
44
+
45
+ it "works even if the array doesn't have an exception hash" do
46
+ c = TablePrint::ConfigResolver.new(Object, [])
47
+ options = [:title, :author]
48
+ c.get_and_remove(options, :except).should == []
49
+ options.should == [:title, :author]
50
+ end
51
+ end
52
+
53
+ describe ":only" do
54
+ context "with a symbol" do
55
+ it "returns a column named foo" do
56
+ c = TablePrint::ConfigResolver.new(Object, [:title], :foo)
57
+ c.columns.length.should == 1
58
+ c.columns.first.name.should == 'foo'
59
+ end
60
+ end
61
+ context "with a string" do
62
+ it "returns a column named foo" do
63
+ c = TablePrint::ConfigResolver.new(Object, [:title], 'foo')
64
+ c.columns.length.should == 1
65
+ c.columns.first.name.should == 'foo'
66
+ end
67
+ end
68
+ context "with an array of symbols and strings" do
69
+ it "returns columns named foo and bar" do
70
+ c = TablePrint::ConfigResolver.new(Object, [:title], :foo, 'bar')
71
+ c.columns.length.should == 2
72
+ c.columns.first.name.should == 'foo'
73
+ c.columns.last.name.should == 'bar'
74
+ end
75
+ end
76
+ end
77
+
78
+ describe ":include" do
79
+ context "with a symbol" do
80
+ it "adds foo to the list of methods" do
81
+ c = TablePrint::ConfigResolver.new(Object, [:title], :include => :foo)
82
+ c.columns.length.should == 2
83
+ c.columns.first.name.should == 'title'
84
+ c.columns.last.name.should == 'foo'
85
+ end
86
+ end
87
+
88
+ context "with an array" do
89
+ it "adds foo and bar to the list of methods" do
90
+ c = TablePrint::ConfigResolver.new(Object, [:title], :include => [:foo, :bar])
91
+ c.columns.length.should == 3
92
+ c.columns.first.name.should == 'title'
93
+ c.columns.last.name.should == 'bar'
94
+ end
95
+ end
96
+
97
+ context "with options" do
98
+ it "adds foo to the list of methods and remembers its options" do
99
+ c = TablePrint::ConfigResolver.new(Object, [:title], :include => {:foo => {:width => 10}})
100
+ c.columns.length.should == 2
101
+ c.columns.first.name.should == 'title'
102
+
103
+ c.columns.last.name.should == 'foo'
104
+ c.columns.last.width.should == 10
105
+ end
106
+ end
107
+ end
108
+
109
+ describe ":except" do
110
+ context "with a symbol" do
111
+ it "removes foo from the list of methods" do
112
+ c = TablePrint::ConfigResolver.new(Object, [:title, :foo], :except => :foo)
113
+ c.columns.length.should == 1
114
+ c.columns.first.name.should == 'title'
115
+ end
116
+ end
117
+ context "with an array" do
118
+ it "removes foo and bar from the list of methods" do
119
+ c = TablePrint::ConfigResolver.new(Object, [:title, :foo, :bar], :except => [:foo, 'bar'])
120
+ c.columns.length.should == 1
121
+ c.columns.first.name.should == 'title'
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "lambdas" do
127
+ it "uses the key as the name and the lambda as the display method" do
128
+ lam = lambda {}
129
+ c = TablePrint::ConfigResolver.new(Object, [:title], :foo => {:display_method => lam})
130
+ c.columns.length.should == 1
131
+ c.columns.first.name.should == 'foo'
132
+ c.columns.first.display_method.should == lam
133
+ end
134
+
135
+ context "without the display_method keyword" do
136
+ it "uses the key as the name and the lambda as the display method" do
137
+ lam = lambda {}
138
+ c = TablePrint::ConfigResolver.new(Object, [:title], :foo => lam)
139
+ c.columns.length.should == 1
140
+ c.columns.first.name.should == 'foo'
141
+ c.columns.first.display_method.should == lam
142
+ end
143
+ end
144
+ end
145
+
146
+ describe "#usable_column_names" do
147
+ it "returns default columns" do
148
+ c = TablePrint::ConfigResolver.new(Object, [:title])
149
+ c.usable_column_names.should == ['title']
150
+ end
151
+
152
+ it "returns specified columns instead of default columns" do
153
+ c = TablePrint::ConfigResolver.new(Object, [:title], [:author])
154
+ c.usable_column_names.should == ['author']
155
+ end
156
+
157
+ it "applies includes on top of default columns" do
158
+ c = TablePrint::ConfigResolver.new(Object, [:title], [:include => :author])
159
+ c.usable_column_names.should == ['title', 'author']
160
+ end
161
+
162
+ it "applies includes on top of specified columns" do
163
+ c = TablePrint::ConfigResolver.new(Object, [:title], [:author, {:include => :pub_date}])
164
+ c.usable_column_names.should == ['author', 'pub_date']
165
+ end
166
+
167
+ it "applies excepts on top of default columns" do
168
+ c = TablePrint::ConfigResolver.new(Object, [:title, :author], [:except => :author])
169
+ c.usable_column_names.should == ['title']
170
+ end
171
+
172
+ it "applies excepts on top of specified columns" do
173
+ c = TablePrint::ConfigResolver.new(Object, [:title, :author], [:pub_date, :length, {:except => :length}])
174
+ c.usable_column_names.should == ['pub_date']
175
+ end
176
+
177
+ it "applies both includes and excepts on top of specified columns" do
178
+ c = TablePrint::ConfigResolver.new(Object, [:title, :author], [:pub_date, :length, {:except => :length, :include => :foobar}])
179
+ c.usable_column_names.should == ['pub_date', 'foobar']
180
+ end
181
+ end
182
+
183
+ describe "column options" do
184
+ context "display_method" do
185
+ it "sets the display method on the column" do
186
+ c = TablePrint::ConfigResolver.new(Object, [:title], :title => {:display_method => :boofar})
187
+ c.columns.length.should == 1
188
+ c.columns.first.name.should == 'title'
189
+ c.columns.first.display_method.should == "boofar"
190
+ end
191
+ end
192
+ context "width" do
193
+ it "sets the width" do
194
+ c = TablePrint::ConfigResolver.new(Object, [:title], :title => {:width => 100})
195
+ c.columns.length.should == 1
196
+ c.columns.first.name.should == 'title'
197
+ c.columns.first.width.should == 100
198
+ end
199
+ end
200
+ context "formatters" do
201
+ it "adds the formatters to the column" do
202
+ f1 = {}
203
+ f2 = {}
204
+ c = TablePrint::ConfigResolver.new(Object, [:title], :title => {:formatters => [f1, f2]})
205
+ c.columns.length.should == 1
206
+ c.columns.first.name.should == 'title'
207
+ c.columns.first.formatters.should == [f1, f2]
208
+ end
209
+ end
210
+ end
211
+
212
+ describe "#option_to_column" do
213
+ context "with a symbol" do
214
+ it "returns a column named foo" do
215
+ c = TablePrint::ConfigResolver.new(Object, [])
216
+ column = c.option_to_column(:foo)
217
+ column.name.should == 'foo'
218
+ end
219
+ end
220
+ context "with a string" do
221
+ it "returns a column named foo" do
222
+ c = TablePrint::ConfigResolver.new(Object, [])
223
+ column = c.option_to_column('foo')
224
+ column.name.should == 'foo'
225
+ end
226
+ end
227
+ context "with a hash" do
228
+ it "returns a column named foo and the specified options" do
229
+ c = TablePrint::ConfigResolver.new(Object, [])
230
+ column = c.option_to_column({:foo => {:width => 10}})
231
+ column.name.should == 'foo'
232
+ column.width.should == 10
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'config'
3
+
4
+ describe TablePrint::Config do
5
+ it "defaults max_width to 30" do
6
+ TablePrint::Config.max_width.should == 30
7
+ end
8
+
9
+ it "defaults time_format to year-month-day-hour-minute-second" do
10
+ TablePrint::Config.time_format.should == "%Y-%m-%d %H:%M:%S"
11
+ end
12
+
13
+ describe "individual config options" do
14
+ describe "storing and retrieving" do
15
+ it "sets the variable" do
16
+ TablePrint::Config.set(:max_width, [10])
17
+ TablePrint::Config.max_width.should == 10
18
+ TablePrint::Config.set(:max_width, [30])
19
+ end
20
+ end
21
+
22
+ describe "clearing" do
23
+ it "resets the variable to its initial value" do
24
+ TablePrint::Config.set(:max_width, [10])
25
+ TablePrint::Config.clear(:max_width)
26
+ TablePrint::Config.max_width.should == 30
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "class-based column config" do
32
+ before :all do
33
+ Sandbox.add_class("Blog")
34
+ end
35
+
36
+ describe "storing and retrieving" do
37
+ it "stores the column hash" do
38
+ TablePrint::Config.set(Sandbox::Blog, [:title, :author])
39
+ TablePrint::Config.for(Sandbox::Blog).should == [:title, :author]
40
+ end
41
+ end
42
+
43
+ describe "clearing" do
44
+ it "removes the class from storage" do
45
+ TablePrint::Config.set(Sandbox::Blog, [:title, :author])
46
+ TablePrint::Config.clear(Sandbox::Blog)
47
+ TablePrint::Config.for(Sandbox::Blog).should be_nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+ require 'fingerprinter'
4
+ require 'column'
5
+
6
+ class TablePrint::Row
7
+ attr_accessor :groups, :cells
8
+ end
9
+
10
+ include TablePrint
11
+
12
+ describe Fingerprinter do
13
+
14
+ before(:each) do
15
+ Sandbox.cleanup!
16
+ end
17
+
18
+ describe "#lift" do
19
+ it "turns a single level of columns into a single row" do
20
+ rows = Fingerprinter.new.lift([Column.new(:name => "name")], OpenStruct.new(:name => "dale carnegie"))
21
+ rows.length.should == 1
22
+ row = rows.first
23
+ row.children.length.should == 0
24
+ row.cells.should == {'name' => "dale carnegie"}
25
+ end
26
+
27
+ it "uses the display_method to get the data" do
28
+ rows = Fingerprinter.new.lift([Column.new(:name => "name of work", :display_method => "title")], OpenStruct.new(:title => "of mice and men"))
29
+ rows.length.should == 1
30
+ row = rows.first
31
+ row.children.length.should == 0
32
+ row.cells.should == {'name of work' => "of mice and men"}
33
+ end
34
+
35
+ it "turns multiple levels of columns into multiple rows" do
36
+ rows = Fingerprinter.new.lift([Column.new(:name => "name"), Column.new(:name => "books.title")], OpenStruct.new(:name => "dale carnegie", :books => [OpenStruct.new(:title => "how to make influences")]))
37
+ rows.length.should == 1
38
+ row = rows.first
39
+ row.children.length.should == 1
40
+ row.cells.should == {'name' => "dale carnegie"}
41
+ row.children.first.children.first.cells.should == {'books.title' => "how to make influences"}
42
+ end
43
+
44
+ it "doesn't choke if an association doesn't exist" do
45
+ rows = Fingerprinter.new.lift([Column.new(:name => "name"), Column.new(:name => "books.title")], OpenStruct.new(:name => "dale carnegie", :books => []))
46
+
47
+ rows.length.should == 1
48
+
49
+ row = rows.first
50
+ row.children.length.should == 0
51
+ end
52
+
53
+ it "allows a lambda as the display_method" do
54
+ rows = Fingerprinter.new.lift([Column.new(:name => "name", :display_method => lambda { |row| row.name.gsub(/[aeiou]/, "") })], OpenStruct.new(:name => "dale carnegie"))
55
+ rows.length.should == 1
56
+ row = rows.first
57
+ row.children.length.should == 0
58
+ row.cells.should == {'name' => "dl crng"}
59
+ end
60
+ end
61
+
62
+ describe "#hash_to_rows" do
63
+ it "uses hashes with empty values as column names" do
64
+ f = Fingerprinter.new
65
+ f.instance_variable_set("@column_names_by_display_method", {"name" => "name"})
66
+ rows = f.hash_to_rows("", {'name' => {}}, OpenStruct.new(:name => "dale carnegie"))
67
+ rows.length.should == 1
68
+ row = rows.first
69
+ row.children.length.should == 0
70
+ row.cells.should == {'name' => 'dale carnegie'}
71
+ end
72
+
73
+ it 'recurses for subsequent levels of hash' do
74
+ f = Fingerprinter.new
75
+ f.instance_variable_set("@column_names_by_display_method", {"name" => "name", "books.title" => "books.title"})
76
+ rows = f.hash_to_rows("", {'name' => {}, 'books' => {'title' => {}}}, [OpenStruct.new(:name => 'dale carnegie', :books => [OpenStruct.new(:title => "hallmark")])])
77
+ rows.length.should == 1
78
+
79
+ top_row = rows.first
80
+ top_row.cells.should == {'name' => 'dale carnegie'}
81
+ top_row.children.length.should == 1
82
+ top_row.children.first.child_count.should == 1
83
+
84
+ bottom_row = top_row.children.first.children.first
85
+ bottom_row.cells.should == {'books.title' => 'hallmark'}
86
+ end
87
+ end
88
+
89
+ describe "#populate_row" do
90
+ it "fills a row by calling methods on the target object" do
91
+ f = Fingerprinter.new
92
+ f.instance_variable_set("@column_names_by_display_method", {"title" => "title", "author" => "author"})
93
+ row = f.populate_row("", {'title' => {}, 'author' => {}, 'publisher' => {'address' => {}}}, OpenStruct.new(:title => "foobar", :author => "bobby"))
94
+ row.cells.should == {'title' => "foobar", 'author' => 'bobby'}
95
+ end
96
+
97
+ it "uses the provided prefix to name the cells" do
98
+ f = Fingerprinter.new
99
+ f.instance_variable_set("@column_names_by_display_method", {"bar.title" => "bar.title", "bar.author" => "bar.author"})
100
+ row = f.populate_row("bar", {'title' => {}, 'author' => {}, 'publisher' => {'address' => {}}}, OpenStruct.new(:title => "foobar", :author => "bobby"))
101
+ row.cells.should == {'bar.title' => "foobar", 'bar.author' => 'bobby'}
102
+ end
103
+
104
+ it "uses the column name as the cell name but uses the display method to get the value" do
105
+ f = Fingerprinter.new
106
+ f.instance_variable_set("@column_names_by_display_method", {"bar.title" => "title", "bar.author" => "bar.author"})
107
+ row = f.populate_row("bar", {'title' => {}, 'author' => {}, 'publisher' => {'address' => {}}}, OpenStruct.new(:title => "foobar", :author => "bobby"))
108
+ row.cells.should == {'title' => "foobar", 'bar.author' => 'bobby'}
109
+ end
110
+ end
111
+
112
+ describe "#create_child_group" do
113
+ it "adds the next level of column information to the prefix" do
114
+ f = Fingerprinter.new
115
+ books = []
116
+
117
+ f.should_receive(:hash_to_rows).with("author.books", {'title' => {}}, books).and_return([])
118
+ groups = f.create_child_group("author", {'books' => {'title' => {}}}, OpenStruct.new(:name => "bobby", :books => books))
119
+ groups.length.should == 1
120
+ groups.first.should be_a TablePrint::RowGroup
121
+ end
122
+ end
123
+
124
+ describe "#columns_to_handle" do
125
+ it "returns hash keys that have an empty hash as the value" do
126
+ Fingerprinter.new.handleable_columns({'name' => {}, 'books' => {'title' => {}}}).should == ["name"]
127
+ end
128
+ end
129
+
130
+ describe "#columns_to_pass" do
131
+ it "returns hash keys that do not have an empty hash as the value" do
132
+ Fingerprinter.new.passable_columns({'name' => {}, 'books' => {'title' => {}}}).should == ["books"]
133
+ end
134
+ end
135
+
136
+ describe "#chain_to_nested_hash" do
137
+ it "turns a list of methods into a nested hash" do
138
+ Fingerprinter.new.display_method_to_nested_hash("books").should == {'books' => {}}
139
+ Fingerprinter.new.display_method_to_nested_hash("reviews.user").should == {'reviews' => {'user' => {}}}
140
+ end
141
+ end
142
+
143
+ describe "#columns_to_nested_hash" do
144
+ it "splits the column names into a nested hash" do
145
+ Fingerprinter.new.display_methods_to_nested_hash(["books.name"]).should == {'books' => {'name' => {}}}
146
+ Fingerprinter.new.display_methods_to_nested_hash(
147
+ ["books.name", "books.publisher", "reviews.rating", "reviews.user.email", "reviews.user.id"]
148
+ ).should == {'books' => {'name' => {}, 'publisher' => {}}, 'reviews' => {'rating' => {}, 'user' => {'email' => {}, 'id' => {}}}}
149
+ end
150
+ end
151
+ end