<commit_before>require 'spec_helper'
require 'ostruct'
require 'cat'
require "row_group"

include TablePrint

describe RowRecursion do
  let(:parent) { RowGroup.new }
  let(:child) { Row.new }

  describe "#set_column" do
    it "assigns the column object to the column name" do
      column = Column.new
      parent.set_column(:foobar, column)
      parent.column_for(:foobar).should == column
    end
  end

  describe "#add_child" do
    it "adds the child to my children" do
      parent.add_child(child)
      parent.child_count.should == 1
    end

    it "sets me as my child's parent" do
      parent.add_child(child)
      child.parent.should == parent
    end
  end

  describe "#add_children" do
    let (:child2) {Row.new}

    it "adds all the children to myself" do
      parent.add_children([child, child2])
      parent.child_count.should == 2
    end

    it "sets me as their parent" do
      parent.add_children([child, child2])
      child.parent.should == parent
      child2.parent.should == parent
    end
  end

  describe "#columns" do
    it "returns columns populated with names and data" do
      child.set_cell_values(:title => 'foobar')
      parent.add_child(child)

      parent.columns.length.should == 1
      parent.columns.first.name.should == 'title'
      parent.columns.first.data.should == ['foobar']
    end

    it "gets the columns from the root node" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')

      parent.columns.length.should == 1
      child.columns.should == parent.columns
    end
  end

  describe "#column_for" do
    it "returns the column object for a given column name" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')
      column = parent.columns.first
      parent.column_for(:title).should == column
    end
  end

  describe "#add_formatter" do
    it "adds the formatter to the column object" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')
      column = parent.columns.first
      parent.add_formatter(:title, {})

      column.formatters.should == [{}]
    end
  end

  describe "#width" do
    it "returns the total width of the columns" do
      parent.add_child(r1 = Row.new)
      parent.add_child(r2 = Row.new)

      r1.set_cell_values(:title => 'foobar')
      r2.set_cell_values(:subtitle => 'elemental')

      parent.width.should == 18
    end
  end

  describe "#horizontal_separator" do
    it "returns hyphens equal to the table width" do
      child.set_cell_values(:title => 'foobar')
      child.horizontal_separator.should == '------'
    end
  end

  describe "#header" do
    it "returns the column names, padded to the proper width, separated by the | character" do
      child.set_cell_values(:title => 'first post', :author => 'chris', :subtitle => 'first is the worst')
      compare_rows(child.header, "AUTHOR | SUBTITLE           | TITLE     ")
    end
  end
end

describe TablePrint::RowGroup do
  describe "#raw_column_data" do
    it "returns the column data from its child rows" do
      group = RowGroup.new
      group.add_child(Row.new.set_cell_values(:title => 'foo'))
      group.add_child(Row.new.set_cell_values(:title => 'bar'))
      group.raw_column_data(:title).should == ['foo', 'bar']
    end
  end

  describe "#column_width" do
    it "finds the width of a column" do
      group = RowGroup.new
      group.add_child(Row.new.set_cell_values(:title => 'asdf'))
      group.add_child(Row.new.set_cell_values(:title => 'qwerty'))
      group.column_width(:title).should == 6
    end
  end
end

