RSpec.shared_examples 'CanCsvImport' do |unique_attributes: []|
  describe '.csv_import' do
    let!(:params) { { string: <<~CSV, parse_params: { col_sep: ',' } } }
      #{described_class.attribute_names.join(',')}
      #{build(factory).attributes.values.join(',')}
    CSV

    let(:factory) { described_class.name.underscore }

    context 'with duplicate entries for unique attributes' do
      shared_examples 'case-insensitive duplicates' do |attribute|
        let!(:params) { { string: <<~CSV, parse_params: { col_sep: ',' } } }
          #{described_class.attribute_names.join(',')}
          #{build(factory, attribute => 'Foo').attributes.values.join(',')}
          #{build(factory, attribute => 'FOO').attributes.values.join(',')}
        CSV

        it 'cancels import' do
          expect { described_class.csv_import(**params) }
            .not_to change(described_class, :count)
        end

        it 'reports the duplicate' do
          expect(described_class.csv_import(**params))
            .to include(result: 'failed')
        end
      end

      Array(unique_attributes).each do |attribute|
        include_examples 'case-insensitive duplicates', attribute
      end
    end

    context 'when record creation unexpectedly fails' do
      around do |example|
        described_class.validate { errors.add(:base, 'Unexpected failure!') }
        example.run
        described_class._validate_callbacks.send(:chain).pop
        described_class.send(:set_callbacks, :validate, described_class._validate_callbacks.dup)
      end

      context 'during a dry-run' do
        before { params.merge!(try: 'true') }

        it 'reports the failure' do
          expect(described_class.csv_import(**params))
            .to include(result: 'failed')
        end
      end
    end
  end
end
