From 79171d364e67a04921a99af11aebf4a8e3ebb17a Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Fri, 21 Jul 2023 17:07:42 +0200 Subject: [PATCH] Fix: unblind box when all samples have a measurement closes #1961 --- app/controllers/samples_controller.rb | 12 +++- spec/controllers/samples_controller_spec.rb | 67 ++++++++++++++++----- spec/spec_helper.rb | 1 + spec/support/uploaded_file_helper.rb | 17 ++++++ 4 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 spec/support/uploaded_file_helper.rb diff --git a/app/controllers/samples_controller.rb b/app/controllers/samples_controller.rb index 74cdfaf80..be41e1cdd 100644 --- a/app/controllers/samples_controller.rb +++ b/app/controllers/samples_controller.rb @@ -201,15 +201,21 @@ def bulk_destroy redirect_to samples_path, notice: "Samples were successfully deleted." end + def upload_results + end + def bulk_process_csv uuid_regex = /\b[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}\b/i + samples = check_access(@navigation_context.institution.samples, UPDATE_SAMPLE) + box_ids = Set.new params[:csv_files].each do |csv_file| CSV.open(csv_file.path) do |csv_stream| csv_stream.each do |(sample_id, measured_signal)| next unless sample_id&.match(uuid_regex) && measured_signal.present? - if sample = Sample.find_by_uuid(sample_id.strip) + if sample = samples.find_by_uuid(sample_id.strip) + box_ids << sample.box_id sample.measured_signal ||= Float(measured_signal.strip) sample.save! end @@ -217,6 +223,10 @@ def bulk_process_csv end end + Box.where(blinded: true, id: box_ids.to_a).each do |box| + box.unblind! if box.samples.all?(&:measured_signal) + end + redirect_to samples_path, notice: "Sample's results uploaded successfully." end diff --git a/spec/controllers/samples_controller_spec.rb b/spec/controllers/samples_controller_spec.rb index 820ba0e21..557d4fdee 100644 --- a/spec/controllers/samples_controller_spec.rb +++ b/spec/controllers/samples_controller_spec.rb @@ -646,30 +646,65 @@ def build_sample_form_plan(options) end context "upload_results" do - let!(:sample1) { Sample.make!(institution: institution, sample_identifiers: [SampleIdentifier.make!(uuid: '01234567-8ce1-a0c8-ac1b-58bed3633e88')], date_produced: Time.zone.local(2018, 1, 1)) } + it "renders form" do + get :upload_results + expect(response).to have_http_status(:ok) + end + end - it "should write measurement results for samples" do - file_path = File.join(Rails.root, 'spec', 'fixtures', 'csvs', 'samples_results_1.csv') - file = fixture_file_upload(file_path, 'text/csv') - post :bulk_process_csv, params: { "csv_files": [file] } - sample1.reload + context "bulk_process_csv" do + let(:sample) { Sample.make! :filled, institution: institution } - expect(sample1.measured_signal).to eq(10.0) + it "should write measurement results for samples" do + uploaded_file("#{sample.uuid},10", "text/csv") do |file| + post :bulk_process_csv, params: { "csv_files": [file] } + expect(response).to redirect_to(samples_path) + end + expect(sample.reload.measured_signal).to eq(10.0) end it "shouldn't overwrite measurement results for samples with measurements" do - file_path = File.join(Rails.root, 'spec', 'fixtures', 'csvs', 'samples_results_1.csv') - file = fixture_file_upload(file_path, 'text/csv') - post :bulk_process_csv, params: { "csv_files": [file] } - sample1.reload + uploaded_file("#{sample.uuid},10", "text/csv") do |file| + post :bulk_process_csv, params: { "csv_files": [file] } + expect(response).to redirect_to(samples_path) + end - file_path = File.join(Rails.root, 'spec', 'fixtures', 'csvs', 'samples_results_2.csv') - file = fixture_file_upload(file_path, 'text/csv') - post :bulk_process_csv, params: { "csv_files": [file] } - sample1.reload + uploaded_file("#{sample.uuid},20", "text/csv") do |file| + post :bulk_process_csv, params: { "csv_files": [file] } + expect(response).to redirect_to(samples_path) + end - expect(sample1.measured_signal).to eq(10.0) + expect(sample.reload.measured_signal).to eq(10.0) end + describe "box" do + let(:box) do + Box.make! :filled_without_measurements, institution: institution, blinded: true + end + + it "unblinds box with complete results" do + contents = <<~CSV + #{box.samples[0].uuid},10 + #{box.samples[1].uuid},20 + CSV + uploaded_file(contents, "text/csv") do |file| + post :bulk_process_csv, params: { "csv_files": [file] } + expect(response).to redirect_to(samples_path) + expect(box.reload.blinded).to be(false) + end + expect(box.samples[0].reload.measured_signal).to eq(10.0) + expect(box.samples[1].reload.measured_signal).to eq(20.0) + end + + it "won't unblind box with partial results" do + uploaded_file("#{box.samples[1].uuid},20", "text/csv") do |file| + post :bulk_process_csv, params: { "csv_files": [file] } + expect(response).to redirect_to(samples_path) + expect(box.reload.blinded).to be(true) + end + expect(box.samples[0].reload.measured_signal).to be_nil + expect(box.samples[1].reload.measured_signal).to eq(20.0) + end + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c87a88a1e..6ba683b17 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -72,6 +72,7 @@ def primary_key_name config.include Devise::TestHelpers, :type => :controller config.include DefaultParamsHelper, :type => :controller + config.include UploadedFileHelper, :type => :controller config.extend SpecFixtures config.include ManifestSpecHelper config.include CdxFieldsHelper diff --git a/spec/support/uploaded_file_helper.rb b/spec/support/uploaded_file_helper.rb new file mode 100644 index 000000000..6385e0cba --- /dev/null +++ b/spec/support/uploaded_file_helper.rb @@ -0,0 +1,17 @@ +require 'active_support/concern' + +module UploadedFileHelper + extend ActiveSupport::Concern + + def uploaded_file(contents, type, binary = false, &block) + tempfile = Tempfile.new("uploaded_file") + begin + tempfile.write(contents) + tempfile.rewind + yield Rack::Test::UploadedFile.new(tempfile, type, binary) + ensure + tempfile.close + tempfile.unlink + end + end +end