def compare_rows(actual_rows, expected_rows)
  actual_rows.split("\n").length.should == expected_rows.split("\n").length
  actual_rows.split("\n").zip(expected_rows.split("\n")).each do |actual, expected|
    actual.split(//).sort.join.should == expected.split(//).sort.join
  end
end

describe TablePrint::Row do
  let(:row) { Row.new.set_cell_values({'title' => "wonky", 'author' => "<NAME>", 'pub_date' => "2012"}) }

  describe "#format" do
    it "formats the row with padding" do
      compare_rows(row.format, "wonky | <NAME> | 2012    ")
    end

    it "also formats the children" do
      row.add_child(RowGroup.new.add_child(Row.new.set_cell_values(:title => "wonky2", :author => "<NAME>", :pub_date => "20122")))
      compare_rows(row.format, "wonky  | <NAME>  | 2012    \nwonky2 | <NAME>2 | 20122   ")
    end
  end

  describe "#apply_formatters" do
    it "calls the format method on each formatter for that column" do
      Sandbox.add_class("DoubleFormatter")
      Sandbox.add_method("DoubleFormatter", :format) { |value| value * 2 }

      Sandbox.add_class("ChopFormatter")
      Sandbox.add_method("ChopFormatter", :format) { |value| value[0..-2] }

      f1 = Sandbox::DoubleFormatter.new
      f2 = Sandbox::ChopFormatter.new

      row.stub(:column_for) {OpenStruct.new(:width => 11, :formatters => [f1, f2])}

      row.apply_formatters(:title, "foobar").should == "foobarfooba"
    end

    it "uses the config'd time_format to format times" do
      row.stub(:column_for) {OpenStruct.new(:width => 20, :formatters => [], :time_format => "%Y %m %d")}

      time_formatter = OpenStruct.new(:format => "")
      TablePrint::TimeFormatter.should_receive(:new).with("%Y %m %d") {time_formatter}
      row.apply_formatters(:title, Time.local(2012, 6, 1, 14, 20, 20))
    end
  end

  describe "#raw_column_data" do
    it "returns all the values for a given column" do
      row = Row.new.set_cell_values(:title => 'one', :author => 'two')

      group = RowGroup.new
      ['two', 'three', 'four', 'five', 'six', 'seven'].each do |title|
        group.add_child(Row.new.set_cell_values(:title => title))
      end
      row.add_child(group)

      row.raw_column_data('title').should == ['one', 'two', 'three', 'four', 'five', 'six', 'seven']
    end
  end

  describe "#collapse" do<commit_msg>use a real TimeFormatter because 1.9 chokes when you call an ostruct method with args<commit_after>require 'spec_helper'
require 'ostruct'
require 'cat'
require "row_group"

include TablePrint

describe RowRecursion do
  let(:parent) { RowGroup.new }
  let(:child) { Row.new }

  describe "#set_column" do
    it "assigns the column object to the column name" do
      column = Column.new
      parent.set_column(:foobar, column)
      parent.column_for(:foobar).should == column
    end
  end

  describe "#add_child" do
    it "adds the child to my children" do
      parent.add_child(child)
      parent.child_count.should == 1
    end

    it "sets me as my child's parent" do
      parent.add_child(child)
      child.parent.should == parent
    end
  end

  describe "#add_children" do
    let (:child2) {Row.new}

    it "adds all the children to myself" do
      parent.add_children([child, child2])
      parent.child_count.should == 2
    end

    it "sets me as their parent" do
      parent.add_children([child, child2])
      child.parent.should == parent
      child2.parent.should == parent
    end
  end

  describe "#columns" do
    it "returns columns populated with names and data" do
      child.set_cell_values(:title => 'foobar')
      parent.add_child(child)

      parent.columns.length.should == 1
      parent.columns.first.name.should == 'title'
      parent.columns.first.data.should == ['foobar']
    end

    it "gets the columns from the root node" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')

      parent.columns.length.should == 1
      child.columns.should == parent.columns
    end
  end

  describe "#column_for" do
    it "returns the column object for a given column name" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')
      column = parent.columns.first
      parent.column_for(:title).should == column
    end
  end

  describe "#add_formatter" do
    it "adds the formatter to the column object" do
      parent.add_child(child)
      child.set_cell_values(:title => 'foobar')
      column = parent.columns.first
      parent.add_formatter(:title, {})

      column.formatters.should == [{}]
    end
  end

  describe "#width" do
    it "returns the total width of the columns" do
      parent.add_child(r1 = Row.new)
      parent.add_child(r2 = Row.new)

      r1.set_cell_values(:title => 'foobar')
      r2.set_cell_values(:subtitle => 'elemental')

      parent.width.should == 18
    end
  end

  describe "#horizontal_separator" do
    it "returns hyphens equal to the table width" do
      child.set_cell_values(:title => 'foobar')
      child.horizontal_separator.should == '------'
    end
  end

  describe "#header" do
    it "returns the column names, padded to the proper width, separated by the | character" do
      child.set_cell_values(:title => 'first post', :author => 'chris', :subtitle => 'first is the worst')
      compare_rows(child.header, "AUTHOR | SUBTITLE           | TITLE     ")
    end
  end
end

describe TablePrint::RowGroup do
  describe "#raw_column_data" do
    it "returns the column data from its child rows" do
      group = RowGroup.new
      group.add_child(Row.new.set_cell_values(:title => 'foo'))
      group.add_child(Row.new.set_cell_values(:title => 'bar'))
      group.raw_column_data(:title).should == ['foo', 'bar']
    end
  end

  describe "#column_width" do
    it "finds the width of a column" do
      group = RowGroup.new
      group.add_child(Row.new.set_cell_values(:title => 'asdf'))
      group.add_child(Row.new.set_cell_values(:title => 'qwerty'))
      group.column_width(:title).should == 6
    end
  end
end

def compare_rows(actual_rows, expected_rows)
  actual_rows.split("\n").length.should == expected_rows.split("\n").length
  actual_rows.split("\n").zip(expected_rows.split("\n")).each do |actual, expected|
    actual.split(//).sort.join.should == expected.split(//).sort.join
  end
end

describe TablePrint::Row do
  let(:row) { Row.new.set_cell_values({'title' => "wonky", 'author' => "<NAME>", 'pub_date' => "2012"}) }

  describe "#format" do
    it "formats the row with padding" do
      compare_rows(row.format, "wonky | <NAME> | 2012    ")
    end

    it "also formats the children" do
      row.add_child(RowGroup.new.add_child(Row.new.set_cell_values(:title => "wonky2", :author => "<NAME>", :pub_date => "20122")))
      compare_rows(row.format, "wonky  | <NAME>  | 2012    \nwonky2 | <NAME> | 20122   ")
    end
  end

  describe "#apply_formatters" do
    it "calls the format method on each formatter for that column" do
      Sandbox.add_class("DoubleFormatter")
      Sandbox.add_method("DoubleFormatter", :format) { |value| value * 2 }

      Sandbox.add_class("ChopFormatter")
      Sandbox.add_method("ChopFormatter", :format) { |value| value[0..-2] }

      f1 = Sandbox::DoubleFormatter.new
      f2 = Sandbox::ChopFormatter.new

      row.stub(:column_for) {OpenStruct.new(:width => 11, :formatters => [f1, f2])}

      row.apply_formatters(:title, "foobar").should == "foobarfooba"
    end

    it "uses the config'd time_format to format times" do
      row.stub(:column_for) {OpenStruct.new(:width => 20, :formatters => [], :time_format => "%Y %m %d")}

      time_formatter = TablePrint::TimeFormatter.new
      TablePrint::TimeFormatter.should_receive(:new).with("%Y %m %d") {time_formatter}
      row.apply_formatters(:title, Time.local(2012, 6, 1, 14, 20, 20))
    end
  end

  describe "#raw_column_data" do
    it "returns all the values for a given column" do
      row = Row.new.set_cell_values(:title => 'one', :author => 'two')

      group = RowGroup.new
      ['two', 'three', 'four', 'five', 'six', 'seven'].each do |title|
        group.add_child(Row.new.set_cell_values(:title => title))
      end
      row.add_child(group)

      row.raw_column_data('title').should == ['one', 'two', 'three', 'four', 'five', 'six', 'seven']
    end
  end

  describe "#collapse" do
{'fraction_non_alphanumeric': 0.13359066879248133, 'fraction_numerical': 0.010657044558194176, 'mean_word_length': 3.126731301939058, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 70, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7354451', 'n_tokens_mistral': 3993, 'n_tokens_neox': 3795, 'n_words': 983}