From c3b95f1e09d09e892d835105284fc3e5387f3f5b Mon Sep 17 00:00:00 2001 From: gangelo Date: Tue, 30 Jan 2024 13:17:49 -0500 Subject: [PATCH] dsu import spec work --- lib/dsu/presenters/import/all_presenter.rb | 2 +- lib/dsu/presenters/import/dates_presenter.rb | 12 +- lib/locales/en/subcommands.yml | 2 +- spec/dsu/views/import_spec.rb | 126 ++++++++++++------ .../files/import-with-duplicate-errors.csv | 5 + 5 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 spec/fixtures/files/import-with-duplicate-errors.csv diff --git a/lib/dsu/presenters/import/all_presenter.rb b/lib/dsu/presenters/import/all_presenter.rb index e38d73ec..b3a9087b 100644 --- a/lib/dsu/presenters/import/all_presenter.rb +++ b/lib/dsu/presenters/import/all_presenter.rb @@ -48,7 +48,7 @@ def import_entry_groups entry_groups_hash[project_name] = {} unless entry_groups_hash.key?(project_name) Date.parse(entry_group_entry[:entry_group]).to_s.tap do |time| - entry_groups_hash[project_name][time] = [] unless entry_groups_hash.key?(time) + entry_groups_hash[project_name][time] = [] unless entry_groups_hash[project_name].key?(time) entry_groups_hash[project_name][time] << entry_group_entry[:entry_group_entry] end end diff --git a/lib/dsu/presenters/import/dates_presenter.rb b/lib/dsu/presenters/import/dates_presenter.rb index 3ce2559d..ddd1a143 100644 --- a/lib/dsu/presenters/import/dates_presenter.rb +++ b/lib/dsu/presenters/import/dates_presenter.rb @@ -11,7 +11,7 @@ module Import class DatesPresenter < BasePresenterEx include ImportFile - attr_reader :from, :to + attr_reader :from, :to, :import_file_path, :import_messages def initialize(from:, to:, import_file_path:, options: {}) super(options: options) @@ -41,8 +41,6 @@ def project_name private - attr_reader :import_file_path - def import_entry_groups @import_entry_groups ||= CSV.foreach(import_file_path, headers: true, header_converters: :symbol).with_object({}) do |entry_group_entry, entry_groups_hash| @@ -59,7 +57,7 @@ def import_entry_groups entry_groups_hash[project_name] = {} unless entry_groups_hash.key?(project_name) entry_group_time.to_date.to_s.tap do |time| - entry_groups_hash[project_name][time] = [] unless entry_groups_hash.key?(time) + entry_groups_hash[project_name][time] = [] unless entry_groups_hash[project_name].key?(time) entry_groups_hash[project_name][time] << entry_group_entry[:entry_group_entry] end end @@ -68,6 +66,12 @@ def import_entry_groups def middle_of_day_for(date_string) Time.parse(date_string).in_time_zone.middle_of_day end + + def importer_service + @importer_service ||= Services::EntryGroup::ImporterService.new( + import_projects: import_entry_groups, options: options + ) + end end end end diff --git a/lib/locales/en/subcommands.yml b/lib/locales/en/subcommands.yml index 9d590d6d..115cb695 100644 --- a/lib/locales/en/subcommands.yml +++ b/lib/locales/en/subcommands.yml @@ -370,7 +370,7 @@ en: $ dsu import all -i /path/to/import.csv messages: import_success: Entry group for %{date} imported successfully. - import_error: "Entry group for %{date} imported with an error: %{error}." + import_error: "Entry group for %{date} imported with an error: %{error}" import_error_raised: "The entry groups failed to import. The following error was raised: \"%{error}\"." nothing_to_import: No entry groups to import. cancelled: Cancelled. diff --git a/spec/dsu/views/import_spec.rb b/spec/dsu/views/import_spec.rb index 6aa0c382..3e893db6 100644 --- a/spec/dsu/views/import_spec.rb +++ b/spec/dsu/views/import_spec.rb @@ -5,18 +5,19 @@ let(:options) { {} } let(:import_file_path) { 'spec/fixtures/files/import.csv' } - let(:presenter) do - Dsu::Presenters::Import::AllPresenter.new(import_file_path: import_file_path, options: options) - end describe '#initialize' do + let(:presenter) do + Dsu::Presenters::Import::AllPresenter.new(import_file_path: import_file_path, options: options) + end + it 'does not raise an error' do expect { import_view }.to_not raise_error end end describe '#render' do - context 'when all entry groups are being imported' do + shared_examples 'the import file does not exist' do context 'when the import file does not exist' do let(:import_file_path) { 'spec/fixtures/files/does-not-exist.csv' } @@ -26,7 +27,9 @@ end.chomp)).to include('Import file spec/fixtures/files/does-not-exist.csv does not exist.') end end + end + shared_examples 'there is nothing to import' do context 'when there is nothing to import' do let(:import_file_path) { 'spec/fixtures/files/nothing-to-import.csv' } @@ -36,61 +39,106 @@ end.chomp)).to include('No entry groups to import.') end end + end - context 'when there is something to import' do - context 'when the user responds with "Y"' do - before do - stub_import_prompt(response: 'Y') - end - - let(:expected_output) do - <<~OUTPUT - Entry group for 2023-12-31 imported successfully. - Entry group for 2024-01-01 imported successfully. - Entry group for 2024-01-02 imported successfully. - OUTPUT - end - - context 'when all imports are successful' do - it "displays the 'imported successfully' message" do - expect(strip_escapes(Dsu::Services::StdoutRedirectorService.call do - import_view.render - end.chomp)).to include(expected_output.chomp) - end - end + shared_examples 'there is something to import' do + context 'when the user responds with "Y"' do + before do + stub_import_prompt(response: 'Y') end - context 'when the user responds with "n"' do - before do - stub_import_prompt(response: 'n') - end + let(:expected_output) do + <<~OUTPUT + Entry group for 2023-12-31 imported successfully. + Entry group for 2024-01-01 imported successfully. + Entry group for 2024-01-02 imported successfully. + OUTPUT + end - it "displays the 'nothing to import' message" do + context 'when all imports are successful' do + it "displays the 'imported successfully' message" do expect(strip_escapes(Dsu::Services::StdoutRedirectorService.call do import_view.render - end.chomp)).to include('Cancelled.') + end.chomp)).to include(expected_output.chomp) end end end - context 'when the import file has errors' do + context 'when the user responds with "n"' do before do - stub_import_prompt(response: 'Y') + stub_import_prompt(response: 'n') end - let(:import_file_path) { 'spec/fixtures/files/import-with-errors.csv' } - let(:expected_output) { /The entry groups failed to import/ } - - it "displays the 'imported successfully' message" do + it "displays the 'nothing to import' message" do expect(strip_escapes(Dsu::Services::StdoutRedirectorService.call do import_view.render - end.chomp)).to match(expected_output) + end.chomp)).to include('Cancelled.') end end end + shared_examples 'the import raises an error' do + before do + stub_import_prompt(response: 'Y') + end + + let(:import_file_path) { 'spec/fixtures/files/import-with-errors.csv' } + let(:expected_output) { /The entry groups failed to import/ } + + it "displays the 'imported successfully' message" do + expect(strip_escapes(Dsu::Services::StdoutRedirectorService.call do + import_view.render + end.chomp)).to match(expected_output) + end + end + + shared_examples 'the import has errors' do + before do + stub_import_prompt(response: 'Y') + end + + let(:options) { { merge: false } } + let(:expected_output) do + <<~OUTPUT + Entry group for 2023-12-31 imported with an error: Entries array contains duplicate entry: "Entry 2023-12-31...". + Entry group for 2024-01-01 imported successfully. + Entry group for 2024-01-02 imported successfully. + OUTPUT + end + + let(:import_file_path) { 'spec/fixtures/files/import-with-duplicate-errors.csv' } + + it "displays the 'imported successfully' message" do + expect(strip_escapes(Dsu::Services::StdoutRedirectorService.call do + import_view.render + end.chomp)).to include(expected_output.chomp) + end + end + + context 'when all entry groups are being imported' do + let(:presenter) do + Dsu::Presenters::Import::AllPresenter.new(import_file_path: import_file_path, options: options) + end + + it_behaves_like 'the import file does not exist' + it_behaves_like 'there is nothing to import' + it_behaves_like 'there is something to import' + it_behaves_like 'the import raises an error' + it_behaves_like 'the import has errors' + end + describe 'when entry groups are being imported by to/from dates' do - let(:presenter) { instance_double(Dsu::Presenters::Import::DatesPresenter) } + let(:presenter) do + Dsu::Presenters::Import::DatesPresenter.new(from: from, to: to, import_file_path: import_file_path, options: options) + end + let(:from) { Time.parse('2023-12-31').localtime } + let(:to) { Time.parse('2024-01-02').localtime } + + it_behaves_like 'the import file does not exist' + it_behaves_like 'there is nothing to import' + it_behaves_like 'there is something to import' + it_behaves_like 'the import raises an error' + it_behaves_like 'the import has errors' end end end diff --git a/spec/fixtures/files/import-with-duplicate-errors.csv b/spec/fixtures/files/import-with-duplicate-errors.csv new file mode 100644 index 00000000..69f57c9b --- /dev/null +++ b/spec/fixtures/files/import-with-duplicate-errors.csv @@ -0,0 +1,5 @@ +project_name,version,entry_group,entry_no,total_entries,entry_group_entry +default,20230613121411,2023-12-31,1,2,Entry 2023-12-31 duplicate +default,20230613121411,2023-12-31,2,2,Entry 2023-12-31 duplicate +default,20230613121411,2024-01-01,1,1,Entry 2024-01-01 1 of 2 +default,20230613121411,2024-01-02,1,1,Entry 2024-01-02 2 of 2