1#!/usr/bin/env ruby -w
2# encoding: UTF-8
3
4# tc_headers.rb
5#
6#  Created by James Edward Gray II on 2005-10-31.
7#  Copyright 2005 James Edward Gray II. You can redistribute or modify this code
8#  under the terms of Ruby's license.
9
10require_relative "base"
11
12class TestCSV::Headers < TestCSV
13  extend DifferentOFS
14
15  def setup
16    super
17    @data = <<-END_CSV.gsub(/^\s+/, "")
18    first,second,third
19    A,B,C
20    1,2,3
21    END_CSV
22  end
23
24  def test_first_row
25    [:first_row, true].each do |setting|  # two names for the same setting
26      # activate headers
27      csv = nil
28      assert_nothing_raised(Exception) do
29        csv = CSV.parse(@data, headers: setting)
30      end
31
32      # first data row - skipping headers
33      row = csv[0]
34      assert_not_nil(row)
35      assert_instance_of(CSV::Row, row)
36      assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
37
38      # second data row
39      row = csv[1]
40      assert_not_nil(row)
41      assert_instance_of(CSV::Row, row)
42      assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
43
44      # empty
45      assert_nil(csv[2])
46    end
47  end
48
49  def test_array_of_headers
50    # activate headers
51    csv = nil
52    assert_nothing_raised(Exception) do
53      csv = CSV.parse(@data, headers: [:my, :new, :headers])
54    end
55
56    # first data row - skipping headers
57    row = csv[0]
58    assert_not_nil(row)
59    assert_instance_of(CSV::Row, row)
60    assert_equal( [[:my, "first"], [:new, "second"], [:headers, "third"]],
61                  row.to_a )
62
63    # second data row
64    row = csv[1]
65    assert_not_nil(row)
66    assert_instance_of(CSV::Row, row)
67    assert_equal([[:my, "A"], [:new, "B"], [:headers, "C"]], row.to_a)
68
69    # third data row
70    row = csv[2]
71    assert_not_nil(row)
72    assert_instance_of(CSV::Row, row)
73    assert_equal([[:my, "1"], [:new, "2"], [:headers, "3"]], row.to_a)
74
75    # empty
76    assert_nil(csv[3])
77
78    # with return and convert
79    assert_nothing_raised(Exception) do
80      csv = CSV.parse( @data, headers:           [:my, :new, :headers],
81                              return_headers:    true,
82                              header_converters: lambda { |h| h.to_s } )
83    end
84    row = csv[0]
85    assert_not_nil(row)
86    assert_instance_of(CSV::Row, row)
87    assert_equal([["my", :my], ["new", :new], ["headers", :headers]], row.to_a)
88    assert(row.header_row?)
89    assert(!row.field_row?)
90  end
91
92  def test_csv_header_string
93    # activate headers
94    csv = nil
95    assert_nothing_raised(Exception) do
96      csv = CSV.parse(@data, headers: "my,new,headers")
97    end
98
99    # first data row - skipping headers
100    row = csv[0]
101    assert_not_nil(row)
102    assert_instance_of(CSV::Row, row)
103    assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
104
105    # second data row
106    row = csv[1]
107    assert_not_nil(row)
108    assert_instance_of(CSV::Row, row)
109    assert_equal([%w{my A}, %w{new B}, %w{headers C}], row.to_a)
110
111    # third data row
112    row = csv[2]
113    assert_not_nil(row)
114    assert_instance_of(CSV::Row, row)
115    assert_equal([%w{my 1}, %w{new 2}, %w{headers 3}], row.to_a)
116
117    # empty
118    assert_nil(csv[3])
119
120    # with return and convert
121    assert_nothing_raised(Exception) do
122      csv = CSV.parse( @data, headers:           "my,new,headers",
123                              return_headers:    true,
124                              header_converters: :symbol )
125    end
126    row = csv[0]
127    assert_not_nil(row)
128    assert_instance_of(CSV::Row, row)
129    assert_equal([[:my, "my"], [:new, "new"], [:headers, "headers"]], row.to_a)
130    assert(row.header_row?)
131    assert(!row.field_row?)
132  end
133
134  def test_csv_header_string_inherits_separators
135    # parse with custom col_sep
136    csv = nil
137    assert_nothing_raised(Exception) do
138      csv = CSV.parse( @data.tr(",", "|"), col_sep: "|",
139                                           headers: "my|new|headers" )
140    end
141
142    # verify headers were recognized
143    row = csv[0]
144    assert_not_nil(row)
145    assert_instance_of(CSV::Row, row)
146    assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
147  end
148
149  def test_return_headers
150    # activate headers and request they are returned
151    csv = nil
152    assert_nothing_raised(Exception) do
153      csv = CSV.parse(@data, headers: true, return_headers: true)
154    end
155
156    # header row
157    row = csv[0]
158    assert_not_nil(row)
159    assert_instance_of(CSV::Row, row)
160    assert_equal( [%w{first first}, %w{second second}, %w{third third}],
161                  row.to_a )
162    assert(row.header_row?)
163    assert(!row.field_row?)
164
165    # first data row - skipping headers
166    row = csv[1]
167    assert_not_nil(row)
168    assert_instance_of(CSV::Row, row)
169    assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
170    assert(!row.header_row?)
171    assert(row.field_row?)
172
173    # second data row
174    row = csv[2]
175    assert_not_nil(row)
176    assert_instance_of(CSV::Row, row)
177    assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
178    assert(!row.header_row?)
179    assert(row.field_row?)
180
181    # empty
182    assert_nil(csv[3])
183  end
184
185  def test_converters
186    # create test data where headers and fields look alike
187    data = <<-END_MATCHING_CSV.gsub(/^\s+/, "")
188    1,2,3
189    1,2,3
190    END_MATCHING_CSV
191
192    # normal converters do not affect headers
193    csv = CSV.parse( data, headers:        true,
194                           return_headers: true,
195                           converters:     :numeric )
196    assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv[0].to_a)
197    assert_equal([["1", 1], ["2", 2], ["3", 3]], csv[1].to_a)
198    assert_nil(csv[2])
199
200    # header converters do affect headers (only)
201    assert_nothing_raised(Exception) do
202      csv = CSV.parse( data, headers:           true,
203                             return_headers:    true,
204                             converters:        :numeric,
205                             header_converters: :symbol )
206    end
207    assert_equal([[:"1", "1"], [:"2", "2"], [:"3", "3"]], csv[0].to_a)
208    assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv[1].to_a)
209    assert_nil(csv[2])
210  end
211
212  def test_builtin_downcase_converter
213    csv = CSV.parse( "One,TWO Three", headers:           true,
214                                      return_headers:    true,
215                                      header_converters: :downcase )
216    assert_equal(%w{one two\ three}, csv.headers)
217  end
218
219  def test_builtin_symbol_converter
220    csv = CSV.parse( "One,TWO Three", headers:           true,
221                                      return_headers:    true,
222                                      header_converters: :symbol )
223    assert_equal([:one, :two_three], csv.headers)
224  end
225
226  def test_custom_converter
227    converter = lambda { |header| header.tr(" ", "_") }
228    csv       = CSV.parse( "One,TWO Three",
229                           headers:           true,
230                           return_headers:    true,
231                           header_converters: converter )
232    assert_equal(%w{One TWO_Three}, csv.headers)
233  end
234
235  def test_table_support
236    csv = nil
237    assert_nothing_raised(Exception) do
238      csv = CSV.parse(@data, headers: true)
239    end
240
241    assert_instance_of(CSV::Table, csv)
242  end
243
244  def test_skip_blanks
245    @data = <<-END_CSV.gsub(/^ +/, "")
246
247
248    A,B,C
249
250    1,2,3
251
252
253
254    END_CSV
255
256    expected = [%w[1 2 3]]
257    CSV.parse(@data, headers: true, skip_blanks: true) do |row|
258      assert_equal(expected.shift, row.fields)
259    end
260
261    expected = [%w[A B C], %w[1 2 3]]
262    CSV.parse( @data,
263               headers:        true,
264               return_headers: true,
265               skip_blanks:    true ) do |row|
266      assert_equal(expected.shift, row.fields)
267    end
268  end
269
270  def test_headers_reader
271    # no headers
272    assert_nil(CSV.new(@data).headers)
273
274    # headers
275    csv = CSV.new(@data, headers: true)
276    assert_equal(true, csv.headers)                    # before headers are read
277    csv.shift                                          # set headers
278    assert_equal(%w[first second third], csv.headers)  # after headers are read
279  end
280
281  def test_blank_row_bug_fix
282    @data += "\n#{@data}"  # add a blank row
283
284    # ensure that everything returned is a Row object
285    CSV.parse(@data, headers: true) do |row|
286      assert_instance_of(CSV::Row, row)
287    end
288  end
289end
290