diff --git a/README.md b/README.md index cfc19af..3bb7a76 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,26 @@ There is a `Makefile` that contains some useful command shortcuts for typical de To see a current list of commands, run `make help`. +### Generating cassettes for tests + +We use [VCR](https://github.com/vcr/vcr) to record transactions with remote systems for testing. This includes the rake +task for reloading Detector::SuggestedResource records, which do not yet have a standard provider. For the initial +feature development, we have used a Lando environment with the following definition: + +```yml +name: static +recipe: lamp +config: + webroot: . +``` + +If you need to regenerate these cassettes, the following procedure should be sufficient: + +1. Use the configuration above to ensure the needed files are visible at `http://static.lndo.site/filename.ext`. +2. Delete any existing cassette files which need to be regenerated. +3. Run the test(s). +4. Commit the resulting files along with your other work. + ## Environment Variables ### Required diff --git a/app/models/detector/suggested_resource.rb b/app/models/detector/suggested_resource.rb index 526074e..3583297 100644 --- a/app/models/detector/suggested_resource.rb +++ b/app/models/detector/suggested_resource.rb @@ -53,5 +53,28 @@ def calculate_fingerprint(old_phrase) # Rejoin tokens tokens.join(' ') end + + # This replaces all current Detector::SuggestedResource records with a new set from an imported CSV. + # + # @note This method is called by the suggested_resource:reload rake task. + # + # @param input [CSV::Table] An imported CSV file containing all Suggested Resource records. The CSV file must have + # at least three headers, named "Title", "URL", and "Phrase". Please note: these values + # are case sensitive. + def self.bulk_replace(input) + raise ArgumentError.new, 'Tabular CSV is required' unless input.instance_of?(CSV::Table) + + # Need to check what columns exist in input + required_headers = %w[Title URL Phrase] + missing_headers = required_headers - input.headers + raise ArgumentError.new, "Some CSV columns missing: #{missing_headers}" unless missing_headers.empty? + + Detector::SuggestedResource.delete_all + + input.each do |line| + record = Detector::SuggestedResource.new({ title: line['Title'], url: line['URL'], phrase: line['Phrase'] }) + record.save + end + end end end diff --git a/lib/tasks/suggested_resources.rake b/lib/tasks/suggested_resources.rake new file mode 100644 index 0000000..9c0272f --- /dev/null +++ b/lib/tasks/suggested_resources.rake @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# These define tasks for managing our SuggestedResource records. +namespace :suggested_resources do + # While we intend to use Dataclips for exporting these records when needed, + # we do need a way to import records from a CSV file. + desc 'Replace all Suggested Resources from CSV' + task :reload, [:addr] => :environment do |_task, args| + raise ArgumentError.new, 'URL is required' unless args.addr.present? + + raise ArgumentError.new, 'Local files are not supported yet' unless URI(args.addr).scheme + + Rails.logger.info('Reloading all Suggested Resource records from CSV') + + url = URI.parse(args.addr) + + raise ArgumentError.new, 'HTTP/HTTPS scheme is required' unless url.scheme.in?(%w[http https]) + + file = url.open.read.gsub("\xEF\xBB\xBF", '').force_encoding('UTF-8').encode + data = CSV.parse(file, headers: true) + + Rails.logger.info("Record count before we reload: #{Detector::SuggestedResource.count}") + + Detector::SuggestedResource.bulk_replace(data) + + Rails.logger.info("Record count after we reload: #{Detector::SuggestedResource.count}") + end +end diff --git a/test/fixtures/files/suggested_resources.csv b/test/fixtures/files/suggested_resources.csv new file mode 100644 index 0000000..f0bec40 --- /dev/null +++ b/test/fixtures/files/suggested_resources.csv @@ -0,0 +1,3 @@ +Title,URL,Phrase +New Example,https://example.org,new example search +Web of Science,https://libraries.mit.edu/webofsci,web of Science \ No newline at end of file diff --git a/test/tasks/suggested_resource_rake_test.rb b/test/tasks/suggested_resource_rake_test.rb new file mode 100644 index 0000000..c1efd9e --- /dev/null +++ b/test/tasks/suggested_resource_rake_test.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'rake' + +class SuggestedResourceRakeTest < ActiveSupport::TestCase + def setup + Tacos::Application.load_tasks if Rake::Task.tasks.empty? + Rake::Task['suggested_resources:reload'].reenable + end + + test 'reload can accept a url' do + records_before = Detector::SuggestedResource.count # We have three fixtures at the moment + first_record_before = Detector::SuggestedResource.first + VCR.use_cassette('suggested_resource:reload from remote csv') do + remote_file = 'http://static.lndo.site/suggested_resources.csv' + Rake::Task['suggested_resources:reload'].invoke(remote_file) + end + refute_equal records_before, Detector::SuggestedResource.count + refute_equal first_record_before, Detector::SuggestedResource.first + end + + test 'reload task errors without a file argument' do + error = assert_raises(ArgumentError) do + Rake::Task['suggested_resources:reload'].invoke + end + assert_equal 'URL is required', error.message + end + + test 'reload errors on a local file' do + error = assert_raises(ArgumentError) do + local_file = Rails.root.join('test', 'fixtures', 'files', 'suggested_resources.csv').to_s + Rake::Task['suggested_resources:reload'].invoke(local_file) + end + assert_equal 'Local files are not supported yet', error.message + end + + test 'reload fails with a non-CSV file' do + assert_raises(CSV::MalformedCSVError) do + VCR.use_cassette('suggested_resource:reload from remote non-csv') do + remote_file = 'http://static.lndo.site/suggested_resources.xlsx' + Rake::Task['suggested_resources:reload'].invoke(remote_file) + end + end + end + + test 'reload fails unless all three columns are present: title, url, phrase' do + error = assert_raises(ArgumentError) do + VCR.use_cassette('suggested_resource:reload with missing field') do + remote_file = 'http://static.lndo.site/suggested_resources_missing_field.csv' + Rake::Task['suggested_resources:reload'].invoke(remote_file) + end + end + assert_equal 'Some CSV columns missing: ["Phrase"]', error.message + end + + # assert_nothing_raised is viewed as an anti-pattern, but I'm leery of a test + # with no assertions. As a result, we use a single assertion to confirm + # something happened. + test 'reload succeeds if extra columns are present' do + records_before = Detector::SuggestedResource.count # We have three fixtures at the moment + VCR.use_cassette('suggested_resource:reload with extra field') do + remote_file = 'http://static.lndo.site/suggested_resources_extra.csv' + Rake::Task['suggested_resources:reload'].invoke(remote_file) + end + refute_equal records_before, Detector::SuggestedResource.count + end +end diff --git a/test/vcr_cassettes/suggested_resource_reload_from_remote_csv.yml b/test/vcr_cassettes/suggested_resource_reload_from_remote_csv.yml new file mode 100644 index 0000000..e901f5c --- /dev/null +++ b/test/vcr_cassettes/suggested_resource_reload_from_remote_csv.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: http://static.lndo.site/suggested_resources.csv + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Accept-Ranges: + - bytes + Content-Length: + - '137' + Content-Type: + - text/csv + Date: + - Wed, 07 Aug 2024 17:19:29 GMT + Etag: + - '"89-61f180643e9d6"' + Last-Modified: + - Wed, 07 Aug 2024 13:38:25 GMT + Server: + - Apache/2.4.54 (Debian) + body: + encoding: ASCII-8BIT + string: !binary |- + 77u/VGl0bGUsVVJMLFBocmFzZQ0KTmV3IGV4YW1wbGUsaHR0cHM6Ly9leGFtcGxlLm9yZyxOZXcgZXhhbXBsZSBzZWFyY2gNCldlYiBvZiBTY2llbmNlLGh0dHBzOi8vbGlicmFyaWVzLm1pdC5lZHUvd2Vib2ZzY2ksd2ViIG9mIFNjaWVuY2U= + recorded_at: Wed, 07 Aug 2024 17:19:29 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/suggested_resource_reload_from_remote_non-csv.yml b/test/vcr_cassettes/suggested_resource_reload_from_remote_non-csv.yml new file mode 100644 index 0000000..9d45c70 --- /dev/null +++ b/test/vcr_cassettes/suggested_resource_reload_from_remote_non-csv.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: http://static.lndo.site/suggested_resources.xlsx + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Accept-Ranges: + - bytes + Content-Length: + - '9466' + Content-Type: + - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + Date: + - Wed, 07 Aug 2024 17:19:29 GMT + Etag: + - '"24fa-61f08dcf07d75"' + Last-Modified: + - Tue, 06 Aug 2024 19:33:07 GMT + Server: + - Apache/2.4.54 (Debian) + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + recorded_at: Wed, 07 Aug 2024 17:19:29 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/suggested_resource_reload_with_extra_field.yml b/test/vcr_cassettes/suggested_resource_reload_with_extra_field.yml new file mode 100644 index 0000000..553e780 --- /dev/null +++ b/test/vcr_cassettes/suggested_resource_reload_with_extra_field.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: http://static.lndo.site/suggested_resources_extra.csv + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Accept-Ranges: + - bytes + Content-Length: + - '151' + Content-Type: + - text/csv + Date: + - Wed, 07 Aug 2024 17:19:29 GMT + Etag: + - '"97-61f08dcf08696"' + Last-Modified: + - Tue, 06 Aug 2024 19:33:07 GMT + Server: + - Apache/2.4.54 (Debian) + body: + encoding: ASCII-8BIT + string: !binary |- + 77u/VGl0bGUsVVJMLFBocmFzZSxFeHRyYQ0KRXhhbXBsZSxodHRwczovL2V4YW1wbGUub3JnLGV4YW1wbGUgc2VhcmNoLGV4dHJhIDENCldlYiBvZiBTY2llbmNlLGh0dHBzOi8vbGlicmFyaWVzLm1pdC5lZHUvd2Vib2ZzY2ksd2ViIG9mIFNjaWVuY2UsZXh0cmEgMg== + recorded_at: Wed, 07 Aug 2024 17:19:29 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/suggested_resource_reload_with_missing_field.yml b/test/vcr_cassettes/suggested_resource_reload_with_missing_field.yml new file mode 100644 index 0000000..0732371 --- /dev/null +++ b/test/vcr_cassettes/suggested_resource_reload_with_missing_field.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: http://static.lndo.site/suggested_resources_missing_field.csv + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Accept-Ranges: + - bytes + Content-Length: + - '92' + Content-Type: + - text/csv + Date: + - Wed, 07 Aug 2024 17:19:29 GMT + Etag: + - '"5c-61f08dcf08c90"' + Last-Modified: + - Tue, 06 Aug 2024 19:33:07 GMT + Server: + - Apache/2.4.54 (Debian) + body: + encoding: ASCII-8BIT + string: !binary |- + 77u/VGl0bGUsVVJMDQpFeGFtcGxlLGh0dHBzOi8vZXhhbXBsZS5vcmcNCldlYiBvZiBTY2llbmNlLGh0dHBzOi8vbGlicmFyaWVzLm1pdC5lZHUvd2Vib2ZzY2k= + recorded_at: Wed, 07 Aug 2024 17:19:29 GMT +recorded_with: VCR 6.2.0