table_print 0.2.3 → 1.0.0.rc3

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.
@@ -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