require File.dirname(__FILE__) + '/../../helper' module Coupler module Models class TestImport < Test::Unit::TestCase def test_sequel_model assert_equal ::Sequel::Model, Models::Import.superclass assert_equal :imports, Import.table_name end def test_many_to_one_project assert_respond_to Models::Import.new, :project end def test_gets_name_from_original_filename import = Import.new(:data => fixture_file_upload('people.csv')) assert_equal "People", import.name end def test_preview_with_headers import = Factory.build(:import) preview = import.preview assert_kind_of Array, preview assert_equal 50, preview.length assert_kind_of Array, preview[0] assert_not_equal %w{id first_name last_name age}, preview[0] end def test_discovers_field_names_and_types import = Factory.build(:import, :data => fixture_file_upload("people.csv")) expected_types = %w{integer string string integer} expected_names = %w{id first_name last_name age} assert_equal expected_names, import.field_names assert_equal expected_types, import.field_types assert_equal "id", import.primary_key_name assert import.has_headers end def test_discover_for_csv_with_no_headers tempfile = Tempfile.new('coupler-import') tempfile.write("foo,bar,1,2,3\njunk,blah,4,5,6") tempfile.close import = Factory.build(:import, :data => file_upload(tempfile.path)) expected_types = %w{string string integer integer integer} assert_equal expected_types, import.field_types assert_nil import.field_names assert_nil import.primary_key_name assert !import.has_headers end def test_import! project = Factory(:project) import = Factory(:import, :data => fixture_file_upload("people.csv"), :project => project) now = Time.now Timecop.freeze(now) do assert import.import! assert_equal now, import.occurred_at end project.local_database do |db| name = :"import_#{import.id}" assert db.tables.include?(name) schema = db.schema(name) assert_equal [:integer, true], schema.assoc(:id)[1].values_at(:type, :primary_key) assert_equal :string, schema.assoc(:first_name)[1][:type] assert_equal :string, schema.assoc(:last_name)[1][:type] assert_equal :integer, schema.assoc(:age)[1][:type] ds = db[name] assert_equal 50, ds.count end end def test_requires_field_names import = Factory.build(:import, :data => fixture_file_upload('no-headers.csv')) assert_nil import.field_names assert !import.valid? end def test_requires_primary_key_name import = Factory.build(:import, :data => fixture_file_upload('no-headers.csv')) import.field_names = %w{id first_name last_name age} assert !import.valid? end def test_requires_valid_primary_key_name import = Factory.build(:import, :data => fixture_file_upload('no-headers.csv')) import.field_names = %w{id first_name last_name age} import.primary_key_name = "foo" assert !import.valid? end def test_flags_duplicate_primary_keys tempfile = Tempfile.new('coupler-import') tempfile.write("id,foo,bar\n1,abc,def\n2,ghi,jkl\n2,mno,pqr") tempfile.close project = Factory(:project) import = Factory(:import, :data => file_upload(tempfile.path), :project => project) now = Time.at(Time.now.to_i) # dumb usecs Timecop.freeze(now) do assert !import.import! assert import.has_duplicate_keys assert_equal now, import.occurred_at, "now: %d-%d; occurred_at: %d-%d" % [now.to_i, now.usec, import.occurred_at.to_i, import.occurred_at.usec] end project.local_database do |db| ds = db[:"import_#{import.id}"] assert ds.filter(:id => 2).select_map(:dup_key_count).all? end end def test_requires_unique_field_names tempfile = Tempfile.new('coupler-import') tempfile.write("id,foo,foo\n1,abc,def\n2,ghi,jkl\n3,mno,pqr") tempfile.close import = Factory.build(:import, :data => file_upload(tempfile.path)) assert !import.valid? end def test_requires_unused_resource_name project = Factory(:project) resource = Factory(:resource, :name => "Foo", :project => project) import = Factory.build(:import, :data => fixture_file_upload('people.csv'), :name => "Foo", :project => project) assert !import.valid? end def test_dataset project = Factory(:project) import = Factory(:import, :project => project) import.import! project.local_database do |db| import.dataset do |ds| expected = db[:"import_#{import.id}"] assert_equal expected.first_source, ds.first_source assert_equal db.uri, ds.db.uri end end end def test_filenames_dont_conflict dir = make_tmpdir filename = File.join(dir, "people.csv") tempfile = File.open(filename, 'w') tempfile.puts("id,foo,bar\n") tempfile.puts("abc,def,ghi\n") tempfile.close import_1 = Factory(:import, :data => fixture_file_upload('people.csv')) import_2 = Factory(:import, :data => file_upload(filename)) assert_not_equal import_1.data.store_path, import_2.data.store_path end def test_repair_duplicate_keys project = Factory(:project) import = Factory(:import, :data => fixture_file_upload('duplicate-keys.csv'), :project => project) import.import! import.repair_duplicate_keys!(nil) import.dataset do |ds| assert !ds.columns!.include?(:dup_key_count) assert_equal 1, ds.filter(:id => 2).count assert_equal 1, ds.filter(:id => 4).count end project.local_database do |db| assert db.schema(:"import_#{import.id}").assoc(:id)[1][:primary_key] end end def test_repair_duplicate_keys_with_deletions tempfile = Tempfile.new('coupler-import') tempfile.write("id,foo,bar\n1,2,3\n1,4,5\n1,6,7\n123,456,789\n") tempfile.close project = Factory(:project) #puts "Project: #{project.id}" import = Factory(:import, :data => file_upload(tempfile.path), :project => project) #puts "Import: #{import.id}" import.import! import.repair_duplicate_keys!({"1" => ["1"]}) import.dataset do |ds| assert !ds.columns!.include?(:dup_key_count) assert_equal 1, ds.filter(:id => 1).count assert_equal 1, ds.filter(:id => 124).count assert_equal 0, ds.filter(:id => 125).count end project.local_database do |db| assert db.schema(:"import_#{import.id}").assoc(:id)[1][:primary_key] end end def test_discover_fields_for_csv_with_headers_and_varying_number_of_fields tempfile = Tempfile.new('coupler-import') tempfile.write("id,foo,bar\n1,2,3\n1,4,5\n1,6,7,\n123,456,789,,\n") tempfile.close import = Factory.build(:import, :data => file_upload(tempfile.path)) expected_types = %w{integer integer integer string string} expected_names = %w{id foo bar} assert_equal expected_names, import.field_names assert_equal expected_types, import.field_types assert_equal "id", import.primary_key_name assert import.has_headers end def test_importing_bad_integers tempfile = Tempfile.new('coupler-import') tempfile.write(%{id,foo,bar\n1,2,3\n2,4,5\n3,6,7\n4,456,""\n}) tempfile.close project = Factory(:project) import = Factory(:import, :data => file_upload(tempfile.path), :project => project) assert_nothing_raised do import.import! end end end end end