diff --git a/.github/workflows/automated_release.yml b/.github/workflows/automated_release.yml index d97cfb087..d3821b796 100644 --- a/.github/workflows/automated_release.yml +++ b/.github/workflows/automated_release.yml @@ -27,10 +27,6 @@ jobs: with: bundler-cache: true # runs 'bundle install' and caches installed gems automatically - # Actually run our build - - name: Create Build - run: ./compile-build - # Create a release tag based on the branch name and .release-version file - name: Set release tag # https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable @@ -38,6 +34,10 @@ jobs: # On the master branch this would then only create RELEASE_VERSION=2.4.6 run: echo "RELEASE_VERSION=$(printf -- '%s%s\n' $(cat .release-version) $([ ${BRANCH_NAME} = "develop" ] && printf -- '-%s-develop' ${GITHUB_RUN_ID} || echo ""))" >> $GITHUB_ENV + # Actually run our build + - name: Create Build + run: ./compile-build '' v${{ env.RELEASE_VERSION }} ${BRANCH_NAME} + # Create a GitHub release with the release asset as an artifact - name: Create release and upload release.tar.gz uses: ncipollo/release-action@v1.8.8 diff --git a/.github/workflows/check_release_version.yml b/.github/workflows/check_release_version.yml index 911217835..d85e1525f 100644 --- a/.github/workflows/check_release_version.yml +++ b/.github/workflows/check_release_version.yml @@ -5,10 +5,19 @@ on: pull_request: branches: - master + types: + # defaults + - opened + - synchronize + - reopened + # custom + - ready_for_review # required for Github-created PRs jobs: check: runs-on: ubuntu-latest + # only run when PR is not draft + if: ${{ !github.event.pull_request.draft }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/create_release_pr.yml b/.github/workflows/create_release_pr.yml new file mode 100644 index 000000000..4626ccf1a --- /dev/null +++ b/.github/workflows/create_release_pr.yml @@ -0,0 +1,61 @@ +# Create or update merge-to-master pull requests for production releases +# Note that by design, creating or editing a PR will not trigger a downstream `pull_request` event as this could lead to recursion +name: Release +on: + push: + branches: + - develop +jobs: + pull_request: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Create or update PR + env: + GH_TOKEN: ${{ github.token }} + run: | + PR_TITLE="[automated] Merge Develop into Master" + + # Extract numbers from PRs that have been merged into develop + PR_NUMBERS=$(gh api repos/:owner/:repo/compare/master...develop --jq ' + .commits[] + | select(.commit.message + | startswith("Merge pull request")) + | .commit.message + | capture("#(?\\d+)") + | .pr_number' + ) + + # Fetch titles for each PR number + PR_NUMBERS_AND_TITLES=$(for PR_NUMBER in $PR_NUMBERS; do + gh pr view $PR_NUMBER --json number,title --jq '{number: .number, title: .title}' + done | jq -s 'sort_by(.title)') + + # Sort extracted PR numbers by title + SORTED_PR_NUMBERS=$(jq -r '.[].number' <<< "$PR_NUMBERS_AND_TITLES") + + STORIES=$(xargs -I {} gh pr view {} --json body --jq '.body | if . | test("Closes #\\d+") then capture("Closes #(?\\d+)") | "- #{} + - Closes #" + .issue_number else "- #{}" end' <<< "$SORTED_PR_NUMBERS") # Note the line-break on this line is for formatting + + PR_BODY="#### Changes proposed in this pull request + + $(echo "$STORIES") + + #### Instructions for Reviewers + + - _Check stories are ready for release._ + - _Check for any database migrations._ + - _Check for debug code._ + - _Check version is appropriate._ + + This description will be overwritten on the next push + This PR was auto-generated on $(TZ=Europe/London date --iso-8601=seconds)" + + # Check if a PR already exists + EXISTING_PR=$(gh pr list --base master --head develop --json number --jq '.[0].number') + + if [ -z "$EXISTING_PR" ]; then + gh pr create --base master --head develop --title "$PR_TITLE" --body "$PR_BODY" --draft + else + gh pr edit "$EXISTING_PR" --body "$PR_BODY" + fi diff --git a/.prettierignore b/.prettierignore index a35fa9c2c..a1d0dba8d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,6 +10,7 @@ public/stylesheets/*.css .sass-cache/ *.orig *.sublime-workspace +/bin /public/packs /public/packs-test /node_modules diff --git a/.prettierrc.json b/.prettierrc.json index cbe842acd..c5a1534ca 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,7 @@ { "printWidth": 120, "semi": false, - "singleQuote": true + "rubySingleQuote": true, + "singleQuote": true, + "plugins": ["@prettier/plugin-ruby"] } diff --git a/.pryrc b/.pryrc new file mode 100644 index 000000000..ca997213f --- /dev/null +++ b/.pryrc @@ -0,0 +1,7 @@ +# frozen_string_literal: true +if defined?(PryByebug) + Pry.commands.alias_command 's', 'step' + Pry.commands.alias_command 'n', 'next' + Pry.commands.alias_command 'f', 'finish' + Pry.commands.alias_command 'c', 'continue' +end diff --git a/.release-version b/.release-version index 71c010956..6621aa3bc 100644 --- a/.release-version +++ b/.release-version @@ -1 +1 @@ -3.60.0 +3.61.1 diff --git a/.rubocop.yml b/.rubocop.yml index 599363460..ace6b1f7c 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -22,6 +22,11 @@ Rails/FindBy: Enabled: false Style/ClassAndModuleChildren: Enabled: false + +# Only use shorthand hash syntax when all keys match the variables for better readability +Style/HashSyntax: + EnforcedShorthandSyntax: consistent + # Filter out all the DSLs Metrics/BlockLength: CountAsOne: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8ad0bced4..f09e82ecf 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,17 +1,52 @@ # This configuration was generated by -# `rubocop --auto-gen-config` -# on 2023-10-17 14:45:52 UTC using RuboCop version 1.39.0. +# `rubocop --auto-gen-config --no-exclude-limit` +# on 2024-09-20 10:20:24 UTC using RuboCop version 1.65.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 7 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods. -Metrics/MethodLength: - Max: 21 - +# Offense count: 2 +# Configuration parameters: LengthThreshold. Metrics/CollectionLiteralLength: Exclude: - - 'spec/models/labware_creators/quadrant_split_plate_spec.rb' - 'spec/helpers/well_helpers_spec.rb' + - 'spec/models/labware_creators/quadrant_split_plate_spec.rb' + +# Offense count: 36 +# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Exclude: + - 'app/controllers/labware_controller.rb' + - 'app/controllers/pipeline_work_in_progress_controller.rb' + - 'app/controllers/plates_controller.rb' + - 'app/helpers/plate_helper.rb' + - 'app/models/concerns/labware_creators/donor_pooling_calculator.rb' + - 'app/models/concerns/presenters/extended_csv.rb' + - 'app/models/concerns/presenters/statemachine.rb' + - 'app/models/labware_creators/custom_tagged_plate.rb' + - 'app/models/labware_creators/final_tube.rb' + - 'app/models/labware_creators/multi_stamp_tubes.rb' + - 'app/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan.rb' + - 'app/models/labware_creators/pcr_cycles_binned_plate/csv_file/well_details_header_base.rb' + - 'app/models/labware_creators/pcr_cycles_binned_plate_for_t_nano_seq.rb' + - 'app/models/labware_creators/plate_split_to_tube_racks.rb' + - 'app/models/labware_creators/stamped_plate_adding_randomised_controls.rb' + - 'app/models/labware_creators/well_filter_allowing_partials.rb' + - 'app/models/pipeline_list.rb' + - 'app/models/print_job.rb' + - 'app/models/robots/splitting_robot.rb' + - 'app/models/sequencescape_submission.rb' + - 'app/models/utility/common_dilution_calculations.rb' + - 'app/models/utility/concentration_binning_calculator.rb' + - 'app/models/utility/normalised_binning_calculator.rb' + - 'app/models/validators/stock_state_validator.rb' + - 'config/initializers/settings.rb' + - 'spec/support/api_url_helper.rb' + - 'spec/support/factory_bot_extensions.rb' + - 'spec/support/feature_helpers.rb' + - 'spec/support/with_pmb_stubbed.rb' + +Style/NumericPredicate: + Exclude: + - 'lib/deployed_version.rb' diff --git a/.ruby-version b/.ruby-version index 818bd47ab..5ae69bd5f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.6 +3.2.5 diff --git a/Dockerfile b/Dockerfile index d7a584cc2..9e4720c98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.0.6-slim +FROM ruby:3.2.5-slim ARG bundlerWithout="development test lint" ARG yarnFlags="--production" diff --git a/Gemfile b/Gemfile index b818c04b8..4fbf055d1 100644 --- a/Gemfile +++ b/Gemfile @@ -67,4 +67,11 @@ group :lint do gem 'rubocop', require: false gem 'rubocop-performance', require: false gem 'rubocop-rails', require: false + + # Ruby dependencies specifically requested by prettier/plugin-ruby v4 + # https://github.com/prettier/plugin-ruby + gem 'prettier_print', require: false + gem 'syntax_tree', require: false + gem 'syntax_tree-haml', require: false + gem 'syntax_tree-rbs', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index 054373965..12080ecf5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -186,6 +186,10 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) + haml (6.3.0) + temple (>= 0.8.2) + thor + tilt hashdiff (1.1.0) hashie (5.0.0) i18n (1.14.5) @@ -247,6 +251,7 @@ GEM parser (3.3.4.0) ast (~> 2.4.1) racc + prettier_print (1.2.1) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) @@ -309,6 +314,8 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) + rbs (3.5.3) + logger rdoc (6.7.0) psych (>= 4.0.0) regexp_parser (2.9.2) @@ -386,7 +393,19 @@ GEM state_machines (0.6.0) stringio (3.1.1) strscan (3.1.0) + syntax_tree (6.2.0) + prettier_print (>= 1.2.0) + syntax_tree-haml (4.0.3) + haml (>= 5.2) + prettier_print (>= 1.2.1) + syntax_tree (>= 6.0.0) + syntax_tree-rbs (1.0.0) + prettier_print + rbs + syntax_tree (>= 2.0.1) + temple (0.10.3) thor (1.3.1) + tilt (2.4.0) timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -407,7 +426,7 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.8.1) + webrick (1.8.2) websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) @@ -432,6 +451,7 @@ DEPENDENCIES launchy oj pmb-client (= 0.1.0)! + prettier_print pry pry-byebug puma @@ -452,6 +472,9 @@ DEPENDENCIES simplecov-lcov sprint_client state_machines + syntax_tree + syntax_tree-haml + syntax_tree-rbs vite_rails vite_ruby web-console @@ -459,4 +482,4 @@ DEPENDENCIES yard BUNDLED WITH - 2.2.33 + 2.5.19 diff --git a/README.md b/README.md index 732f3bf45..10a10ffc7 100644 --- a/README.md +++ b/README.md @@ -28,19 +28,19 @@ You must have Docker Desktop installed on your machine. Then the only command you should need to run is: ```shell -docker-compose up +docker compose up ``` Variations on this command include: -- `docker-compose up -d` which starts the container as a background task - (freeing up the terminal). You can then use `docker-compose down` to turn it +- `docker compose up -d` which starts the container as a background task + (freeing up the terminal). You can then use `docker compose down` to turn it off again. -- `GENERATE_CONFIG=false docker-compose up` which will avoid running the +- `GENERATE_CONFIG=false docker compose up` which will avoid running the `config:generate` rake task as Limber is started. -- `PRECOMPILE_ASSETS=false docker-compose up` which will avoid precompiling the +- `PRECOMPILE_ASSETS=false docker compose up` which will avoid precompiling the assets as Limber is started. -- `docker-compose up --build` which forces a rebuild of the Docker image if your +- `docker compose up --build` which forces a rebuild of the Docker image if your changes to the Dockerfile or related scripts don't seem to be taking effect. Limber should be accessible via [http://localhost:3001](http://localhost:3001). @@ -158,7 +158,7 @@ Alternatively, run `./compile_build.sh` to compile the build files or run `yarn If during development changes do not seem to be taking effect, try: - Restart the application: -- Destroy and recreate the Docker container `docker-compose down && GENERATE_CONFIG=false docker-compose up -d` +- Destroy and recreate the Docker container `docker compose down && GENERATE_CONFIG=false docker compose up -d` - Rebuild the Docker image, particularly useful for changing dependencies - Clobber local resources `rails assets:clobber` @@ -167,7 +167,7 @@ If during development changes do not seem to be taking effect, try: The rest of the sections shown here were written for and apply to the native installation, but can also be used in the Docker container if required. In order to use Docker, it's probably best to create a shell in the running container. -Assuming you started the container via `docker-compose` you can access the shell +Assuming you started the container via `docker compose` you can access the shell using: ```shell diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb index 02b1ee3cf..1298857fc 100644 --- a/app/controllers/health_controller.rb +++ b/app/controllers/health_controller.rb @@ -2,5 +2,6 @@ # Controller to display a page stating that Limber is up, as a health check endpoint class HealthController < ApplicationController - def show; end + def show + end end diff --git a/app/controllers/labware_controller.rb b/app/controllers/labware_controller.rb index dccbe7d45..43bd0fd60 100644 --- a/app/controllers/labware_controller.rb +++ b/app/controllers/labware_controller.rb @@ -22,8 +22,9 @@ def show # rubocop:todo Metrics/AbcSize format.html { render @presenter.page } format.csv do render @presenter.csv - response.headers['Content-Disposition'] = - "attachment; filename=#{@presenter.filename(params['offset'])}" if @presenter.filename + response.headers[ + 'Content-Disposition' + ] = "attachment; filename=#{@presenter.filename(params['offset'])}" if @presenter.filename end format.json end @@ -35,7 +36,7 @@ def update # rubocop:todo Metrics/AbcSize notice = +"Labware: #{params[:labware_barcode]} has been changed to a state of #{params[:state].titleize}." notice << ' The customer will still be charged.' if update_params[2] - respond_to { |format| format.html { redirect_to(search_path, notice: notice) } } + respond_to { |format| format.html { redirect_to(search_path, notice:) } } rescue StateChangers::StateChangeError => e respond_to do |format| format.html { redirect_to(search_path, alert: e.message) } @@ -89,7 +90,7 @@ def state_changer_for(purpose_uuid, labware_uuid) end def presenter_for(labware) - presenter = Presenters.lookup_for(labware).new(labware: labware) + presenter = Presenters.lookup_for(labware).new(labware:) # TODO: {Y24-190} - Remove this line when the API v1 is removed from Presenters::ExtendedCsv presenter.api = api if presenter.respond_to?(:api=) diff --git a/app/controllers/robots_controller.rb b/app/controllers/robots_controller.rb index 0d2733d01..79fdbbf8a 100644 --- a/app/controllers/robots_controller.rb +++ b/app/controllers/robots_controller.rb @@ -73,9 +73,9 @@ def update_bed_labware_metadata(bed, robot_barcode) # @raise [Sequencescape::Api::ResourceNotFound] if the labware cannot be found # def labware_created_with_robot(labware_barcode, robot_barcode) - LabwareMetadata - .new(user_uuid: current_user_uuid, barcode: labware_barcode) - .update!(created_with_robot: robot_barcode) + LabwareMetadata.new(user_uuid: current_user_uuid, barcode: labware_barcode).update!( + created_with_robot: robot_barcode + ) end def verify diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 730af2e97..e3ecce169 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -7,7 +7,8 @@ class InputError < StandardError before_action :check_for_login!, only: [:my_plates] # rubocop:todo Rails/LexicallyScopedActionFilter - def new; end + def new + end def ongoing_plates # rubocop:todo Metrics/AbcSize plate_search = api.search.find(Settings.searches.fetch('Find plates')) @@ -56,7 +57,7 @@ def find_labware(barcode) end def find_qcable(barcode) - api.search.find(Settings.searches['Find qcable by barcode']).first(barcode: barcode) + api.search.find(Settings.searches['Find qcable by barcode']).first(barcode:) rescue Sequencescape::Api::ResourceNotFound => e raise e, "Sorry, could not find qcable with the barcode '#{barcode}'." end diff --git a/app/controllers/tubes/validate_paired_tubes_controller.rb b/app/controllers/tubes/validate_paired_tubes_controller.rb index ca929c7cd..db1c8980f 100644 --- a/app/controllers/tubes/validate_paired_tubes_controller.rb +++ b/app/controllers/tubes/validate_paired_tubes_controller.rb @@ -5,5 +5,6 @@ class Tubes::ValidatePairedTubesController < ApplicationController before_action :check_for_current_user! - def index; end + def index + end end diff --git a/app/frontend/entrypoints/pages/bed_verification.js b/app/frontend/entrypoints/pages/bed_verification.js index 79af43401..085885d0f 100644 --- a/app/frontend/entrypoints/pages/bed_verification.js +++ b/app/frontend/entrypoints/pages/bed_verification.js @@ -30,21 +30,21 @@ let newScanned = function (bed, labware) { .append( $(document.createElement('h3')) .attr('class', 'ui-li-heading') - .text('Bed: ' + bed) + .text('Bed: ' + bed), ) .append(closeIcon()) .append( $(document.createElement('p')) .attr('class', 'ui-li-desc') - .text('Labware: ' + labware) + .text('Labware: ' + labware), ) .append( $(document.createElement('input')) .attr('type', 'hidden') .attr('id', 'bed_labwares[' + bed + ']') .attr('name', 'bed_labwares[' + bed + '][]') - .val(labware) - ) + .val(labware), + ), ) SCAPE.robot_beds[bed] = SCAPE.robot_beds[bed] || [] SCAPE.robot_beds[bed].push(labware) @@ -162,7 +162,7 @@ $('#validate_layout').on('click', function () { }).fail(function (_data, _status) { SCAPE.message( 'The beds could not be validated. There may be network issues, or problems with Sequencescape.', - 'danger' + 'danger', ) fail() }) diff --git a/app/frontend/entrypoints/pages/multi_plate_pooling.js b/app/frontend/entrypoints/pages/multi_plate_pooling.js index 441a30133..af79ae588 100644 --- a/app/frontend/entrypoints/pages/multi_plate_pooling.js +++ b/app/frontend/entrypoints/pages/multi_plate_pooling.js @@ -284,7 +284,7 @@ SCAPE.renderSourceWells = function () { for (let wellName of wells) { well = $('.plate-id-' + plateIndex + ' .' + wellName) well.append( - SCAPE.newAliquot(capPoolOffset + poolNumber, WELLS_IN_COLUMN_MAJOR_ORDER[capPoolOffset + poolNumber]) + SCAPE.newAliquot(capPoolOffset + poolNumber, WELLS_IN_COLUMN_MAJOR_ORDER[capPoolOffset + poolNumber]), ) newInput = $(document.createElement('input')) diff --git a/app/frontend/entrypoints/pages/multi_tube_pooling.js b/app/frontend/entrypoints/pages/multi_tube_pooling.js index 1c55a96b5..95fc5c028 100644 --- a/app/frontend/entrypoints/pages/multi_tube_pooling.js +++ b/app/frontend/entrypoints/pages/multi_tube_pooling.js @@ -74,7 +74,7 @@ newScanned.prototype = { .append( $(document.createElement('h3')) .attr('class', 'ui-li-heading') - .text('Tube: ' + this.tubeBarcode) + .text('Tube: ' + this.tubeBarcode), ) .append($(document.createElement('div')).attr('class', 'tube_validation_report').text('Waiting...')) .append( @@ -82,8 +82,8 @@ newScanned.prototype = { .attr('type', 'hidden') .attr('id', 'tube[parents][' + this.tubeBarcode + ']') .attr('name', 'tube[parents][' + this.tubeBarcode + ']') - .val(1) - ) + .val(1), + ), ) return this.listElement }, @@ -140,7 +140,7 @@ tubeCollector = new statusCollector( }, function () { $('#tube_submit').prop('disabled', true) - } + }, ) $('.sibling-tube').each(function () { diff --git a/app/frontend/entrypoints/pages/tagged-plate.js b/app/frontend/entrypoints/pages/tagged-plate.js index f401b722f..83e1fe5ed 100644 --- a/app/frontend/entrypoints/pages/tagged-plate.js +++ b/app/frontend/entrypoints/pages/tagged-plate.js @@ -87,7 +87,7 @@ qcableLookup.prototype = { return function () { qc_lookup.message( 'The barcode could not be found. There may be network issues, or problems with Sequencescape.', - 'danger' + 'danger', ) } }, @@ -164,7 +164,7 @@ qcableLookup.prototype = { $(document.createElement('div')) .addClass('alert') .addClass('alert-' + status) - .text(message) + .text(message), ) }, dual: function () { @@ -182,7 +182,7 @@ let qcCollector = new tagStatusCollector( function (message) { $('#submit-summary').text(message) $('#plate_submit').prop('disabled', true) - } + }, ) new qcableLookup($('#plate_tag_plate_barcode'), qcCollector) diff --git a/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.spec.js b/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.spec.js index 037afeb9c..954bfc22e 100644 --- a/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.spec.js +++ b/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.spec.js @@ -833,8 +833,8 @@ describe('CustomTaggedPlate', () => { purpose_uuid: 'purpose-uuid', parent_uuid: 'parent-plate-uuid', tag_layout: { - tag_group: 'tag-1-group-uuid', - tag2_group: 'tag-2-group-uuid', + tag_group_uuid: 'tag-1-group-uuid', + tag2_group_uuid: 'tag-2-group-uuid', direction: 'column', walking_by: 'manual by plate', initial_tag: 1, diff --git a/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.vue b/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.vue index 07220aff2..8f2f2a123 100644 --- a/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.vue +++ b/app/frontend/javascript/custom-tagged-plate/components/CustomTaggedPlate.vue @@ -252,7 +252,7 @@ export default { this.parentWellSubmissionDetails, this.tagLayout, this.tagSubstitutions, - this.tagGroupOligoStrings + this.tagGroupOligoStrings, ) }, createButtonDisabled() { @@ -619,8 +619,8 @@ export default { purpose_uuid: this.purposeUuid, parent_uuid: this.parentUuid, tag_layout: { - tag_group: this.tag1GroupUuid, - tag2_group: this.tag2GroupUuid, + tag_group_uuid: this.tag1GroupUuid, + tag2_group_uuid: this.tag2GroupUuid, direction: this.direction, walking_by: this.walkingBy, initial_tag: initialTag, diff --git a/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.js b/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.js index c4aa5a516..3548377a6 100644 --- a/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.js +++ b/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.js @@ -23,7 +23,7 @@ function extractParentWellSubmissionDetails(parentPlate) { // TODO Replace this with generic limber logging when available // See https://github.com/sanger/limber/issues/836 console.error( - 'Tag clash functions: extractParentWellSubmissionDetails: Error: Submission Id not found for well' + 'Tag clash functions: extractParentWellSubmissionDetails: Error: Submission Id not found for well', ) return } @@ -94,7 +94,7 @@ function extractChildUsedOligos(parentUsedOligos, parentWellSubmDetails, tagLayo parentWellSubmDetails, tagLayout, tagSubstitutions, - tagGroupOligos + tagGroupOligos, ) ) { return {} @@ -135,7 +135,7 @@ function isValidChildUsedOligoParameters( parentWellSubmDetails, tagLayout, tagSubstitutions, - tagGroupOligos + tagGroupOligos, ) { let isValid = true diff --git a/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.spec.js b/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.spec.js index 40e1a90e7..b027dc95a 100644 --- a/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.spec.js +++ b/app/frontend/javascript/custom-tagged-plate/tagClashFunctions.spec.js @@ -362,7 +362,7 @@ describe('extractChildUsedOligos', () => { parentWellSubmDetsForPools, tagLayout, tagSubs, - tagGroupOligos + tagGroupOligos, ) expect(response).toEqual(exptSubmUsedTags) @@ -399,7 +399,7 @@ describe('extractChildUsedOligos', () => { parentWellSubmDetsForPools, tagLayout, tagSubs, - tagGroupOligos + tagGroupOligos, ) expect(response).toEqual(exptSubmUsedTags) @@ -435,7 +435,7 @@ describe('extractChildUsedOligos', () => { parentWellSubmDetsForPools, tagLayout, tagSubs, - tagGroupOligos + tagGroupOligos, ) expect(response).toEqual(exptSubmUsedTags) @@ -473,7 +473,7 @@ describe('extractChildUsedOligos', () => { parentWellSubmDetsForPools, tagLayout, tagSubs, - tagGroupOligos + tagGroupOligos, ) expect(response).toEqual(exptSubmUsedTags) @@ -509,7 +509,7 @@ describe('extractChildUsedOligos', () => { parentWellSubmDetsForPools, tagLayout, tagSubs, - tagGroupOligos + tagGroupOligos, ) expect(response).toEqual(exptSubmUsedTags) diff --git a/app/frontend/javascript/custom-tagged-plate/tagLayoutFunctions.js b/app/frontend/javascript/custom-tagged-plate/tagLayoutFunctions.js index 580e8ec0a..341bd7ff0 100644 --- a/app/frontend/javascript/custom-tagged-plate/tagLayoutFunctions.js +++ b/app/frontend/javascript/custom-tagged-plate/tagLayoutFunctions.js @@ -147,7 +147,7 @@ const calculateTagLayout = function (data) { data.tagsPerWell, (well, relIndex, absIndex) => { return walkingByFunctions[data.walkingBy](well, tags, relIndex, absIndex, offset, counters) - } + }, ) } diff --git a/app/frontend/javascript/labware-custom-metadata/components/LabwareCustomMetadataAddForm.spec.js b/app/frontend/javascript/labware-custom-metadata/components/LabwareCustomMetadataAddForm.spec.js index 4b70ceb96..251efe18d 100644 --- a/app/frontend/javascript/labware-custom-metadata/components/LabwareCustomMetadataAddForm.spec.js +++ b/app/frontend/javascript/labware-custom-metadata/components/LabwareCustomMetadataAddForm.spec.js @@ -28,7 +28,7 @@ describe('LabwareCustomMetadataAddForm', () => { global.fetch = vi.fn().mockReturnValue( Promise.resolve({ json: () => Promise.resolve(data), - }) + }), ) // This is a workaround for the following warning: @@ -80,7 +80,7 @@ describe('LabwareCustomMetadataAddForm', () => { // expect(wrapper.find('#RT DFD Syringe Lot Number').exists()).toBe(true) expect(wrapper.find('#labware_custom_metadata_submit_button').exists()).toBe(true) expect(wrapper.find('#labware_custom_metadata_submit_button').text()).toEqual( - 'Add Custom Metadata to Sequencescape' + 'Add Custom Metadata to Sequencescape', ) }) }) diff --git a/app/frontend/javascript/lib/global_message_system.js b/app/frontend/javascript/lib/global_message_system.js index 82fea0d7a..f8aa308e3 100644 --- a/app/frontend/javascript/lib/global_message_system.js +++ b/app/frontend/javascript/lib/global_message_system.js @@ -16,7 +16,7 @@ SCAPE.message = function (message, status) { $(document.createElement('div')) .addClass('alert') .addClass('alert-' + status) - .text(message) + .text(message), ) } diff --git a/app/frontend/javascript/multi-stamp/components/MultiStampLibrarySplitter.js b/app/frontend/javascript/multi-stamp/components/MultiStampLibrarySplitter.js index 29d0a256a..be6912133 100644 --- a/app/frontend/javascript/multi-stamp/components/MultiStampLibrarySplitter.js +++ b/app/frontend/javascript/multi-stamp/components/MultiStampLibrarySplitter.js @@ -95,7 +95,7 @@ export default Vue.extend({ headers: { 'X-Requested-With': 'XMLHttpRequest' }, data: payload, }) - }) + }), ) .then((responses) => { const response = responses[0] diff --git a/app/frontend/javascript/multi-stamp/components/PrimerPanelFilter.vue b/app/frontend/javascript/multi-stamp/components/PrimerPanelFilter.vue index fad3d94b4..005de6dbe 100644 --- a/app/frontend/javascript/multi-stamp/components/PrimerPanelFilter.vue +++ b/app/frontend/javascript/multi-stamp/components/PrimerPanelFilter.vue @@ -39,7 +39,7 @@ export default { return [] } const primerPanelsIterable = Array.from(primerPanelsByPlate.values()).reduce((accu, current) => - accu.filter((val) => current.includes(val)) + accu.filter((val) => current.includes(val)), ) return primerPanelsIterable }, diff --git a/app/frontend/javascript/multi-stamp/components/shared_examples/multi_stamp_instance.shared_spec.js b/app/frontend/javascript/multi-stamp/components/shared_examples/multi_stamp_instance.shared_spec.js index 660316d2f..058fab0bb 100644 --- a/app/frontend/javascript/multi-stamp/components/shared_examples/multi_stamp_instance.shared_spec.js +++ b/app/frontend/javascript/multi-stamp/components/shared_examples/multi_stamp_instance.shared_spec.js @@ -171,7 +171,7 @@ const sharedSpecs = (args) => { expect(wrapper.vm.duplicatedTransfers.length).toEqual(1) expect(wrapper.vm.transfersError).toEqual( - 'This would result in multiple transfers into the same well. Check if the source plates (DN1S) have more than one active submission.' + 'This would result in multiple transfers into the same well. Check if the source plates (DN1S) have more than one active submission.', ) }) diff --git a/app/frontend/javascript/pipeline-graph/index.js b/app/frontend/javascript/pipeline-graph/index.js index 658a6b454..9b3d477f8 100644 --- a/app/frontend/javascript/pipeline-graph/index.js +++ b/app/frontend/javascript/pipeline-graph/index.js @@ -204,7 +204,7 @@ const applyMouseEvents = function () {
${content}
- ` + `, ) return document.querySelector('.graph-tooltip') }, diff --git a/app/frontend/javascript/plain-javascript/tag-animations.js b/app/frontend/javascript/plain-javascript/tag-animations.js index 37abc6e77..2a96413fb 100644 --- a/app/frontend/javascript/plain-javascript/tag-animations.js +++ b/app/frontend/javascript/plain-javascript/tag-animations.js @@ -27,5 +27,5 @@ document.addEventListener( } } }, - false + false, ) diff --git a/app/frontend/javascript/plain-javascript/threshold-well-failing.js b/app/frontend/javascript/plain-javascript/threshold-well-failing.js index 9d3061587..9c161191f 100644 --- a/app/frontend/javascript/plain-javascript/threshold-well-failing.js +++ b/app/frontend/javascript/plain-javascript/threshold-well-failing.js @@ -51,7 +51,7 @@ document.addEventListener('DOMContentLoaded', () => { // The well must meet all thresholds. const wellInvalid = Object.entries(threshold).some( - ([qcKey, thresholdValue]) => parseFloat(well.dataset[qcKey]) < thresholdValue + ([qcKey, thresholdValue]) => parseFloat(well.dataset[qcKey]) < thresholdValue, ) well.checked = wellInvalid diff --git a/app/frontend/javascript/qc-information/components/QcInformation.vue b/app/frontend/javascript/qc-information/components/QcInformation.vue index fdcceb2a9..fcfd7d556 100644 --- a/app/frontend/javascript/qc-information/components/QcInformation.vue +++ b/app/frontend/javascript/qc-information/components/QcInformation.vue @@ -108,7 +108,7 @@ export default { }, () => { this.state = 'failure' - } + }, ) }, }, diff --git a/app/frontend/javascript/session_scripts.js b/app/frontend/javascript/session_scripts.js index e72d80654..925bfc5a6 100644 --- a/app/frontend/javascript/session_scripts.js +++ b/app/frontend/javascript/session_scripts.js @@ -20,7 +20,7 @@ logIn = function () { if (user_name !== wasLoggedIn) { updateUserName(user_name) warning( - 'The logged in user has changed since this page was last viewed. You are now logged in as ' + user_name + '.' + 'The logged in user has changed since this page was last viewed. You are now logged in as ' + user_name + '.', ) } } else { diff --git a/app/frontend/javascript/shared/components/AssetLookupByUuid.spec.js b/app/frontend/javascript/shared/components/AssetLookupByUuid.spec.js index a1990a362..32dafca05 100644 --- a/app/frontend/javascript/shared/components/AssetLookupByUuid.spec.js +++ b/app/frontend/javascript/shared/components/AssetLookupByUuid.spec.js @@ -34,7 +34,7 @@ describe('AssetLookupByUuid', () => { filter: { uuid: assetUuid }, fields: {}, }, - { data: [] } // no plates found + { data: [] }, // no plates found ) const wrapper = wrapperFactoryPlate(api) @@ -59,7 +59,7 @@ describe('AssetLookupByUuid', () => { filter: { uuid: assetUuid }, fields: {}, }, - goodPlate + goodPlate, ) const wrapper = wrapperFactoryPlate(api) diff --git a/app/frontend/javascript/shared/components/LabwareScan.spec.js b/app/frontend/javascript/shared/components/LabwareScan.spec.js index ddfb7fc39..7ec99fb41 100644 --- a/app/frontend/javascript/shared/components/LabwareScan.spec.js +++ b/app/frontend/javascript/shared/components/LabwareScan.spec.js @@ -138,7 +138,7 @@ describe('LabwareScan', () => { receptacles: 'uuid', }, }, - goodTube + goodTube, ) wrapper.find('input').setValue('DN12345') @@ -170,7 +170,7 @@ describe('LabwareScan', () => { receptacles: 'uuid', }, }, - nullTube + nullTube, ) const wrapper = wrapperFactoryTube(api) @@ -202,7 +202,7 @@ describe('LabwareScan', () => { receptacles: 'uuid', }, }, - pendingTube + pendingTube, ) wrapper.find('input').setValue('Good barcode') @@ -263,7 +263,7 @@ describe('LabwareScan', () => { status: 500, }, ], - } + }, ) const wrapper = wrapperFactoryTube(api) @@ -312,7 +312,7 @@ describe('LabwareScan', () => { plates: 'labware_barcode,uuid,number_of_rows,number_of_columns', }, }, - goodPlate + goodPlate, ) wrapper.find('input').setValue('DN12345') @@ -343,7 +343,7 @@ describe('LabwareScan', () => { plates: 'labware_barcode,uuid,number_of_rows,number_of_columns', }, }, - nullPlate + nullPlate, ) const wrapper = wrapperFactoryPlate(api) @@ -373,7 +373,7 @@ describe('LabwareScan', () => { plates: 'labware_barcode,uuid,number_of_rows,number_of_columns', }, }, - badPlate + badPlate, ) wrapper.find('input').setValue('Good barcode') @@ -428,7 +428,7 @@ describe('LabwareScan', () => { status: 500, }, ], - } + }, ) const wrapper = wrapperFactoryPlate(api) diff --git a/app/frontend/javascript/shared/components/mixins/devourSelect.spec.js b/app/frontend/javascript/shared/components/mixins/devourSelect.spec.js index 7ea4886fe..9e3c60d5a 100644 --- a/app/frontend/javascript/shared/components/mixins/devourSelect.spec.js +++ b/app/frontend/javascript/shared/components/mixins/devourSelect.spec.js @@ -99,7 +99,7 @@ describe('DevourSelect mixin', () => { status: 500, }, ], - } + }, ) const wrapper = wrapperFactory(api) diff --git a/app/frontend/javascript/shared/components/plateScanValidators.js b/app/frontend/javascript/shared/components/plateScanValidators.js index 82e89792e..843fa0f8a 100644 --- a/app/frontend/javascript/shared/components/plateScanValidators.js +++ b/app/frontend/javascript/shared/components/plateScanValidators.js @@ -306,13 +306,13 @@ const checkAllLibraryRequestsWithSameReadySubmissions = () => { return (plate) => { const [firstWellSubmissionIds, ...remainingWellsSubmissionIds] = getAllLibrarySubmissionsWithMatchingStateForPlate( plate, - 'ready' + 'ready', ) // To compare lists we use _.isEqual because there is no equivalent function for lists in // plain Javascript if ( remainingWellsSubmissionIds.every((currentElemSubmissionIds) => - _.isEqual(firstWellSubmissionIds.sort(), currentElemSubmissionIds.sort()) + _.isEqual(firstWellSubmissionIds.sort(), currentElemSubmissionIds.sort()), ) ) { return validScanMessage() diff --git a/app/frontend/javascript/shared/devourApiValidators.js b/app/frontend/javascript/shared/devourApiValidators.js index ceb6ef19b..abece2c81 100644 --- a/app/frontend/javascript/shared/devourApiValidators.js +++ b/app/frontend/javascript/shared/devourApiValidators.js @@ -25,7 +25,7 @@ const hasExpectedProperties = (expectedProperties) => { for (const currTagGroup of results) { const hasAllProperties = expectedProperties.every((property) => - Object.prototype.hasOwnProperty.call(currTagGroup, property) + Object.prototype.hasOwnProperty.call(currTagGroup, property), ) if (!hasAllProperties) { diff --git a/app/frontend/javascript/shared/transfersLayouts.js b/app/frontend/javascript/shared/transfersLayouts.js index 43be7b1ef..e1500ff06 100644 --- a/app/frontend/javascript/shared/transfersLayouts.js +++ b/app/frontend/javascript/shared/transfersLayouts.js @@ -54,7 +54,7 @@ const quadrantTransfers = function (requestsWithPlates) { plateObj.index, well.position.name, quadrantOffsets.rowOffset, - quadrantOffsets.colOffset + quadrantOffsets.colOffset, ) const transfer = { request: request, @@ -189,7 +189,7 @@ const buildSequentialTransfersArray = function (transferRequests) { // const buildSequentialLibrarySplitTransfersArray = function ( transferRequests, - numberOfWellsForEachSourcePlateInColumnOrder = 24 + numberOfWellsForEachSourcePlateInColumnOrder = 24, ) { const libraryTypes = [] return transferRequests.map((requestWithPlate) => { diff --git a/app/frontend/javascript/shared/tubeTransferVolumes.js b/app/frontend/javascript/shared/tubeTransferVolumes.js index 342f1cb00..4ca595ecf 100644 --- a/app/frontend/javascript/shared/tubeTransferVolumes.js +++ b/app/frontend/javascript/shared/tubeTransferVolumes.js @@ -13,10 +13,10 @@ const tubeMostRecentMolarity = function (tube) { const qcResults = tube?.receptacle?.qc_results const molarityEntries = qcResults?.filter((result) => result.key === 'molarity' && result.units === 'nM') const sortedByCreatedAt = molarityEntries?.sort( - (resultA, resultB) => -1 * ('' + resultA.created_at).localeCompare(resultB.created_at) + (resultA, resultB) => -1 * ('' + resultA.created_at).localeCompare(resultB.created_at), ) const sortedByIds = sortedByCreatedAt?.sort((resultA, resultB) => - parseInt(resultA.id) > parseInt(resultB.id) ? -1 : 1 + parseInt(resultA.id) > parseInt(resultB.id) ? -1 : 1, ) const mostRecentMolarityResult = sortedByIds?.[0] return mostRecentMolarityResult ? parseFloat(mostRecentMolarityResult?.value) : undefined diff --git a/app/frontend/javascript/test_support/factories/json_factory.js b/app/frontend/javascript/test_support/factories/json_factory.js index 56e4400c9..4490c68ef 100644 --- a/app/frontend/javascript/test_support/factories/json_factory.js +++ b/app/frontend/javascript/test_support/factories/json_factory.js @@ -71,7 +71,7 @@ const extractAssociations = (resource_config, attributeValues, resourceUrl) => { return { relationships, included } }, - { relationships: {}, included: [] } + { relationships: {}, included: [] }, ) } @@ -94,7 +94,7 @@ const buildMany = (associationName, associationValue) => { includeData.push(...singleResource.includeData) return { relationData, includeData } }, - { relationData: { data: [] }, includeData: [] } + { relationData: { data: [] }, includeData: [] }, ) } @@ -168,7 +168,7 @@ const jsonCollectionFactory = (factoryName, collectionAttributes, options = {}) included.push(...json.included) return { data, included } }, - { data: [], included: [] } + { data: [], included: [] }, ) return { diff --git a/app/frontend/javascript/test_support/factories/json_factory.spec.js b/app/frontend/javascript/test_support/factories/json_factory.spec.js index 036869523..bf9cbc073 100644 --- a/app/frontend/javascript/test_support/factories/json_factory.spec.js +++ b/app/frontend/javascript/test_support/factories/json_factory.spec.js @@ -242,7 +242,7 @@ describe('jsonCollectionFactory', () => { ], { base: 'assets/123/comments', - } + }, ) expect(json).toEqual({ diff --git a/app/frontend/javascript/test_support/factories/plate_factory.js b/app/frontend/javascript/test_support/factories/plate_factory.js index 53a9ac1d3..fc7d0b880 100644 --- a/app/frontend/javascript/test_support/factories/plate_factory.js +++ b/app/frontend/javascript/test_support/factories/plate_factory.js @@ -26,7 +26,7 @@ const plateFactory = function (options = {}) { position: { name: indexToName(iteration, 8) }, }, ..._wellOptions, - }) + }), ), } return { ...plateDefaults, ...(plateOptions || {}) } diff --git a/app/frontend/javascript/test_support/mock_api.spec.js b/app/frontend/javascript/test_support/mock_api.spec.js index f33ac7d1e..b0b795a80 100644 --- a/app/frontend/javascript/test_support/mock_api.spec.js +++ b/app/frontend/javascript/test_support/mock_api.spec.js @@ -42,7 +42,7 @@ describe('mockApi', () => { status: 500, }, ], - } + }, ) let response = await api.devour diff --git a/app/frontend/stylesheets/limber/spinner.scss b/app/frontend/stylesheets/limber/spinner.scss index ab8e7ad23..d2430970e 100644 --- a/app/frontend/stylesheets/limber/spinner.scss +++ b/app/frontend/stylesheets/limber/spinner.scss @@ -36,57 +36,111 @@ 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } 5%, 95% { - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } 10%, 59% { - box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, - -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + -0.087em -0.825em 0 -0.42em, + -0.173em -0.812em 0 -0.44em, + -0.256em -0.789em 0 -0.46em, + -0.297em -0.775em 0 -0.477em; } 20% { - box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, - -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + -0.338em -0.758em 0 -0.42em, + -0.555em -0.617em 0 -0.44em, + -0.671em -0.488em 0 -0.46em, + -0.749em -0.34em 0 -0.477em; } 38% { - box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, + box-shadow: + 0 -0.83em 0 -0.4em, + -0.377em -0.74em 0 -0.42em, + -0.645em -0.522em 0 -0.44em, + -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em; } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } } @keyframes load6 { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } 5%, 95% { - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } 10%, 59% { - box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, - -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + -0.087em -0.825em 0 -0.42em, + -0.173em -0.812em 0 -0.44em, + -0.256em -0.789em 0 -0.46em, + -0.297em -0.775em 0 -0.477em; } 20% { - box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, - -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + -0.338em -0.758em 0 -0.42em, + -0.555em -0.617em 0 -0.44em, + -0.671em -0.488em 0 -0.46em, + -0.749em -0.34em 0 -0.477em; } 38% { - box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, + box-shadow: + 0 -0.83em 0 -0.4em, + -0.377em -0.74em 0 -0.42em, + -0.645em -0.522em 0 -0.44em, + -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em; } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); - box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + box-shadow: + 0 -0.83em 0 -0.4em, + 0 -0.83em 0 -0.42em, + 0 -0.83em 0 -0.44em, + 0 -0.83em 0 -0.46em, + 0 -0.83em 0 -0.477em; } } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8475a0dd6..9d2c29a09 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -27,8 +27,8 @@ def environment Rails.env end - def each_robot(&block) - Robots.each_robot(&block) + def each_robot(&) + Robots.each_robot(&) end # Return a list of unique pipeline group names diff --git a/app/helpers/barcode_labels_helper.rb b/app/helpers/barcode_labels_helper.rb index 069a4851d..7446ace27 100644 --- a/app/helpers/barcode_labels_helper.rb +++ b/app/helpers/barcode_labels_helper.rb @@ -19,7 +19,7 @@ def barcode_printing_form( ) # Is redirection_url needed? - locals = { print_job: print_job, printers: printers, labels: labels, redirection_url: redirection_url } + locals = { print_job:, printers:, labels:, redirection_url: } render(partial: 'labware/barcode_printing_form', locals: locals) end diff --git a/app/helpers/labware_helper.rb b/app/helpers/labware_helper.rb index faca8f25a..efa383c77 100644 --- a/app/helpers/labware_helper.rb +++ b/app/helpers/labware_helper.rb @@ -2,11 +2,11 @@ module LabwareHelper # rubocop:todo Style/Documentation def state_change_form(presenter) - render partial: 'labware/state_change', locals: { presenter: presenter } + render partial: 'labware/state_change', locals: { presenter: } end def simple_state_change_form(presenter) - render partial: 'labware/simple_state_change', locals: { presenter: presenter } + render partial: 'labware/simple_state_change', locals: { presenter: } end STANDARD_COLOURS = (1..384).map { |i| "colour-#{i}" } diff --git a/app/helpers/page_helper.rb b/app/helpers/page_helper.rb index 71678f7fa..49f774667 100644 --- a/app/helpers/page_helper.rb +++ b/app/helpers/page_helper.rb @@ -5,8 +5,8 @@ def flash_messages render(partial: 'application/flash_messages') end - def grouping(_data_role, options = {}, &block) - tag.div(**options, &block) + def grouping(_data_role, options = {}, &) + tag.div(**options, &) end private :grouping @@ -23,13 +23,13 @@ def page(id, css_class = nil, prevent_row: false, &block) end # Main body of the page, provides information about what you HAVE - def content(&block) - grouping(:content, class: 'content-main', &block) + def content(&) + grouping(:content, class: 'content-main', &) end # Provides information about what you can DO - def sidebar(&block) - grouping(:sidebar, class: 'sidebar content-secondary', &block) + def sidebar(&) + grouping(:sidebar, class: 'sidebar content-secondary', &) end def card(title: nil, css_class: '', without_block: false, id: nil, &block) @@ -43,11 +43,11 @@ def card(title: nil, css_class: '', without_block: false, id: nil, &block) end end - def jumbotron(jumbotron_id = nil, options = {}, &block) + def jumbotron(jumbotron_id = nil, options = {}, &) options[:class] ||= +'' options[:class] << ' jumbotron' options[:id] = jumbotron_id - tag.div(**options, &block) + tag.div(**options, &) end # eg. state_badge('pending') diff --git a/app/models/concerns/presenters/creation_behaviour.rb b/app/models/concerns/presenters/creation_behaviour.rb index e457c9d67..2e0ba7204 100644 --- a/app/models/concerns/presenters/creation_behaviour.rb +++ b/app/models/concerns/presenters/creation_behaviour.rb @@ -23,10 +23,9 @@ def purposes_of_type(type) end def construct_buttons(scope) - scope.map do |purpose_uuid, purpose_settings| - LabwareCreators - .class_for(purpose_uuid) - .creator_button( + scope + .map do |purpose_uuid, purpose_settings| + LabwareCreators.class_for(purpose_uuid).creator_button( creator: LabwareCreators.class_for(purpose_uuid), parent_uuid: uuid, parent: labware, @@ -35,7 +34,8 @@ def construct_buttons(scope) type: purpose_settings.asset_type, filters: purpose_settings.filters || {} ) - end.force + end + .force end def active_pipelines diff --git a/app/models/concerns/presenters/extended_csv.rb b/app/models/concerns/presenters/extended_csv.rb index 5130312e6..bf634d05a 100644 --- a/app/models/concerns/presenters/extended_csv.rb +++ b/app/models/concerns/presenters/extended_csv.rb @@ -59,14 +59,7 @@ def transfers_for_csv # rubocop:todo Metrics/AbcSize destination_barcode = ct.destination.barcode.machine transfers = ct.transfers.reverse_merge(all_wells).sort { |a, b| split_location(a.first) <=> split_location(b.first) } - { - source_ean: source_ean, - source_barcode: source_barcode, - source_stock: source_stock, - destination_ean: destination_ean, - destination_barcode: destination_barcode, - transfers: transfers - } + { source_ean:, source_barcode:, source_stock:, destination_ean:, destination_barcode:, transfers: } end end end diff --git a/app/models/concerns/presenters/statemachine/state_does_not_allow_child_creation.rb b/app/models/concerns/presenters/statemachine/state_does_not_allow_child_creation.rb index 88f264d89..93f447a5e 100644 --- a/app/models/concerns/presenters/statemachine/state_does_not_allow_child_creation.rb +++ b/app/models/concerns/presenters/statemachine/state_does_not_allow_child_creation.rb @@ -5,7 +5,7 @@ module Presenters::Statemachine module StateDoesNotAllowChildCreation extend ActiveSupport::Concern included do - def control_additional_creation(&block) + def control_additional_creation(&) # Does nothing because you can't! end end diff --git a/app/models/labware_creators/baited_plate.rb b/app/models/labware_creators/baited_plate.rb index b4a49ccc6..ebddd05c7 100644 --- a/app/models/labware_creators/baited_plate.rb +++ b/app/models/labware_creators/baited_plate.rb @@ -25,12 +25,13 @@ def plate end def bait_library_layout_preview - @bait_library_layout_preview ||= api.bait_library_layout.preview!(plate: parent_uuid, user: user_uuid).layout + @bait_library_layout_preview ||= + Sequencescape::Api::V2::BaitLibraryLayout.preview(plate_uuid: parent_uuid, user_uuid: user_uuid).first.layout end def create_labware! create_plate_with_standard_transfer! do |child| - api.bait_library_layout.create!(plate: child.uuid, user: user_uuid) + Sequencescape::Api::V2::BaitLibraryLayout.create!(plate_uuid: child.uuid, user_uuid: user_uuid) end end diff --git a/app/models/labware_creators/base.rb b/app/models/labware_creators/base.rb index 86a6557e4..5a3278750 100644 --- a/app/models/labware_creators/base.rb +++ b/app/models/labware_creators/base.rb @@ -35,9 +35,9 @@ def self.support_parent?(_parent) # We pull out the api as the first argument as it ensures # we'll always have it available, even during assignment of # other attributes. Otherwise we end up relying on hash order. - def initialize(api, *args) + def initialize(api, *) @api = api - super(*args) + super(*) end def plate_to_walk @@ -117,9 +117,7 @@ def create_plate_from_parent! end def transfer!(attributes) - Sequencescape::Api::V2::Transfer.create!( - attributes.merge(transfer_template_uuid: transfer_template_uuid, user_uuid: user_uuid) - ) + Sequencescape::Api::V2::Transfer.create!(attributes.merge(transfer_template_uuid:, user_uuid:)) end def transfer_material_from_parent!(child_uuid) diff --git a/app/models/labware_creators/common_file_handling/csv_file/row_base.rb b/app/models/labware_creators/common_file_handling/csv_file/row_base.rb index eaf8d46ad..a0cc9ce96 100644 --- a/app/models/labware_creators/common_file_handling/csv_file/row_base.rb +++ b/app/models/labware_creators/common_file_handling/csv_file/row_base.rb @@ -76,7 +76,7 @@ def check_for_invalid_characters return if empty? @row_data.each_with_index do |cell, i| - next if cell_is_blank?(cell) + next if cell.nil? next if cell_is_valid_utf8?(cell) add_invalid_character_error(i) @@ -85,12 +85,6 @@ def check_for_invalid_characters private - def cell_is_blank?(cell) - # NB. cannot use cell.blank? as triggers an exception if cell contains the unusual characters - # are trying to spot - cell.nil? || cell.strip.empty? - end - def cell_is_valid_utf8?(cell) cell.bytes.all? { |byte| byte < 128 } && cell.dup.force_encoding('UTF-8').valid_encoding? end diff --git a/app/models/labware_creators/custom_tagged_plate.rb b/app/models/labware_creators/custom_tagged_plate.rb index 8892620e5..d7d161c94 100644 --- a/app/models/labware_creators/custom_tagged_plate.rb +++ b/app/models/labware_creators/custom_tagged_plate.rb @@ -18,10 +18,10 @@ class CustomTaggedPlate < Base { tag_plate: %i[asset_uuid template_uuid state], tag_layout: [ - :user, - :plate, - :tag_group, - :tag2_group, + :user_uuid, + :plate_uuid, + :tag_group_uuid, + :tag2_group_uuid, :direction, :walking_by, :initial_tag, @@ -40,21 +40,18 @@ def tag_plate=(params) @tag_plate = OpenStruct.new(params) # rubocop:todo Style/OpenStructUse end - def initialize(*args, &block) + def initialize(*args, &) super parent.populate_wells_with_pool end def create_plate! # rubocop:todo Metrics/AbcSize @child = - api - .pooled_plate_creation - .create!( - child_purpose: purpose_uuid, - user: user_uuid, - parents: [parent_uuid, tag_plate.asset_uuid].compact_blank - ) - .child + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: [parent_uuid, tag_plate.asset_uuid].compact_blank, + user_uuid: user_uuid + ).child transfer_material_from_parent!(@child.uuid) @@ -107,7 +104,7 @@ def tag_layout_attributes def create_labware! create_plate! do |plate_uuid| - api.tag_layout.create!(tag_layout_attributes.merge(plate: plate_uuid, user: user_uuid)) + Sequencescape::Api::V2::TagLayout.create!(tag_layout_attributes.merge(plate_uuid:, user_uuid:)) end end end diff --git a/app/models/labware_creators/final_tube.rb b/app/models/labware_creators/final_tube.rb index afa8fa9ff..1177d5d3b 100644 --- a/app/models/labware_creators/final_tube.rb +++ b/app/models/labware_creators/final_tube.rb @@ -19,8 +19,8 @@ class FinalTube < Base validate :all_parents_and_only_parents?, if: :barcodes_provided? validate :custom_input_expected, unless: :no_pooling_required? - def each_sibling(&block) - siblings.each(&block) + def each_sibling(&) + siblings.each(&) end def all_ready? diff --git a/app/models/labware_creators/merged_plate.rb b/app/models/labware_creators/merged_plate.rb index d6bd17bfb..8f1be6c3f 100644 --- a/app/models/labware_creators/merged_plate.rb +++ b/app/models/labware_creators/merged_plate.rb @@ -51,10 +51,10 @@ def barcodes=(barcodes) private def create_plate_from_parent! - api.pooled_plate_creation.create!( - child_purpose: purpose_uuid, - user: user_uuid, - parents: source_plates.map(&:uuid) + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: source_plates.map(&:uuid), + user_uuid: user_uuid ) end diff --git a/app/models/labware_creators/multi_plate_pool.rb b/app/models/labware_creators/multi_plate_pool.rb index 6beeaacc5..597447a01 100644 --- a/app/models/labware_creators/multi_plate_pool.rb +++ b/app/models/labware_creators/multi_plate_pool.rb @@ -17,10 +17,12 @@ class MultiPlatePool < Base private def create_labware! - plate_creation = - api.pooled_plate_creation.create!(parents: transfers.keys, child_purpose: purpose_uuid, user: user_uuid) - - @child = plate_creation.child + @child = + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: transfers.keys, + user_uuid: user_uuid + ).child api.bulk_transfer.create!(user: user_uuid, well_transfers: well_transfers) diff --git a/app/models/labware_creators/multi_stamp.rb b/app/models/labware_creators/multi_stamp.rb index 6cb8a9810..04d09ccbc 100644 --- a/app/models/labware_creators/multi_stamp.rb +++ b/app/models/labware_creators/multi_stamp.rb @@ -30,10 +30,12 @@ class MultiStamp < Base # rubocop:todo Style/Documentation private def create_labware! - plate_creation = - api.pooled_plate_creation.create!(parents: parent_uuids, child_purpose: purpose_uuid, user: user_uuid) - - @child = plate_creation.child + @child = + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: parent_uuids, + user_uuid: user_uuid + ).child transfer_material_from_parent!(@child.uuid) diff --git a/app/models/labware_creators/multi_stamp_tubes.rb b/app/models/labware_creators/multi_stamp_tubes.rb index aa3b153d0..c596f399a 100644 --- a/app/models/labware_creators/multi_stamp_tubes.rb +++ b/app/models/labware_creators/multi_stamp_tubes.rb @@ -41,13 +41,14 @@ def create_labware! create_and_build_submission return if errors.size.positive? - plate_creation = - api.pooled_plate_creation.create!(parents: parent_uuids, child_purpose: purpose_uuid, user: user_uuid) + @child = + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: parent_uuids, + user_uuid: user_uuid + ).child - @child = plate_creation.child - child_v2 = Sequencescape::Api::V2.plate_with_wells(@child.uuid) - - transfer_material_from_parent!(child_v2) + transfer_material_from_parent! yield(@child) if block_given? true @@ -87,15 +88,12 @@ def parent_tubes Sequencescape::Api::V2::Tube.find_all(uuid: parent_uuids, includes: 'receptacle,aliquots,aliquots.study') end - def transfer_material_from_parent!(child_plate) - api.transfer_request_collection.create!( - user: user_uuid, - transfer_requests: transfer_request_attributes(child_plate) - ) + def transfer_material_from_parent! + api.transfer_request_collection.create!(user: user_uuid, transfer_requests: transfer_request_attributes) end - def transfer_request_attributes(child_plate) - transfers.map { |transfer| request_hash(transfer, child_plate) } + def transfer_request_attributes + transfers.map { |transfer| request_hash(transfer) } end def source_tube_outer_request_uuid(tube) @@ -108,13 +106,13 @@ def source_tube_outer_request_uuid(tube) pending_reqs.first.uuid || nil end - def request_hash(transfer, child_plate) + def request_hash(transfer) tube = Sequencescape::Api::V2::Tube.find_by(uuid: transfer[:source_tube]) { 'source_asset' => transfer[:source_asset], 'target_asset' => - child_plate.wells.detect { |child_well| child_well.location == transfer.dig(:new_target, :location) }&.uuid, + @child.wells.detect { |child_well| child_well.location == transfer.dig(:new_target, :location) }&.uuid, 'outer_request' => source_tube_outer_request_uuid(tube) } end diff --git a/app/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan.rb b/app/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan.rb index d1aab1bd2..471889ac4 100644 --- a/app/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan.rb +++ b/app/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan.rb @@ -65,13 +65,14 @@ def save # # @return [Boolean] true if the child plate was created successfully. def create_labware! - plate_creation = - api.pooled_plate_creation.create!(parents: parent_tube_uuids, child_purpose: purpose_uuid, user: user_uuid) + @child = + Sequencescape::Api::V2::PooledPlateCreation.create!( + child_purpose_uuid: purpose_uuid, + parent_uuids: parent_tube_uuids, + user_uuid: user_uuid + ).child - @child = plate_creation.child - child_v2 = Sequencescape::Api::V2.plate_with_wells(@child.uuid) - - transfer_material_from_parent!(child_v2) + transfer_material_from_parent! yield(@child) if block_given? true @@ -232,29 +233,23 @@ def tube_has_expected_active_request?(tube_in_db) end # Transfers material from the parent tubes to the given child plate. - # @param child_plate [Sequencescape::Api::V2::Plate] The plate to transfer material to. - def transfer_material_from_parent!(child_plate) - api.transfer_request_collection.create!( - user: user_uuid, - transfer_requests: transfer_request_attributes(child_plate) - ) + def transfer_material_from_parent! + api.transfer_request_collection.create!(user: user_uuid, transfer_requests: transfer_request_attributes) end # Returns an array of hashes representing the transfer requests for the given child plate. # Each hash includes the UUIDs of the parent tube and child well, and the UUID of the outer request. - # @param child_plate [Sequencescape::Api::V2::Plate] The plate to get the transfer requests for. # @return [Array] An array of hashes representing the transfer requests. - def transfer_request_attributes(child_plate) + def transfer_request_attributes parent_tubes.each_with_object([]) do |(foreign_barcode, parent_tube), tube_transfers| - tube_transfers << - request_hash( - parent_tube.uuid, - child_plate - .wells - .detect { |child_well| child_well.location == csv_file.location_by_barcode_details[foreign_barcode] } - &.uuid, - { outer_request: source_tube_outer_request_uuid(parent_tube) } - ) + tube_transfers << request_hash( + parent_tube.uuid, + @child + .wells + .detect { |child_well| child_well.location == csv_file.location_by_barcode_details[foreign_barcode] } + &.uuid, + { outer_request: source_tube_outer_request_uuid(parent_tube) } + ) end end diff --git a/app/models/labware_creators/pcr_cycles_binned_plate/csv_file_for_duplex_seq.rb b/app/models/labware_creators/pcr_cycles_binned_plate/csv_file_for_duplex_seq.rb index c6b95285e..b7ff6d86f 100644 --- a/app/models/labware_creators/pcr_cycles_binned_plate/csv_file_for_duplex_seq.rb +++ b/app/models/labware_creators/pcr_cycles_binned_plate/csv_file_for_duplex_seq.rb @@ -14,8 +14,14 @@ module PcrCyclesBinnedPlate class CsvFileForDuplexSeq < CsvFileBase delegate :submit_for_sequencing_column, :sub_pool_column, :coverage_column, to: :well_details_header_row - FIELDS_FOR_WELL_DETAILS = %w[diluent_volume pcr_cycles submit_for_sequencing sub_pool coverage sample_volume] - .freeze + FIELDS_FOR_WELL_DETAILS = %w[ + diluent_volume + pcr_cycles + submit_for_sequencing + sub_pool + coverage + sample_volume + ].freeze # Returns the contents of the header row for the well detail columns def well_details_header_row diff --git a/app/models/labware_creators/plate_split_to_tube_racks.rb b/app/models/labware_creators/plate_split_to_tube_racks.rb index 8ccec4303..ca7208100 100644 --- a/app/models/labware_creators/plate_split_to_tube_racks.rb +++ b/app/models/labware_creators/plate_split_to_tube_racks.rb @@ -317,7 +317,7 @@ def ancestor_stock_tubes def locate_ancestor_tubes purpose_name = purpose_config[:ancestor_stock_tube_purpose_name] - ancestor_results = parent.ancestors.where(purpose_name: purpose_name) + ancestor_results = parent.ancestors.where(purpose_name:) return {} if ancestor_results.blank? ancestor_results.each_with_object({}) do |ancestor_result, tube_list| @@ -408,13 +408,12 @@ def parent_wells_for_contingency # @param tube_attributes [Hash] A hash of attributes to use for the created tubes. # @return [Hash] A hash of the created tubes indexed by name. def create_tubes(tube_purpose_uuid, number_of_tubes, tube_attributes) - api - .specific_tube_creation + Sequencescape::Api::V2::SpecificTubeCreation .create!( - user: user_uuid, - parent: parent_uuid, - child_purposes: [tube_purpose_uuid] * number_of_tubes, - tube_attributes: tube_attributes + child_purpose_uuids: [tube_purpose_uuid] * number_of_tubes, + parent_uuids: [parent_uuid], + tube_attributes: tube_attributes, + user_uuid: user_uuid ) .children .index_by(&:name) @@ -580,7 +579,7 @@ def generate_tube_attributes(tube_type, csv_file, wells) # @param dest_tube_posn [String] The position of the destination tube. # @return [Hash] A hash of details to use for generating a tube name. def name_for_details_hash(prefix, stock_tube_bc, dest_tube_posn) - { prefix: prefix, stock_tube_bc: stock_tube_bc, dest_tube_posn: dest_tube_posn } + { prefix:, stock_tube_bc:, dest_tube_posn: } end # Generates a human-readable name for a tube based on the given details hash. @@ -654,9 +653,10 @@ def add_contingency_tube_metadata # @param tube_details [Hash] The tube details hash from the tube rack scan file. # @return [void] def add_tube_metadata(child_tube, tube_posn, tube_details) - LabwareMetadata - .new(user_uuid: user_uuid, barcode: child_tube.barcode.machine) - .update!(tube_rack_barcode: tube_details['tube_rack_barcode'], tube_rack_position: tube_posn) + LabwareMetadata.new(user_uuid: user_uuid, barcode: child_tube.barcode.machine).update!( + tube_rack_barcode: tube_details['tube_rack_barcode'], + tube_rack_position: tube_posn + ) end # Generates a transfer request hash for the given source well UUID, target tube UUID, and additional parameters. diff --git a/app/models/labware_creators/pooled_tubes_base.rb b/app/models/labware_creators/pooled_tubes_base.rb index f55e8bc3a..abc4a7d10 100644 --- a/app/models/labware_creators/pooled_tubes_base.rb +++ b/app/models/labware_creators/pooled_tubes_base.rb @@ -20,13 +20,12 @@ def create_labware! end def create_child_stock_tubes - api - .specific_tube_creation + Sequencescape::Api::V2::SpecificTubeCreation .create!( - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid] * pool_uuids.length, - tube_attributes: tube_attributes + child_purpose_uuids: [purpose_uuid] * pool_uuids.length, + parent_uuids: [parent_uuid], + tube_attributes: tube_attributes, + user_uuid: user_uuid ) .children .index_by(&:name) @@ -41,12 +40,11 @@ def transfer_request_attributes # this currently assumes that pool_identifier will be the submission_uuid # (it would have always been, historically) pool.each do |location| - transfer_requests << - request_hash( - well_locations.fetch(location).uuid, - child_stock_tubes.fetch(name_for(pool)).uuid, - pool_identifier - ) + transfer_requests << request_hash( + well_locations.fetch(location).uuid, + child_stock_tubes.fetch(name_for(pool)).uuid, + pool_identifier + ) end end end diff --git a/app/models/labware_creators/pooled_tubes_by_sample.rb b/app/models/labware_creators/pooled_tubes_by_sample.rb index 29121318a..f4c00f7ce 100644 --- a/app/models/labware_creators/pooled_tubes_by_sample.rb +++ b/app/models/labware_creators/pooled_tubes_by_sample.rb @@ -47,13 +47,12 @@ def parent_v1 # Have we made this class so cardinal-specific (e.g. lookup of ancestor vac tubes) that it cannot be re-used? def create_child_stock_tubes - api - .specific_tube_creation + Sequencescape::Api::V2::SpecificTubeCreation .create!( - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid] * pool_uuids.length, - tube_attributes: tube_attributes + child_purpose_uuids: [purpose_uuid] * pool_uuids.length, + parent_uuids: [parent_uuid], + tube_attributes: tube_attributes, + user_uuid: user_uuid ) .children .index_by(&:name) @@ -69,12 +68,11 @@ def name_for_details(pool_identifier) def transfer_request_attributes pools.each_with_object([]) do |(pool_identifier, pool), transfer_requests| pool.each do |location| - transfer_requests << - request_hash( - well_locations.fetch(location).uuid, - child_stock_tubes.fetch(name_for(name_for_details(pool_identifier))).uuid, - pool_identifier - ) + transfer_requests << request_hash( + well_locations.fetch(location).uuid, + child_stock_tubes.fetch(name_for(name_for_details(pool_identifier))).uuid, + pool_identifier + ) end end end @@ -186,7 +184,7 @@ def ancestor_stock_tubes def locate_ancestor_tubes purpose_name = purpose_config[:ancestor_stock_tube_purpose_name] - ancestor_results = parent.ancestors.where(purpose_name: purpose_name) + ancestor_results = parent.ancestors.where(purpose_name:) return {} if ancestor_results.blank? ancestor_results.each_with_object({}) do |ancestor_result, tube_list| diff --git a/app/models/labware_creators/pooled_tubes_by_submission_with_phi_x.rb b/app/models/labware_creators/pooled_tubes_by_submission_with_phi_x.rb index f0d6103f0..cef106449 100644 --- a/app/models/labware_creators/pooled_tubes_by_submission_with_phi_x.rb +++ b/app/models/labware_creators/pooled_tubes_by_submission_with_phi_x.rb @@ -15,13 +15,12 @@ class PooledTubesBySubmissionWithPhiX < PooledTubesBySubmission attr_accessor :spikedbuffer_tube_barcode def create_child_stock_tubes - api - .specific_tube_creation + Sequencescape::Api::V2::SpecificTubeCreation .create!( - user: user_uuid, - parents: parents, - child_purposes: [purpose_uuid] * pool_uuids.length, - tube_attributes: tube_attributes + child_purpose_uuids: [purpose_uuid] * pool_uuids.length, + parent_uuids: parents, + tube_attributes: tube_attributes, + user_uuid: user_uuid ) .children .index_by(&:name) diff --git a/app/models/labware_creators/pooled_tubes_from_whole_plates.rb b/app/models/labware_creators/pooled_tubes_from_whole_plates.rb index 41a09f490..937e23569 100644 --- a/app/models/labware_creators/pooled_tubes_from_whole_plates.rb +++ b/app/models/labware_creators/pooled_tubes_from_whole_plates.rb @@ -15,15 +15,14 @@ class PooledTubesFromWholePlates < Base def create_labware! # Create a single tube - # TODO: This should link to multiple parents in production + # TODO: {Y24-190} See if we can do all the transfers as part of the SpecificTubeCreation instead of separately. @child = - api - .specific_tube_creation + Sequencescape::Api::V2::SpecificTubeCreation .create!( - user: user_uuid, - parent: parents.first.uuid, - child_purposes: [purpose_uuid], - tube_attributes: [{ name: "#{stock_plate_barcode}+" }] + child_purpose_uuids: [purpose_uuid], + parent_uuids: [parents.first.uuid], + tube_attributes: [{ name: "#{stock_plate_barcode}+" }], + user_uuid: user_uuid ) .children .first @@ -40,6 +39,10 @@ def stock_plate_barcode "#{parents.first.stock_plate.barcode.prefix}#{parents.first.stock_plate.barcode.number}" end + def redirection_target + TubeProxy.new(@child.uuid) + end + # TODO: This should probably be asynchronous def available_plates @search_options = OngoingPlate.new(purposes: [parent.plate_purpose.uuid], include_used: false, states: ['passed']) diff --git a/app/models/labware_creators/quadrant_split_plate.rb b/app/models/labware_creators/quadrant_split_plate.rb index 0ae504e88..befb86a62 100644 --- a/app/models/labware_creators/quadrant_split_plate.rb +++ b/app/models/labware_creators/quadrant_split_plate.rb @@ -45,7 +45,7 @@ def add_stock_barcode_metadata(plates) # rubocop:todo Metrics/AbcSize metadata = LabwareMetadata.new(barcode: merger_plate.barcode.machine).metadata plates.each_with_index do |plate, index| stock_barcode = stock_barcode_from_quadrant(index, metadata) || "* #{plate.barcode.human}" - LabwareMetadata.new(user_uuid: user_uuid, barcode: plate.barcode.machine).update!(stock_barcode: stock_barcode) + LabwareMetadata.new(user_uuid: user_uuid, barcode: plate.barcode.machine).update!(stock_barcode:) end end diff --git a/app/models/labware_creators/quadrant_stamp_base.rb b/app/models/labware_creators/quadrant_stamp_base.rb index 60ced9c7c..87c0d3b99 100644 --- a/app/models/labware_creators/quadrant_stamp_base.rb +++ b/app/models/labware_creators/quadrant_stamp_base.rb @@ -46,8 +46,9 @@ def source_plates_by_quadrant transfers.each do |transfer| target_well_location = transfer.dig(:new_target, :location) target_well_quadrant = WellHelpers.well_quadrant(target_well_location) - source_plates_uuids[target_well_quadrant] = transfer[:source_plate] if source_plates_uuids[target_well_quadrant] - .nil? + source_plates_uuids[target_well_quadrant] = transfer[:source_plate] if source_plates_uuids[ + target_well_quadrant + ].nil? end source_plates_uuids end @@ -57,7 +58,7 @@ def stock_barcodes_by_quadrant source_plates_by_quadrant.each_with_index do |uuid, index| next if uuid.nil? - source_plate = Sequencescape::Api::V2::Plate.find_by(uuid: uuid) + source_plate = Sequencescape::Api::V2::Plate.find_by(uuid:) stock_barcode = source_plate&.stock_plate&.barcode&.human quadrants[:"stock_barcode_q#{index}"] = stock_barcode unless stock_barcode.nil? end diff --git a/app/models/labware_creators/tagged_plate.rb b/app/models/labware_creators/tagged_plate.rb index 088a8f10c..bd2366bab 100644 --- a/app/models/labware_creators/tagged_plate.rb +++ b/app/models/labware_creators/tagged_plate.rb @@ -30,7 +30,7 @@ def tag_plate=(params) @tag_plate = QcableObject.new(params[:asset_uuid], params[:template_uuid]) end - def initialize(*args, &block) + def initialize(*args, &) super parent.populate_wells_with_pool end diff --git a/app/models/labware_metadata.rb b/app/models/labware_metadata.rb index 90df6af17..e6675b7d4 100644 --- a/app/models/labware_metadata.rb +++ b/app/models/labware_metadata.rb @@ -8,7 +8,7 @@ def initialize(params = {}) @user = Sequencescape::Api::V2::User.find(uuid: @user_uuid).first unless @user_uuid.nil? @barcode = params.fetch(:barcode, nil) if barcode.present? - @labware = Sequencescape::Api::V2::Labware.find(barcode: barcode).first + @labware = Sequencescape::Api::V2::Labware.find(barcode:).first else @labware = params.fetch(:labware, nil) raise ArgumentError, 'Parameters labware or barcode missing' if labware.nil? diff --git a/app/models/presenters/plate_presenter.rb b/app/models/presenters/plate_presenter.rb index 9874478d2..e8baf963e 100644 --- a/app/models/presenters/plate_presenter.rb +++ b/app/models/presenters/plate_presenter.rb @@ -91,7 +91,7 @@ def label end def tubes_and_sources - @tubes_and_sources ||= Presenters::TubesWithSources.build(wells: wells, pools: pools) + @tubes_and_sources ||= Presenters::TubesWithSources.build(wells:, pools:) yield(@tubes_and_sources) if block_given? && @tubes_and_sources.tubes? @tubes_and_sources end diff --git a/app/models/print_job.rb b/app/models/print_job.rb index f1a7eeae3..eac78d4c3 100644 --- a/app/models/print_job.rb +++ b/app/models/print_job.rb @@ -24,10 +24,14 @@ def execute end def print_to_pmb + # Ensure the template exists before attempting to print + label_template_id = pmb_label_template_id + return false if label_template_id.nil? + job = PMB::PrintJob.new( printer_name: printer_name, - label_template_id: pmb_label_template_id, + label_template_id: label_template_id, labels: { body: (labels * number_of_copies) } @@ -134,10 +138,17 @@ def number_of_copies=(number) private def pmb_label_template_id - # This isn't a rails finder; so we disable the cop. - PMB::LabelTemplate.where(name: get_label_template_by_service('PMB')).first.id + pmb_label_template = get_label_template_by_service('PMB') + template_id = PMB::LabelTemplate.where(name: pmb_label_template).first&.id + if template_id.nil? + errors.add(:pmb, "Unable to find label template: #{pmb_label_template}") + nil + else + template_id + end rescue JsonApiClient::Errors::ConnectionError errors.add(:pmb, 'PrintMyBarcode service is down') + nil end def get_label_template_by_service(print_service) diff --git a/app/models/robots/bed/invalid.rb b/app/models/robots/bed/invalid.rb index f707b1606..d881210d2 100644 --- a/app/models/robots/bed/invalid.rb +++ b/app/models/robots/bed/invalid.rb @@ -7,7 +7,8 @@ def initialize(barcode) @barcode = barcode end - def load(_plate_barcodes); end + def load(_plate_barcodes) + end def plate nil diff --git a/app/models/robots/bed/plate_to_tube_racks_bed.rb b/app/models/robots/bed/plate_to_tube_racks_bed.rb index 6e013c6ad..02e360c84 100644 --- a/app/models/robots/bed/plate_to_tube_racks_bed.rb +++ b/app/models/robots/bed/plate_to_tube_racks_bed.rb @@ -17,9 +17,9 @@ class PlateToTubeRacksBed < Robots::Bed::Base def labware_created_with_robot(robot_barcode) # RobotController uses machine barcode for initialising LabwareMetadata labware.tubes.each do |tube| - LabwareMetadata - .new(user_uuid: user_uuid, barcode: tube.barcode.machine) - .update!(created_with_robot: robot_barcode) + LabwareMetadata.new(user_uuid: user_uuid, barcode: tube.barcode.machine).update!( + created_with_robot: robot_barcode + ) end end diff --git a/app/models/sequencescape_submission.rb b/app/models/sequencescape_submission.rb index fa53d444b..911130a55 100644 --- a/app/models/sequencescape_submission.rb +++ b/app/models/sequencescape_submission.rb @@ -117,7 +117,7 @@ def asset_groups_for_orders_creation def generate_orders asset_groups_for_orders_creation.map do |asset_group| - order_parameters = { request_options: request_options, user: user }.merge(asset_group) + order_parameters = { request_options:, user: }.merge(asset_group) submission_template.orders.create!(order_parameters) end end diff --git a/app/models/utility/pcr_cycles_csv_file_upload_config_base.rb b/app/models/utility/pcr_cycles_csv_file_upload_config_base.rb index cbd55caa5..5427f7397 100644 --- a/app/models/utility/pcr_cycles_csv_file_upload_config_base.rb +++ b/app/models/utility/pcr_cycles_csv_file_upload_config_base.rb @@ -29,8 +29,8 @@ def initialize_pipeline_specific_methods raise '#initialize_pipeline_specific_methods must be implemented on subclasses' end - def create_method(name, &block) - self.class.send(:define_method, name, &block) + def create_method(name, &) + self.class.send(:define_method, name, &) end def submit_for_sequencing_valid_values diff --git a/app/models/validators/failed_validator.rb b/app/models/validators/failed_validator.rb index de774df76..9d963438a 100644 --- a/app/models/validators/failed_validator.rb +++ b/app/models/validators/failed_validator.rb @@ -11,8 +11,8 @@ def validate(presenter) affected_range = WellHelpers.formatted_range(problem_wells, presenter.size) presenter.errors.add( - :libraries, - "on this plate have already been failed (#{affected_range}). You should not carry out further work. " \ + :submission, + "on this plate has already been failed (#{affected_range}). You should not carry out further work. " \ 'Any further work conducted from this plate will run into issues at the end of the pipeline.' ) end diff --git a/app/models/validators/in_progress_validator.rb b/app/models/validators/in_progress_validator.rb index d9b00921e..f7dfc3b85 100644 --- a/app/models/validators/in_progress_validator.rb +++ b/app/models/validators/in_progress_validator.rb @@ -7,8 +7,8 @@ def validate(presenter) return true unless presenter.labware.any_complete_requests? presenter.errors.add( - :libraries, - 'on this plate have already been completed. ' \ + :submission, + '(active) is not present for this labware. ' \ 'Any further work conducted from this plate may run into issues at the end of the pipeline.' ) end diff --git a/app/sequencescape/sequencescape/api/v2.rb b/app/sequencescape/sequencescape/api/v2.rb index df5dc2391..5b06efc3e 100644 --- a/app/sequencescape/sequencescape/api/v2.rb +++ b/app/sequencescape/sequencescape/api/v2.rb @@ -30,10 +30,7 @@ module Sequencescape::Api::V2 # @return [Sequencescape::V2::Api::Labware] Found labware object # def self.minimal_labware_by_barcode(barcode, select: :uuid) - Sequencescape::Api::V2::Labware - .where(barcode: barcode) - .select(tube_racks: select, plates: select, tubes: select) - .first + Sequencescape::Api::V2::Labware.where(barcode:).select(tube_racks: select, plates: select, tubes: select).first end # sample_description added into includes here for use in bioscan plate label creation @@ -53,7 +50,7 @@ def self.additional_plates_for_presenter(query) end def self.plate_with_wells(uuid) - Plate.includes('wells').find(uuid: uuid).first + Plate.includes('wells').find(uuid:).first end def self.tube_rack_for_presenter(query) @@ -67,14 +64,11 @@ def self.tube_rack_for_presenter(query) end def self.plate_for_completion(uuid) - Plate.includes('wells.aliquots.request.submission,wells.aliquots.request.request_type').find(uuid: uuid).first + Plate.includes('wells.aliquots.request.submission,wells.aliquots.request.request_type').find(uuid:).first end def self.tube_for_completion(uuid) - Tube - .includes('receptacle.aliquots.request.submission,receptacle.aliquots.request.request_type') - .find(uuid: uuid) - .first + Tube.includes('receptacle.aliquots.request.submission,receptacle.aliquots.request.request_type').find(uuid:).first end def self.plate_with_custom_includes(include_params, search_params) diff --git a/app/sequencescape/sequencescape/api/v2/bait_library_layout.rb b/app/sequencescape/sequencescape/api/v2/bait_library_layout.rb new file mode 100644 index 000000000..bb5bb251d --- /dev/null +++ b/app/sequencescape/sequencescape/api/v2/bait_library_layout.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# bait library layout resource +class Sequencescape::Api::V2::BaitLibraryLayout < Sequencescape::Api::V2::Base + custom_endpoint :preview, on: :collection, request_method: :post +end diff --git a/app/sequencescape/sequencescape/api/v2/base.rb b/app/sequencescape/sequencescape/api/v2/base.rb index 2cb7a15e8..933fb5686 100644 --- a/app/sequencescape/sequencescape/api/v2/base.rb +++ b/app/sequencescape/sequencescape/api/v2/base.rb @@ -12,8 +12,12 @@ class SequencescapePaginator < JsonApiClient::Paginating::NestedParamPaginator # set the api base url in an abstract base class self.site = Limber::Application.config.api.v2.connection_options.url - connection.faraday.headers['X-Sequencescape-Client-Id'] = - Limber::Application.config.api.v2.connection_options.authorisation + connection.faraday.headers['X-Sequencescape-Client-Id'] = Limber::Application + .config + .api + .v2 + .connection_options + .authorisation self.plate = false self.tube = false self.paginator = SequencescapePaginator diff --git a/app/sequencescape/sequencescape/api/v2/pooled_plate_creation.rb b/app/sequencescape/sequencescape/api/v2/pooled_plate_creation.rb new file mode 100644 index 000000000..ef2d1d631 --- /dev/null +++ b/app/sequencescape/sequencescape/api/v2/pooled_plate_creation.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Represents a pooled plate creation in Limber via the Sequencescape API +class Sequencescape::Api::V2::PooledPlateCreation < Sequencescape::Api::V2::Base + has_one :child, class_name: 'Sequencescape::Api::V2::Plate' + has_many :parents, class_name: 'Sequencescape::Api::V2::Labware' + has_one :user, class_name: 'Sequencescape::Api::V2::User' +end diff --git a/app/sequencescape/sequencescape/api/v2/receptacle.rb b/app/sequencescape/sequencescape/api/v2/receptacle.rb index b940df168..deb61afbc 100644 --- a/app/sequencescape/sequencescape/api/v2/receptacle.rb +++ b/app/sequencescape/sequencescape/api/v2/receptacle.rb @@ -11,7 +11,8 @@ def latest_molarity end def latest_qc(key:, units:) - qc_results.to_a # Convert to array to resolve any api queries. Otherwise select fails to work. + qc_results + .to_a # Convert to array to resolve any api queries. Otherwise select fails to work. .select { |qc| qc.key.casecmp(key).zero? } .select { |qc| qc.units.casecmp(units).zero? } .max_by(&:created_at) diff --git a/app/sequencescape/sequencescape/api/v2/shared/has_requests.rb b/app/sequencescape/sequencescape/api/v2/shared/has_requests.rb index 289ed0d27..e4af355c8 100644 --- a/app/sequencescape/sequencescape/api/v2/shared/has_requests.rb +++ b/app/sequencescape/sequencescape/api/v2/shared/has_requests.rb @@ -70,7 +70,7 @@ def requests_in_progress(request_types_to_complete: nil) # Based on in_progress requests def in_progress_submission_uuids(request_types_to_complete: nil) - requests_in_progress(request_types_to_complete: request_types_to_complete).flat_map(&:submission_uuid).uniq + requests_in_progress(request_types_to_complete:).flat_map(&:submission_uuid).uniq end def all_requests diff --git a/app/sequencescape/sequencescape/api/v2/specific_tube_creation.rb b/app/sequencescape/sequencescape/api/v2/specific_tube_creation.rb new file mode 100644 index 000000000..4b3235552 --- /dev/null +++ b/app/sequencescape/sequencescape/api/v2/specific_tube_creation.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Represents a specific tube creation in Limber via the Sequencescape API +class Sequencescape::Api::V2::SpecificTubeCreation < Sequencescape::Api::V2::Base + has_many :children, class_name: 'Sequencescape::Api::V2::Tube' + has_many :parents, class_name: 'Sequencescape::Api::V2::Labware' + has_one :user, class_name: 'Sequencescape::Api::V2::User' +end diff --git a/app/sequencescape/sequencescape/api/v2/tag_layout.rb b/app/sequencescape/sequencescape/api/v2/tag_layout.rb new file mode 100644 index 000000000..2e5f92fda --- /dev/null +++ b/app/sequencescape/sequencescape/api/v2/tag_layout.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# tag layout resource +class Sequencescape::Api::V2::TagLayout < Sequencescape::Api::V2::Base +end diff --git a/app/sequencescape/sequencescape/api/v2/well.rb b/app/sequencescape/sequencescape/api/v2/well.rb index a8782d472..6a57e1bbc 100644 --- a/app/sequencescape/sequencescape/api/v2/well.rb +++ b/app/sequencescape/sequencescape/api/v2/well.rb @@ -44,7 +44,8 @@ def latest_cell_viability end def latest_qc(key:, units:) - qc_results.to_a # Convert to array to resolve any api queries. Otherwise select fails to work. + qc_results + .to_a # Convert to array to resolve any api queries. Otherwise select fails to work. .select { |qc| qc.key.casecmp(key).zero? } .select { |qc| qc.units.casecmp(units).zero? } .max_by(&:created_at) diff --git a/app/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb b/app/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb index 92fa28913..b432a7670 100644 --- a/app/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb +++ b/app/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb @@ -45,9 +45,9 @@ src_location, @plate.labware_barcode.human, mapping[dest_well.location], - '%0.2f' % source_well_volume, - '%0.2f' % sample_volume, - '%0.2f' % pbs_volume + '%0.1f' % source_well_volume, + '%0.1f' % sample_volume, + '%0.1f' % pbs_volume ] end %> diff --git a/app/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb b/app/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb index f278ed8e2..9afc22e87 100644 --- a/app/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb +++ b/app/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb @@ -24,6 +24,7 @@ study_required_number_of_cells_key = args[:study_required_number_of_cells_key] maximum_sample_volume = 60.0 # microlitres + minimum_sample_volume = 5.0 # microlitres resuspension_volume_per_sample = 2.2 # microlitres minimum_resuspension_volume = 10.0 # microlitres millilitres_to_microlitres = 1_000.0 @@ -52,14 +53,14 @@ # Calculate the sample volume required for the number of cells - required_volume = [millilitres_to_microlitres * required_number_of_cells / cell_count.value.to_i, maximum_sample_volume].min + required_volume = (millilitres_to_microlitres * required_number_of_cells / cell_count.value.to_f).clamp(minimum_sample_volume, maximum_sample_volume) transfer_request_data << [ src_barcode, src_location, @plate.labware_barcode.human, dest_well.location, - '%0.2f' % required_volume, + '%0.1f' % required_volume, # We pass in the required number of cells so that we can calculate the resuspension volume later required_number_of_cells ] @@ -74,7 +75,7 @@ required_number_of_cells = data[5] resuspension_volume = [(samples_in_pool * required_number_of_cells * wastage_accountment) / desired_chip_loading_concentration, minimum_resuspension_volume].max # Replace required number of cells with resuspension volume - data[5] = '%0.2f' % resuspension_volume + data[5] = '%0.1f' % resuspension_volume data end %> diff --git a/app/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb b/app/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb index 2c099d73e..375cfa9be 100644 --- a/app/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb +++ b/app/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb @@ -31,7 +31,7 @@ @plate.labware_barcode.human, well.location, well.name, - '%0.2f' % source_well_volume + '%0.1f' % source_well_volume ] rows_array << row end diff --git a/app/views/exports/pbmc_bank_tubes_content_report.csv.erb b/app/views/exports/pbmc_bank_tubes_content_report.csv.erb index 96969e020..a63003273 100644 --- a/app/views/exports/pbmc_bank_tubes_content_report.csv.erb +++ b/app/views/exports/pbmc_bank_tubes_content_report.csv.erb @@ -10,7 +10,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', @@ -68,7 +68,7 @@ child_tube_v2.barcode, # FluidX barcode child_tube_v2.created_at, # Extraction and freeze date destination, # Sequencing or contingency - source_well.latest_live_cell_count&.value, # Cell count + source_well.latest_total_cell_count&.value, # Total Cell Count source_well.latest_cell_viability&.value, # Viability volume, # Volume source_well.aliquots.first.study.name, # Study name diff --git a/app/views/labware/_relatives_list.html.erb b/app/views/labware/_relatives_list.html.erb index dadcd9544..6d07d5040 100644 --- a/app/views/labware/_relatives_list.html.erb +++ b/app/views/labware/_relatives_list.html.erb @@ -1,14 +1,18 @@ <%# locals: (presenter:) %> +<% + valid_parents = presenter.labware.parents&.filter{ |parent| parent.purpose.present? } || [] + valid_children = presenter.labware.children&.filter{ |child| child.purpose.present? } || [] +%>
Parents - <%= content_tag :span, presenter.labware.parents.size, class: "badge badge-pill badge-secondary" if presenter.labware.parents&.any? %> + <%= content_tag :span, valid_parents.size, class: "badge badge-pill badge-secondary" %>
- <% if presenter.labware.parents&.any? { |parent| parent.purpose.present? } %> - <%= render partial: 'labware/parent_labware_item', collection: presenter.labware.parents, as: :labware %> + <% if valid_parents %> + <%= render partial: 'labware/parent_labware_item', collection: valid_parents, as: :labware %> <% else %>
No parents found
<% end %> @@ -16,12 +20,12 @@
Children - <%= content_tag :span, presenter.labware.children.size, class: "badge badge-pill badge-secondary" if presenter.labware.children&.any? %> + <%= content_tag :span, valid_children.size, class: "badge badge-pill badge-secondary" %>
- <% if presenter.labware.children&.any? { |child| child.purpose.present? } %> - <%= render partial: 'labware/child_labware_item', collection: presenter.labware.children, as: :labware, locals: { presenter: presenter, open_in_new_window: true } %> + <% if valid_children %> + <%= render partial: 'labware/child_labware_item', collection: valid_children, as: :labware, locals: { presenter: presenter, open_in_new_window: true } %> <% else %>
No children found
<% end %> diff --git a/compile-build b/compile-build index aefb1c1ec..f5ff94575 100755 --- a/compile-build +++ b/compile-build @@ -10,9 +10,9 @@ bundle exec rake assets:clobber echo 'Compiling assets' bundle exec rake assets:precompile echo 'Generating sha' -git rev-parse HEAD > REVISION -git tag -l --points-at HEAD --sort -version:refname | head -1 > TAG -git rev-parse --abbrev-ref HEAD > BRANCH +echo ${1:-$(git rev-parse HEAD)} > REVISION +echo ${2:-$(git tag -l --points-at HEAD --sort -version:refname | head -1)} > TAG +echo ${3:-$(git rev-parse --abbrev-ref HEAD)} > BRANCH echo 'Compiling tar.gz' tar \ --exclude='*.swp' \ diff --git a/config/pipelines/high_throughput_anospp.wip.yml b/config/pipelines/high_throughput_anospp.yml similarity index 100% rename from config/pipelines/high_throughput_anospp.wip.yml rename to config/pipelines/high_throughput_anospp.yml diff --git a/config/purposes/lcm_triomics.wip.yml b/config/purposes/lcm_triomics.wip.yml index 289e8a979..14a059f9b 100644 --- a/config/purposes/lcm_triomics.wip.yml +++ b/config/purposes/lcm_triomics.wip.yml @@ -47,6 +47,7 @@ LCMT EM NaOH Denat: :stock_plate: false :cherrypickable_target: false :input_plate: false + :presenter_class: Presenters::PermissivePresenter :size: 96 LCMT EM APOBEC Deam: :asset_type: plate diff --git a/config/purposes/scrna_core_cdna_prep.yml b/config/purposes/scrna_core_cdna_prep.yml index 2bb7489d8..ec992d5e0 100644 --- a/config/purposes/scrna_core_cdna_prep.yml +++ b/config/purposes/scrna_core_cdna_prep.yml @@ -32,11 +32,11 @@ LRC PBMC Defrost PBS: :qc_thresholds: viability: units: '%' - default_threshold: 50 + default_threshold: 65 total_cell_count: name: Total cell count units: 'cells/ml' - default_threshold: 400000 + default_threshold: 500000 decimal_places: 0 :stock_plate: false :input_plate: false @@ -48,7 +48,12 @@ LRC PBMC Pools: :qc_thresholds: viability: units: '%' - default_threshold: 70 + default_threshold: 65 + total_cell_count: + name: Total cell count + units: 'cells/ml' + default_threshold: 500000 + decimal_places: 0 :presenter_class: name: Presenters::DonorPoolingPlatePresenter args: diff --git a/config/purposes/scrna_core_cell_extraction.yml b/config/purposes/scrna_core_cell_extraction.yml index 112f7cc0e..8039dd289 100644 --- a/config/purposes/scrna_core_cell_extraction.yml +++ b/config/purposes/scrna_core_cell_extraction.yml @@ -80,11 +80,11 @@ LRC PBMC Bank: :qc_thresholds: viability: units: '%' - default_threshold: 50 - live_cell_count: - name: Live cell count + default_threshold: 85 + total_cell_count: + name: Total cell count units: 'cells/ml' - default_threshold: 400000 + default_threshold: 650000 decimal_places: 0 # FluidX tube for freezing and output of cell banking protocol LRC Bank Seq: diff --git a/config/robots.rb b/config/robots.rb index 940dba882..bd18dc2bf 100644 --- a/config/robots.rb +++ b/config/robots.rb @@ -1179,64 +1179,22 @@ } ) - # WIP: Activate for ANOSPP release # GBS pipeline bed verification # Allows use of either GBS or ANOSPP 96-well source plates # GBS-96 Stock or LANS-96 Lysate to GBS PCR1 # Transfers 4:1 (1-4 source 96-well plates of either type to 1 destination 384-well plate) - # custom_robot( - # 'mosquito-gbs-96-stock-to-gbs-pcr1', - # name: 'Mosquito GBS-96 Stock or LANS-96 Lysate => GBS PCR1', - # beds: { - # bed(1).barcode => { - # purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], - # states: %w[passed qc_complete], - # child: bed(3).barcode, - # label: 'Bed 1' - # }, - # bed(2).barcode => { - # purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], - # states: %w[passed qc_complete], - # child: bed(3).barcode, - # label: 'Bed 2' - # }, - # bed(3).barcode => { - # purpose: 'GBS PCR1', - # states: %w[pending], - # parents: [bed(1).barcode, bed(2).barcode, bed(4).barcode, bed(5).barcode], - # target_state: 'passed', - # label: 'Bed 3' - # }, - # bed(4).barcode => { - # purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], - # states: %w[passed qc_complete], - # child: bed(3).barcode, - # label: 'Bed 4' - # }, - # bed(5).barcode => { - # purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], - # states: %w[passed qc_complete], - # child: bed(3).barcode, - # label: 'Bed 5' - # } - # }, - # destination_bed: bed(3).barcode, - # class: 'Robots::QuadrantRobot' - # ) - - # WIP: Delete this version for ANOSPP release custom_robot( 'mosquito-gbs-96-stock-to-gbs-pcr1', - name: 'Mosquito GBS-96 Stock => GBS PCR1', + name: 'Mosquito GBS-96 Stock or LANS-96 Lysate => GBS PCR1', beds: { bed(1).barcode => { - purpose: 'GBS-96 Stock', + purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], states: %w[passed qc_complete], child: bed(3).barcode, label: 'Bed 1' }, bed(2).barcode => { - purpose: 'GBS-96 Stock', + purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], states: %w[passed qc_complete], child: bed(3).barcode, label: 'Bed 2' @@ -1249,13 +1207,13 @@ label: 'Bed 3' }, bed(4).barcode => { - purpose: 'GBS-96 Stock', + purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], states: %w[passed qc_complete], child: bed(3).barcode, label: 'Bed 4' }, bed(5).barcode => { - purpose: 'GBS-96 Stock', + purpose: ['GBS-96 Stock', 'LANS-96 Lysate'], states: %w[passed qc_complete], child: bed(3).barcode, label: 'Bed 5' @@ -3769,4 +3727,320 @@ } } ) + + # LCM Triomics WGS and EMSeq bed verification + # Verify initial setup + custom_robot( + 'bravo-verify-initial-setup', + name: 'Bravo Verify Initial Setup', + require_robot: true, # Robot barcode must be scanned in. + verify_robot: false, # First robot step; no previous robot. + beds: { + bed(4).barcode => { + purpose: 'LCMT Lysate', + states: ['passed'], + label: 'Bed 4' + }, + car('1,4').barcode => { + purpose: 'LCMT DNA Frag', + states: ['pending'], + label: 'Carousel 1,4', + parent: bed(4).barcode, + target_state: 'started' + }, + car('2,4').barcode => { + purpose: 'LCMT DNA End Prep', + states: ['pending'], + label: 'Carousel 2,4', + parent: car('1,4').barcode, + target_state: 'started' + }, + car('3,5').barcode => { + purpose: 'LCMT DNA Adp Lig', + states: ['pending'], + label: 'Carousel 3,5', + parent: car('2,4').barcode, + target_state: 'started' + }, + car('4,4').barcode => { + purpose: 'LCMT EM TET2 Ox', + states: ['pending'], + label: 'Carousel 4,4', + parent: car('3,5').barcode, + target_state: 'started' + }, + car('4,3').barcode => { + purpose: 'LCMT EM TET2 Stop', + states: ['pending'], + label: 'Carousel 4,3', + parent: car('4,4').barcode, + target_state: 'started' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT DNA Frag Verification + custom_robot( + 'bravo-lcmt-dna-frag-verification', + name: 'Bravo LCMT DNA Frag Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT DNA Frag', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT DNA End Prep Verification + custom_robot( + 'bravo-lcmt-dna-end-prep-verification', + name: 'Bravo LCMT DNA End Prep Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT DNA End Prep', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT DNA Adp Lig to LCMT DNA Lib PCR + custom_robot( + 'bravo-lcmt-dna-adp-lig-to-lcmt-dna-lib-pcr', + name: 'Bravo LCMT DNA Adp Lig => LCMT DNA Lib PCR', + require_robot: true, + verify_robot: true, + beds: { + bed(6).barcode => { + purpose: 'LCMT DNA Adp Lig', + states: ['passed'], + label: 'Bed 6' + }, + bed(7).barcode => { + purpose: 'LCMT DNA Lib PCR', + states: ['pending'], + label: 'Bed 7', + parent: bed(6).barcode, + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT DNA Adp Lig Verification + custom_robot( + 'bravo-lcmt-dna-adp-lig-verification', + name: 'Bravo LCMT DNA Adp Lig Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT DNA Adp Lig', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM TET2 Ox Verification + custom_robot( + 'bravo-lcmt-em-tet2-ox-verification', + name: 'Bravo LCMT EM TET2 Ox Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT EM TET2 Ox', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM TET2 Stop Verification + custom_robot( + 'bravo-lcmt-em-tet2-stop-verification', + name: 'Bravo LCMT EM TET2 Stop Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT EM TET2 Stop', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM TET2 Stop to Denat and Deam Setup + custom_robot( + 'bravo-lcmt-em-tet2-stop-to-denat-and-deam-setup', + name: 'Bravo LCMT EM TET2 Stop to Denat and Deam Setup', + require_robot: true, + verify_robot: true, + beds: { + bed(4).barcode => { + purpose: 'LCMT EM TET2 Stop', + states: ['passed'], + label: 'Bed 4' + }, + car('3,3').barcode => { + purpose: 'LCMT EM NaOH Denat', + states: ['pending'], + label: 'Carousel 3,3', + parent: bed(4).barcode, + target_state: 'started' + }, + car('3,4').barcode => { + purpose: 'LCMT EM APOBEC Deam', + states: ['pending'], + label: 'Carousel 3,4', + parent: car('3,3').barcode, + target_state: 'started' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM NaOH Denat Verification + custom_robot( + 'bravo-lcmt-em-naoh-denat-verification', + name: 'Bravo LCMT EM NaOH Denat Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT EM NaOH Denat', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM APOBEC Deam Verification + custom_robot( + 'bravo-lcmt-em-apobec-deam-verification', + name: 'Bravo LCMT EM APOBEC Deam Verification', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT EM APOBEC Deam', + states: ['started'], + label: 'Bed 5', + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Bravo LCMT EM APOBEC Deam => LCMT EM Lib PCR + custom_robot( + 'bravo-lcmt-em-apobec-deam-to-lcmt-em-lib-pcr', + name: 'Bravo LCMT EM APOBEC Deam => LCMT EM Lib PCR', + require_robot: true, + verify_robot: true, + beds: { + bed(5).barcode => { + purpose: 'LCMT EM APOBEC Deam', + states: ['passed'], + label: 'Bed 5' + }, + bed(6).barcode => { + purpose: 'LCMT EM Lib PCR', + states: ['pending'], + label: 'Bed 6', + parent: bed(5).barcode, + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Hamilton LCMT DNA Lib PCR => LCMT DNA PCR XP + custom_robot( + 'hamilton-lcmt-dna-lib-pcr-to-lcmt-dna-pcr-xp', + name: 'Hamilton LCMT DNA Lib PCR => LCMT DNA PCR XP', + require_robot: true, + verify_robot: false, # Previous robot is Bravo. + beds: { + bed(7).barcode => { + purpose: 'LCMT DNA Lib PCR', + states: ['passed'], + label: 'Bed 7' + }, + bed(9).barcode => { + purpose: 'LCMT DNA PCR XP', + states: ['pending'], + label: 'Bed 9', + parent: bed(7).barcode, + target_state: 'passed' + }, + bed(12).barcode => { + purpose: 'LCMT DNA Lib PCR', + states: ['passed'], + label: 'Bed 12' + }, + bed(14).barcode => { + purpose: 'LCMT DNA PCR XP', + states: ['pending'], + label: 'Bed 14', + parent: bed(12).barcode, + target_state: 'passed' + } + } + ) + + # LCM Triomics WGS and EMSeq bed verification + # Hamilton LCMT EM Lib PCR => LCMT EM PCR XP + custom_robot( + 'hamilton-lcmt-em-lib-pcr-to-lcmt-em-pcr-xp', + name: 'Hamilton LCMT EM Lib PCR => LCMT EM PCR XP', + require_robot: true, + verify_robot: false, # Previous robot is Bravo. + beds: { + bed(7).barcode => { + purpose: 'LCMT EM Lib PCR', + states: ['passed'], + label: 'Bed 7' + }, + bed(9).barcode => { + purpose: 'LCMT EM PCR XP', + states: ['pending'], + label: 'Bed 9', + parent: bed(7).barcode, + target_state: 'passed' + }, + bed(12).barcode => { + purpose: 'LCMT EM Lib PCR', + states: ['passed'], + label: 'Bed 12' + }, + bed(14).barcode => { + purpose: 'LCMT EM PCR XP', + states: ['pending'], + label: 'Bed 14', + parent: bed(12).barcode, + target_state: 'passed' + } + } + ) end diff --git a/docker-compose.yml b/docker-compose.yml index f5de17ba0..c1c79b2b8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.3' services: limber: build: diff --git a/lib/purpose_config.rb b/lib/purpose_config.rb index db9ba5f3f..15761045b 100644 --- a/lib/purpose_config.rb +++ b/lib/purpose_config.rb @@ -109,14 +109,13 @@ def register! # maintains the behaviour of version 1, but includes an addditional # asset_shape option if configured. It raises an error if the purpose # cannot be created. - options_for_creation = - { - name: name, - stock_plate: config.fetch(:stock_plate, false), - cherrypickable_target: config.fetch(:cherrypickable_target, false), - input_plate: config.fetch(:input_plate, false), - size: config.fetch(:size, 96) - }.merge(config.slice(:asset_shape)) + options_for_creation = { + name: name, + stock_plate: config.fetch(:stock_plate, false), + cherrypickable_target: config.fetch(:cherrypickable_target, false), + input_plate: config.fetch(:input_plate, false), + size: config.fetch(:size, 96) + }.merge(config.slice(:asset_shape)) Sequencescape::Api::V2::PlatePurpose.create!(options_for_creation) end end diff --git a/lib/robot_configuration.rb b/lib/robot_configuration.rb index c4663231c..a9a09903b 100644 --- a/lib/robot_configuration.rb +++ b/lib/robot_configuration.rb @@ -21,9 +21,9 @@ def car(position) class Register # rubocop:todo Style/Documentation include BedHelpers - def self.configure(&block) + def self.configure(&) register = new - register.instance_eval(&block) + register.instance_eval(&) register.configuration end @@ -31,18 +31,12 @@ def custom_robot(key, hash) @robots[key] = hash end - def bravo_robot(transition_to: 'passed', verify_robot: false, require_robot: false, &block) - simple_robot( - 'bravo', - transition_to: transition_to, - verify_robot: verify_robot, - require_robot: require_robot, - &block - ) + def bravo_robot(transition_to: 'passed', verify_robot: false, require_robot: false, &) + simple_robot('bravo', transition_to:, verify_robot:, require_robot:, &) end - def simple_robot(type, transition_to: 'passed', verify_robot: false, require_robot: false, &block) - added_robot = RobotConfiguration::Simple.new(type, transition_to, verify_robot, require_robot, &block) + def simple_robot(type, transition_to: 'passed', verify_robot: false, require_robot: false, &) + added_robot = RobotConfiguration::Simple.new(type, transition_to, verify_robot, require_robot, &) @robots[added_robot.key] = added_robot.configuration added_robot end diff --git a/lib/tasks/config.rake b/lib/tasks/config.rake index bacade73b..03c190ae4 100644 --- a/lib/tasks/config.rake +++ b/lib/tasks/config.rake @@ -47,8 +47,10 @@ namespace :config do # TODO: Y24-190 - Remove this once we have moved everything else over to V2; # also the config entries for :searches puts 'Preparing searches ...' - configuration[:searches] = - api.search.all.each_with_object({}) { |search, searches| searches[search.name] = search.uuid } + configuration[:searches] = api + .search + .all + .each_with_object({}) { |search, searches| searches[search.name] = search.uuid } puts 'Preparing transfer templates ...' query = Sequencescape::Api::V2::TransferTemplate.select(:uuid, :name).paginate(per_page: 100) @@ -64,14 +66,14 @@ namespace :config do default_count: 2 } - configuration[:purposes] = - {}.tap do |labware_purposes| - puts 'Preparing purpose configs...' - purpose_config.each { |purpose| labware_purposes[purpose.uuid] = purpose.config } - end + configuration[:purposes] = {}.tap do |labware_purposes| + puts 'Preparing purpose configs...' + purpose_config.each { |purpose| labware_purposes[purpose.uuid] = purpose.config } + end - configuration[:purpose_uuids] = - tracked_purposes.each_with_object({}) { |purpose, store| store[purpose.name] = purpose.uuid } + configuration[:purpose_uuids] = tracked_purposes.each_with_object({}) do |purpose, store| + store[purpose.name] = purpose.uuid + end configuration[:robots] = ROBOT_CONFIG diff --git a/lib/well_helpers.rb b/lib/well_helpers.rb index 306620a79..e770daaa1 100644 --- a/lib/well_helpers.rb +++ b/lib/well_helpers.rb @@ -43,8 +43,8 @@ def self.rows_range(size = nil, rows: nil) # # @return [Array] well names in column order ie. A1, B1, C1 ... def self.column_order(size = 96, rows: nil, columns: nil) - columns_range(size, columns: columns) - .each_with_object([]) { |c, wells| rows_range(size, rows: rows).each { |r| wells << "#{r}#{c}" } } + columns_range(size, columns:) + .each_with_object([]) { |c, wells| rows_range(size, rows:).each { |r| wells << "#{r}#{c}" } } .freeze end @@ -53,8 +53,8 @@ def self.column_order(size = 96, rows: nil, columns: nil) # @param [96,192] number of wells on the plate. Only valid for 3:2 ratio plate sizes # @return [Array] well names in row order ie. A1, A2, A3 ... def self.row_order(size = 96, rows: nil, columns: nil) - rows_range(size, rows: rows) - .each_with_object([]) { |r, wells| columns_range(size, columns: columns).each { |c| wells << "#{r}#{c}" } } + rows_range(size, rows:) + .each_with_object([]) { |r, wells| columns_range(size, columns:).each { |c| wells << "#{r}#{c}" } } .freeze end @@ -66,7 +66,7 @@ def self.row_order(size = 96, rows: nil, columns: nil) # @return [Hash] eg. { 'A1' => 'A1', 'B1' => 'B1', ...} # def self.stamp_hash(size, rows: nil, columns: nil) - column_order(size, rows: rows, columns: columns).each_with_object({}) { |well, hash| hash[well] = well } + column_order(size, rows:, columns:).each_with_object({}) { |well, hash| hash[well] = well } end # Returns the index of the well by column diff --git a/limber.sublime-project b/limber.sublime-project index ff819a7c3..4f8e6d07c 100644 --- a/limber.sublime-project +++ b/limber.sublime-project @@ -22,12 +22,12 @@ "*.swf", "*.jar", "*.zip", - "*.xls" - ] + "*.xls", + ], }, { - "path": "coverage" - } + "path": "coverage", + }, ], // These settings will be applied to anyone working // on the project. They are intended to set up the accepted @@ -35,6 +35,6 @@ "settings": { "tab_size": 2, "translate_tabs_to_spaces": true, - "trim_trailing_white_space_on_save": true - } + "trim_trailing_white_space_on_save": true, + }, } diff --git a/package.json b/package.json index add3e87bf..2201fdcf9 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "web-worker": "^1.3.0" }, "devDependencies": { - "@prettier/plugin-ruby": "^2.1.0", + "@prettier/plugin-ruby": "^4.0.0", "@vitejs/plugin-vue2": "^2.3.1", "@vitest/coverage-v8": "^2.0.5", "@vue/test-utils": "^1.3.6", @@ -30,7 +30,7 @@ "postcss-import": "16.1.0", "postcss-nested": "^6.0.1", "postcss-preset-env": "^9.6.0", - "prettier": "^2.8.8", + "prettier": "^3.0.0", "sass": "^1.77.8", "typescript": "^4.6.3", "vite": "^5.4.7", diff --git a/public/404.html b/public/404.html index c5194504f..68d177fa2 100644 --- a/public/404.html +++ b/public/404.html @@ -1,4 +1,4 @@ - + The page you were looking for doesn't exist (404) diff --git a/public/422.html b/public/422.html index d16dd7f62..9e9cf0df2 100644 --- a/public/422.html +++ b/public/422.html @@ -1,4 +1,4 @@ - + The change you wanted was rejected (422) diff --git a/public/500.html b/public/500.html index 5a03944b5..0fc2fcef7 100644 --- a/public/500.html +++ b/public/500.html @@ -1,4 +1,4 @@ - + We're sorry, but something went wrong (500) diff --git a/public/502.html b/public/502.html index b5082d265..6f09738ed 100644 --- a/public/502.html +++ b/public/502.html @@ -1,4 +1,4 @@ - + We're sorry, but something went wrong (502) diff --git a/public/504.html b/public/504.html index 95e94d118..c8927e613 100644 --- a/public/504.html +++ b/public/504.html @@ -1,4 +1,4 @@ - + We're sorry, but something took too long (504) diff --git a/spec/controllers/exports_controller_spec.rb b/spec/controllers/exports_controller_spec.rb index 08cf8840c..ea19c1de2 100644 --- a/spec/controllers/exports_controller_spec.rb +++ b/spec/controllers/exports_controller_spec.rb @@ -63,9 +63,10 @@ context 'on generating a csv' do before do - expect(Sequencescape::Api::V2).to receive(:plate_with_custom_includes) - .with(includes, barcode: plate_barcode) - .and_return(plate) + expect(Sequencescape::Api::V2).to receive(:plate_with_custom_includes).with( + includes, + barcode: plate_barcode + ).and_return(plate) end context 'where csv id requested is concentrations_ngul.csv' do @@ -318,9 +319,10 @@ before do # Make the controller to receive the plate. # NB. Uses plate_includes if specified in the export configuration. - allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes) - .with(export.plate_includes, barcode: plate_barcode) - .and_return(plate) + allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes).with( + export.plate_includes, + barcode: plate_barcode + ).and_return(plate) # Make the controller to use the export loaded from fixture config. allow(subject).to receive(:export).and_return(export) @@ -334,16 +336,17 @@ asset_ancestors = ancestor_plates.map { |ancestor_plate| double('Sequencescape::Api::V2::Asset', id: ancestor_plate.id) } - allow(plate).to receive_message_chain(:ancestors, :where) - .with(purpose_name: export.ancestor_purpose) - .and_return(asset_ancestors) + allow(plate).to receive_message_chain(:ancestors, :where).with(purpose_name: export.ancestor_purpose).and_return( + asset_ancestors + ) # Stub the plate_with_custom_includes query to return the first ancestor plate. # NB. This stub is required to make the other methods in the show controller # action not to fail when they try to receive the first ancestor plate. - allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes) - .with(export.plate_includes, id: asset_ancestors.first.id) - .and_return(ancestor_plates.first) + allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes).with( + export.plate_includes, + id: asset_ancestors.first.id + ).and_return(ancestor_plates.first) # Stub the plate query to return ancestor plates. builder = double('JsonApiClient::Query::Builder') diff --git a/spec/controllers/pipeline_work_in_progress_controller_spec.rb b/spec/controllers/pipeline_work_in_progress_controller_spec.rb index 601bcef35..8c54f4104 100644 --- a/spec/controllers/pipeline_work_in_progress_controller_spec.rb +++ b/spec/controllers/pipeline_work_in_progress_controller_spec.rb @@ -25,7 +25,7 @@ let(:date) { Date.new(2019, 5, 13) } it 'parses the date from the URL parameters' do - expect(controller.from_date({ date: date })).to eq date + expect(controller.from_date({ date: })).to eq date end it 'defaults to a month ago' do diff --git a/spec/controllers/plates/work_completions_controller_spec.rb b/spec/controllers/plates/work_completions_controller_spec.rb index 5c65e2a4e..3eb1d80b3 100644 --- a/spec/controllers/plates/work_completions_controller_spec.rb +++ b/spec/controllers/plates/work_completions_controller_spec.rb @@ -23,7 +23,7 @@ end it 'creates work_completion' do - post :create, params: { limber_plate_id: plate_uuid }, session: { user_uuid: user_uuid } + post :create, params: { limber_plate_id: plate_uuid }, session: { user_uuid: } expect(response).to redirect_to(limber_plate_path(plate_uuid)) expect(work_completion_creation).to have_been_made.once assert_equal ['Requests have been passed'], flash.notice diff --git a/spec/controllers/plates_controller_spec.rb b/spec/controllers/plates_controller_spec.rb index 5c4cb9303..a574ae102 100644 --- a/spec/controllers/plates_controller_spec.rb +++ b/spec/controllers/plates_controller_spec.rb @@ -68,7 +68,7 @@ def expect_state_change_create(attributes) purpose_uuid: 'stock-plate-purpose-uuid' }, session: { - user_uuid: user_uuid + user_uuid: } expect(response).to redirect_to(search_path) @@ -83,19 +83,7 @@ def expect_state_change_create(attributes) reason: 'Individual Well Failure' ) - post :fail_wells, - params: { - id: plate_uuid, - plate: { - wells: { - 'A1' => 1, - 'B1' => 0 - } - } - }, - session: { - user_uuid: user_uuid - } + post :fail_wells, params: { id: plate_uuid, plate: { wells: { 'A1' => 1, 'B1' => 0 } } }, session: { user_uuid: } expect(response).to redirect_to(limber_plate_path(plate_uuid)) end diff --git a/spec/controllers/qc_files_controller_spec.rb b/spec/controllers/qc_files_controller_spec.rb index 2256ef0d7..22ba6cf95 100644 --- a/spec/controllers/qc_files_controller_spec.rb +++ b/spec/controllers/qc_files_controller_spec.rb @@ -12,14 +12,12 @@ before do stub_api_get(file_uuid, body: json(:qc_file, uuid: file_uuid, filename: filename)) - stub_request(:get, api_url_for(file_uuid)) - .with(headers: { 'Accept' => 'sequencescape/qc_file' }) - .to_return( - body: 'example file content', - headers: { - 'Content-Disposition' => "attachment; filename=\"#{filename}\"" - } - ) + stub_request(:get, api_url_for(file_uuid)).with(headers: { 'Accept' => 'sequencescape/qc_file' }).to_return( + body: 'example file content', + headers: { + 'Content-Disposition' => "attachment; filename=\"#{filename}\"" + } + ) end it 'returns a file' do @@ -39,21 +37,19 @@ let(:plate_uuid) { 'plate-uuid' } let(:stub_post) do - stub_request(:post, api_url_for(plate_uuid, 'qc_files')) - .with( - body: file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="test_file.txt"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'test_file.txt'), - headers: { - 'content-type' => 'application/json' - } - ) + stub_request(:post, api_url_for(plate_uuid, 'qc_files')).with( + body: file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="test_file.txt"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'test_file.txt'), + headers: { + 'content-type' => 'application/json' + } + ) end before do diff --git a/spec/controllers/searches_controller_spec.rb b/spec/controllers/searches_controller_spec.rb index d02015525..c3ff23908 100644 --- a/spec/controllers/searches_controller_spec.rb +++ b/spec/controllers/searches_controller_spec.rb @@ -29,7 +29,7 @@ before { stub_barcode_search(barcode, labware) } context 'for a plate' do - let(:labware) { create :labware_plate, uuid: uuid } + let(:labware) { create :labware_plate, uuid: } it 'redirects to the found labware' do post :create, params: { plate_barcode: barcode } expect(response).to redirect_to(limber_plate_path(uuid)) @@ -37,7 +37,7 @@ end context 'for a tube' do - let(:labware) { create :labware_tube, uuid: uuid } + let(:labware) { create :labware_tube, uuid: } it 'redirects to the found labware' do post :create, params: { plate_barcode: barcode } expect(response).to redirect_to(limber_tube_path(uuid)) @@ -45,7 +45,7 @@ end context 'for a tube rack' do - let(:labware) { create :labware_tube_rack, uuid: uuid } + let(:labware) { create :labware_tube_rack, uuid: } it 'redirects to the found labware' do post :create, params: { plate_barcode: barcode } expect(response).to redirect_to(limber_tube_rack_path(uuid)) diff --git a/spec/controllers/sequencescape_submissions_controller_spec.rb b/spec/controllers/sequencescape_submissions_controller_spec.rb index ec89884cb..763dfae01 100644 --- a/spec/controllers/sequencescape_submissions_controller_spec.rb +++ b/spec/controllers/sequencescape_submissions_controller_spec.rb @@ -65,7 +65,7 @@ let!(:submission_submit) { stub_api_post('sub-uuid', 'submit') } it 'creates a submission' do - post :create, params: request_parameters, session: { user_uuid: user_uuid } + post :create, params: request_parameters, session: { user_uuid: } expect(order_request).to have_been_made.once expect(submission_request).to have_been_made.once expect(submission_submit).to have_been_made.once diff --git a/spec/controllers/tube_creation_controller_spec.rb b/spec/controllers/tube_creation_controller_spec.rb index 20ee5bd19..049073624 100644 --- a/spec/controllers/tube_creation_controller_spec.rb +++ b/spec/controllers/tube_creation_controller_spec.rb @@ -23,14 +23,7 @@ describe '#new' do it 'creates a tube from a tube parent' do - get :new, - params: { - limber_tube_id: parent_uuid, - purpose_uuid: child_purpose_uuid - }, - session: { - user_uuid: user_uuid - } + get :new, params: { limber_tube_id: parent_uuid, purpose_uuid: child_purpose_uuid }, session: { user_uuid: } expect(response).to render_template('new') expect(assigns(:labware_creator).parent_uuid).to eq(parent_uuid) expect(assigns(:labware_creator).user_uuid).to eq(user_uuid) @@ -38,14 +31,7 @@ end it 'creates a tube from a plate parent' do - get :new, - params: { - limber_plate_id: parent_uuid, - purpose_uuid: child_purpose_uuid - }, - session: { - user_uuid: user_uuid - } + get :new, params: { limber_plate_id: parent_uuid, purpose_uuid: child_purpose_uuid }, session: { user_uuid: } expect(response).to render_template('new') expect(assigns(:labware_creator).parent_uuid).to eq(parent_uuid) expect(assigns(:labware_creator).user_uuid).to eq(user_uuid) @@ -71,7 +57,7 @@ } }, session: { - user_uuid: user_uuid + user_uuid: } expect(response).to redirect_to("#{limber_tube_path(child_uuid)}#relatives_tab") expect(assigns(:labware_creator).parent_uuid).to eq(parent_uuid) @@ -90,7 +76,7 @@ } }, session: { - user_uuid: user_uuid + user_uuid: } expect(response).to redirect_to("#{limber_tube_path(child_uuid)}#relatives_tab") expect(assigns(:labware_creator).parent_uuid).to eq(parent_uuid) diff --git a/spec/controllers/tubes/tubes_exports_controller_spec.rb b/spec/controllers/tubes/tubes_exports_controller_spec.rb index 365f41e70..e32037013 100644 --- a/spec/controllers/tubes/tubes_exports_controller_spec.rb +++ b/spec/controllers/tubes/tubes_exports_controller_spec.rb @@ -29,9 +29,11 @@ context 'on generating a csv' do before do - expect(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with(includes, selects, barcode: tube_barcode) - .and_return(tube) + expect(Sequencescape::Api::V2).to receive(:tube_with_custom_includes).with( + includes, + selects, + barcode: tube_barcode + ).and_return(tube) end context 'where tsv id requested is bioscan_mbrave.tsv' do diff --git a/spec/controllers/tubes/work_completions_controller_spec.rb b/spec/controllers/tubes/work_completions_controller_spec.rb index e38c0c538..4f2c5aad9 100644 --- a/spec/controllers/tubes/work_completions_controller_spec.rb +++ b/spec/controllers/tubes/work_completions_controller_spec.rb @@ -19,7 +19,7 @@ end it 'creates work_completion' do - post :create, params: { limber_tube_id: tube_uuid }, session: { user_uuid: user_uuid } + post :create, params: { limber_tube_id: tube_uuid }, session: { user_uuid: } expect(response).to redirect_to(limber_tube_path(tube_uuid)) expect(tube_get).to have_been_made expect(work_completion_creation).to have_been_made.once diff --git a/spec/controllers/tubes_controller_spec.rb b/spec/controllers/tubes_controller_spec.rb index 7d75da7ef..eb8adcf78 100644 --- a/spec/controllers/tubes_controller_spec.rb +++ b/spec/controllers/tubes_controller_spec.rb @@ -60,7 +60,7 @@ purpose_uuid: 'stock-tube-purpose-uuid' }, session: { - user_uuid: user_uuid + user_uuid: } expect(response).to redirect_to(search_path) diff --git a/spec/factories/bait_library_layout_factories.rb b/spec/factories/bait_library_layout_factories.rb index 9301e066e..f5fc1bc58 100644 --- a/spec/factories/bait_library_layout_factories.rb +++ b/spec/factories/bait_library_layout_factories.rb @@ -3,11 +3,9 @@ require_relative '../support/factory_bot_extensions' FactoryBot.define do - # Generates a BaitLibraryLayout (API V1) - factory :bait_library_layout, class: Sequencescape::BaitLibraryLayout, traits: [:api_object] do - json_root { 'bait_library_layout' } - - with_belongs_to_associations 'plate' + # Generates an incomplete, but sufficient for testing, V2 BaitLibraryLayout + factory :bait_library_layout, class: Sequencescape::Api::V2::BaitLibraryLayout do + skip_create transient do # Provide an array of pools, describing the number of wells in each diff --git a/spec/factories/labware_factories.rb b/spec/factories/labware_factories.rb index 04b51a260..dc0b22c7e 100644 --- a/spec/factories/labware_factories.rb +++ b/spec/factories/labware_factories.rb @@ -29,7 +29,7 @@ end factory(:labware_with_state_changes) do - state_changes { create_list :v2_state_change, 2, target_state: target_state } + state_changes { create_list :v2_state_change, 2, target_state: } after(:build) { |labware, evaluator| labware._cached_relationship(:state_changes) { evaluator.state_changes } } end diff --git a/spec/factories/plate_factories.rb b/spec/factories/plate_factories.rb index 4a0a421a7..0b0aefe38 100644 --- a/spec/factories/plate_factories.rb +++ b/spec/factories/plate_factories.rb @@ -335,7 +335,7 @@ factory :stock_plate do purpose_name { 'Limber Cherrypicked' } purpose_uuid { 'stock-plate-purpose-uuid' } - stock_plate { { barcode: barcode, uuid: uuid } } + stock_plate { { barcode:, uuid: } } factory :stock_plate_with_metadata do with_belongs_to_associations 'custom_metadatum_collection' @@ -355,21 +355,20 @@ pooled_wells = wells.reject { |w| empty_wells.include?(w) } pool_hash = {} pool_sizes.each_with_index do |pool_size, index| - pool_hash["pool-#{index + 1}-uuid"] = - { - 'wells' => pooled_wells.shift(pool_size).sort_by { |well| WellHelpers.row_order(size).index(well) }, - 'insert_size' => { - from: 100, - to: 300 - }, - 'library_type' => { - name: library_type - }, - 'request_type' => request_type, - 'pcr_cycles' => pool_prc_cycles[index], - 'for_multiplexing' => pool_for_multiplexing[index], - 'pool_complete' => pool_complete - }.merge(extra_pool_info) + pool_hash["pool-#{index + 1}-uuid"] = { + 'wells' => pooled_wells.shift(pool_size).sort_by { |well| WellHelpers.row_order(size).index(well) }, + 'insert_size' => { + from: 100, + to: 300 + }, + 'library_type' => { + name: library_type + }, + 'request_type' => request_type, + 'pcr_cycles' => pool_prc_cycles[index], + 'for_multiplexing' => pool_for_multiplexing[index], + 'pool_complete' => pool_complete + }.merge(extra_pool_info) end pool_hash end diff --git a/spec/factories/poly_metadata_factories.rb b/spec/factories/poly_metadata_factories.rb index 754d5bc01..f92dd7ab4 100644 --- a/spec/factories/poly_metadata_factories.rb +++ b/spec/factories/poly_metadata_factories.rb @@ -12,7 +12,8 @@ after(:build) do |poly_metadatum, evaluator| poly_metadatum.relationships.metadatable = { - 'links' => {}, + 'links' => { + }, 'data' => { 'type' => 'Request', 'id' => evaluator.metadatable.id diff --git a/spec/factories/purpose_config_factories.rb b/spec/factories/purpose_config_factories.rb index a5014f1aa..430cbafc3 100644 --- a/spec/factories/purpose_config_factories.rb +++ b/spec/factories/purpose_config_factories.rb @@ -181,7 +181,7 @@ transient { acceptable_purposes { %w[Purpose1 Purpose2] } } state_changer_class { 'StateChangers::AutomaticPlateStateChanger' } - creator_class { { name: 'LabwareCreators::TenStamp', args: { acceptable_purposes: acceptable_purposes } } } + creator_class { { name: 'LabwareCreators::TenStamp', args: { acceptable_purposes: } } } work_completion_request_type { 'limber_bespoke_aggregation' } end @@ -239,11 +239,13 @@ { 'Cardinal library prep' => { 'template_name' => 'example', - 'request_options' => {} + 'request_options' => { + } }, 'Another Cardinal library prep' => { 'template_name' => 'example', - 'request_options' => {} + 'request_options' => { + } } } end @@ -268,14 +270,7 @@ # Configuration to set number_of_source_wells argument factory :pooled_wells_by_sample_in_groups_purpose_config do transient { number_of_source_wells { 2 } } - creator_class do - { - name: 'LabwareCreators::PooledWellsBySampleInGroups', - args: { - number_of_source_wells: number_of_source_wells - } - } - end + creator_class { { name: 'LabwareCreators::PooledWellsBySampleInGroups', args: { number_of_source_wells: } } } end factory :multi_stamp_tubes_using_tube_rack_scan_purpose_config do @@ -294,15 +289,7 @@ factory :donor_pooling_plate_purpose_config do transient { max_number_of_source_plates { 2 } } transient { pooling { 'donor_pooling' } } - creator_class do - { - name: 'LabwareCreators::DonorPoolingPlate', - args: { - max_number_of_source_plates: max_number_of_source_plates, - pooling: pooling - } - } - end + creator_class { { name: 'LabwareCreators::DonorPoolingPlate', args: { max_number_of_source_plates:, pooling: } } } end factory :banking_plate_purpose_config do diff --git a/spec/factories/strategies/api_strategy.rb b/spec/factories/strategies/api_strategy.rb index 588c984fb..79432b1d6 100644 --- a/spec/factories/strategies/api_strategy.rb +++ b/spec/factories/strategies/api_strategy.rb @@ -11,7 +11,8 @@ def initialize delegate :association, to: :@strategy - def result(evaluation); end + def result(evaluation) + end end FactoryBot.register_strategy(:api_object, ApiStrategy) diff --git a/spec/factories/transfer_factories.rb b/spec/factories/transfer_factories.rb index af3f09536..b7b451be5 100644 --- a/spec/factories/transfer_factories.rb +++ b/spec/factories/transfer_factories.rb @@ -148,7 +148,7 @@ associated_on { 'transfers_to_tubes' } plate_uuid { SecureRandom.uuid } plate { associated :plate, uuid: plate_uuid } - sources { source_uuids.map { |uuid| associated :plate, uuid: uuid } } + sources { source_uuids.map { |uuid| associated :plate, uuid: } } # While resources can be paginated, wells wont be. # Furthermore, we trust the api gem to handle that side of things. diff --git a/spec/factories/tube_factories.rb b/spec/factories/tube_factories.rb index 02a1c909a..34575815d 100644 --- a/spec/factories/tube_factories.rb +++ b/spec/factories/tube_factories.rb @@ -80,7 +80,7 @@ factory :stock_tube do purpose_name { 'Limber Cherrypicked' } purpose_uuid { 'stock-plate-purpose-uuid' } - stock_plate { { barcode: barcode, uuid: uuid } } + stock_plate { { barcode:, uuid: } } factory :stock_tube_with_metadata do with_belongs_to_associations 'custom_metadatum_collection' @@ -112,9 +112,7 @@ request_factory { :library_request } aliquot_count { 2 } aliquot_factory { :v2_tagged_aliquot } - aliquots do - create_list aliquot_factory, aliquot_count, library_state: library_state, outer_request: outer_request - end + aliquots { create_list aliquot_factory, aliquot_count, library_state:, outer_request: } parents { [] } purpose { create :v2_purpose, name: purpose_name, uuid: purpose_uuid } diff --git a/spec/factories/well_factories.rb b/spec/factories/well_factories.rb index 60e5059b8..3e5dba5d9 100644 --- a/spec/factories/well_factories.rb +++ b/spec/factories/well_factories.rb @@ -60,11 +60,7 @@ aliquot_factory { :v2_aliquot } aliquots do # Conditional to avoid generating requests when not required - if aliquot_count > 0 - create_list aliquot_factory, aliquot_count, outer_request: outer_request, study: study, project: project - else - [] - end + aliquot_count.positive? ? create_list(aliquot_factory, aliquot_count, outer_request:, study:, project:) : [] end # The factory to use for outer requests diff --git a/spec/factory_outputs/bait_library_layout_factory_spec.rb b/spec/factory_outputs/bait_library_layout_factory_spec.rb deleted file mode 100644 index 784db8853..000000000 --- a/spec/factory_outputs/bait_library_layout_factory_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'bait library layout factory' do - subject { json(:bait_library_layout, plate_uuid: 'plate-uuid', uuid: 'bait-library-layout-uuid') } - - let(:json_content) do - '{ - "bait_library_layout": { - "actions": {"read": "http://example.com:3000/bait-library-layout-uuid"}, - "plate": { - "actions": { - "read": "http://example.com:3000/plate-uuid" - }, - "uuid": "plate-uuid" - }, - "uuid": "bait-library-layout-uuid", - "layout": { - "A1": "Human all exon 50MB", - "B1": "Human all exon 50MB", - "C1": "Mouse all exon", - "D1": "Mouse all exon" - } - } - }' - end - - it 'should match the expected json' do - expect(JSON.parse(subject)['bait_library_layout']).to eq JSON.parse(json_content)['bait_library_layout'] - end -end diff --git a/spec/factory_outputs/well_factory_spec.rb b/spec/factory_outputs/well_factory_spec.rb index 8f395bf18..0578805b7 100644 --- a/spec/factory_outputs/well_factory_spec.rb +++ b/spec/factory_outputs/well_factory_spec.rb @@ -134,7 +134,7 @@ subject { create(:v2_well, location: 'A1', aliquots: [source_aliquot]) } # source aliquots - let(:source_aliquot) { create(:v2_aliquot, sample: sample) } + let(:source_aliquot) { create(:v2_aliquot, sample:) } describe 'first aliquot' do let(:first_well_aliquot) { subject.aliquots.first } @@ -195,7 +195,7 @@ let(:first_aliquot) { subject.aliquots.first } # source aliquots - let(:source_aliquot) { create(:v2_aliquot, sample: sample, study: study, project: project) } + let(:source_aliquot) { create(:v2_aliquot, sample:, study:, project:) } # study let(:study_uuid) { SecureRandom.uuid } @@ -239,7 +239,7 @@ end context 'with specified study and project at well level' do - subject { create(:v2_well, study: study, project: project) } + subject { create(:v2_well, study:, project:) } let(:first_aliquot) { subject.aliquots.first } # study diff --git a/spec/features/charge_and_pass_libraries_spec.rb b/spec/features/charge_and_pass_libraries_spec.rb index 26518e966..f9d2f998f 100644 --- a/spec/features/charge_and_pass_libraries_spec.rb +++ b/spec/features/charge_and_pass_libraries_spec.rb @@ -52,14 +52,7 @@ end context 'tube with submissions to be made' do - before do - create :passable_tube, - submission: { - request_options: request_options, - template_uuid: template_uuid - }, - uuid: 'example-purpose-uuid' - end + before { create :passable_tube, submission: { request_options:, template_uuid: }, uuid: 'example-purpose-uuid' } let(:submissions) { [] } let(:request_options) { { read_length: '150' } } let(:labware_barcode) { example_tube_v2.labware_barcode.machine } diff --git a/spec/features/creating_a_plate_spec.rb b/spec/features/creating_a_plate_spec.rb index 45676b4f7..be4bbe800 100644 --- a/spec/features/creating_a_plate_spec.rb +++ b/spec/features/creating_a_plate_spec.rb @@ -125,9 +125,9 @@ allow(child_plate).to receive(:stock_plates).and_return(stock_plates) allow(child_plate).to receive(:stock_plate).and_return(stock_plates.last) allow(child_plate).to receive(:ancestors).and_return(ancestors_scope) - allow(ancestors_scope).to receive(:where) - .with(purpose_name: alternative_purpose_name) - .and_return([alternative_plate]) + allow(ancestors_scope).to receive(:where).with(purpose_name: alternative_purpose_name).and_return( + [alternative_plate] + ) allow(job).to receive(:save).and_return(true) allow(PMB::PrintJob).to receive(:new) do |args| diff --git a/spec/features/creating_a_quadrant_stamp_primer_panel_plate_spec.rb b/spec/features/creating_a_quadrant_stamp_primer_panel_plate_spec.rb index 51ee784bd..3e3d05d94 100644 --- a/spec/features/creating_a_quadrant_stamp_primer_panel_plate_spec.rb +++ b/spec/features/creating_a_quadrant_stamp_primer_panel_plate_spec.rb @@ -51,7 +51,7 @@ parents: [parent_uuid, parent2_uuid] } }, - body: json(:plate_creation, child_uuid: child_uuid) + body: json(:plate_creation, child_uuid:) ) end diff --git a/spec/features/creating_a_tag_plate_spec.rb b/spec/features/creating_a_tag_plate_spec.rb index b319045bc..b217d147b 100644 --- a/spec/features/creating_a_tag_plate_spec.rb +++ b/spec/features/creating_a_tag_plate_spec.rb @@ -49,10 +49,12 @@ background do # Set-up the plate config create :purpose_config, uuid: 'stock-plate-purpose-uuid', name: 'Limber Cherrypicked' - create :tagged_purpose_config, - tag_layout_templates: acceptable_templates, - uuid: child_purpose_uuid, - enforce_same_template_within_pool: enforce_same_template_within_pool + create( + :tagged_purpose_config, + tag_layout_templates: acceptable_templates, + uuid: child_purpose_uuid, + enforce_same_template_within_pool: enforce_same_template_within_pool + ) create :pipeline, relationships: { 'Limber Cherrypicked' => 'Tag Purpose' } # We look up the user @@ -232,7 +234,7 @@ let(:direction) { 'column' } let(:templates) do - create_list(template_factory, 2, direction: direction) do |template, i| + create_list(template_factory, 2, direction:) do |template, i| template.uuid = "tag-layout-template-#{i}" template.name = "Tag2 layout #{i}" end @@ -247,7 +249,7 @@ let(:direction) { 'row' } let(:templates) do - create_list(template_factory, 2, direction: direction) do |template, i| + create_list(template_factory, 2, direction:) do |template, i| template.uuid = "tag-layout-template-#{i}" template.name = "Tag2 layout #{i}" end diff --git a/spec/features/creating_plate_with_bait_spec.rb b/spec/features/creating_plate_with_bait_spec.rb index d7625dd66..99aa56faa 100644 --- a/spec/features/creating_plate_with_bait_spec.rb +++ b/spec/features/creating_plate_with_bait_spec.rb @@ -21,6 +21,8 @@ let(:transfer_template) { json :transfer_template, uuid: transfer_template_uuid } let(:expected_transfers) { WellHelpers.stamp_hash(96) } + let(:bait_library_layout) { create :bait_library_layout } + let(:transfer_requests) do WellHelpers.column_order(96)[0, 6].map do |well_name| { 'source_asset' => "2-well-#{well_name}", 'target_asset' => "3-well-#{well_name}", 'submission_id' => '2' } @@ -44,17 +46,7 @@ # end of stubs for plate show page # These stubs are required to render plate_creation baiting page - stub_api_post( - 'bait_library_layouts', - 'preview', - body: json(:bait_library_layout), - payload: { - bait_library_layout: { - plate: plate_uuid, - user: user_uuid - } - } - ) + expect_api_v2_posts('BaitLibraryLayout', [{ plate_uuid:, user_uuid: }], [[bait_library_layout]], method: :preview) # end of stubs for plate_creation baiting page @@ -80,16 +72,8 @@ }, body: '{}' ) - stub_api_post( - 'bait_library_layouts', - body: json(:bait_library_layout), - payload: { - bait_library_layout: { - plate: 'child-uuid', - user: user_uuid - } - } - ) + + expect_api_v2_posts('BaitLibraryLayout', [{ plate_uuid: 'child-uuid', user_uuid: user_uuid }]) # end of stubs for creating a new plate with baits # Stub the requests for the next plate page diff --git a/spec/features/pooling_multiple_plates_into_one_tube_spec.rb b/spec/features/pooling_multiple_plates_into_one_tube_spec.rb index 73937a3d7..1e2487b1a 100644 --- a/spec/features/pooling_multiple_plates_into_one_tube_spec.rb +++ b/spec/features/pooling_multiple_plates_into_one_tube_spec.rb @@ -57,32 +57,13 @@ end let(:example_plate_3_listed) { associated(*example_plate3_args) } - let(:child_tube_uuid) { 'tube-0' } - let(:child_tube) do - create :v2_tube, purpose_uuid: 'child-purpose-0', purpose_name: 'Pool tube', uuid: child_tube_uuid - end + let(:child_tube) { create :v2_tube, purpose_uuid: 'child-purpose-0', purpose_name: 'Pool tube' } - let(:tube_creation_request_uuid) { SecureRandom.uuid } - - let!(:tube_creation_request) do - # TODO: In reality we want to link in all four parents. - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - user: user_uuid, - parent: plate_uuid, - child_purposes: ['child-purpose-0'], - tube_attributes: [{ name: 'DN2+' }] - } - }, - body: json(:specific_tube_creation, uuid: tube_creation_request_uuid, children_count: 1) - ) - end + let(:specific_tube_creation) do + response = double + allow(response).to receive(:children).and_return([child_tube]) - # Find out what tubes we've just made! - let!(:tube_creation_children_request) do - stub_api_get(tube_creation_request_uuid, 'children', body: json(:tube_collection, names: ['DN1+'])) + response end # Used to fetch the pools. This is the kind of thing we could pass through from a custom form @@ -119,8 +100,6 @@ stub_v2_plate(example_plate_new_api) - stub_v2_plate(example_plate_new_api) - stub_api_get(plate_uuid, body: example_plate) stub_api_get(plate_uuid, 'wells', body: well_set_a) @@ -132,13 +111,25 @@ scenario 'creates multiple plates' do stub_v2_plate(example_plate_2) + expect_api_v2_posts( + 'SpecificTubeCreation', + [ + { + child_purpose_uuids: ['child-purpose-0'], + parent_uuids: [plate_uuid], + tube_attributes: [{ name: 'DN2+' }], + user_uuid: user_uuid + } + ], + [specific_tube_creation] + ) expect_api_v2_posts( 'Transfer', [plate_uuid, plate_uuid_2].map do |source_uuid| { user_uuid: user_uuid, source_uuid: source_uuid, - destination_uuid: 'tube-0', + destination_uuid: child_tube.uuid, transfer_template_uuid: 'whole-plate-to-tube' } end @@ -156,15 +147,11 @@ click_on('Make Pool') expect(page).to have_text('New empty labware added to the system') expect(page).to have_text('Pool tube') - - # This isn't strictly speaking correct to test. But there isn't a great way - # of confirming that the right information got passed to the back end otherwise. - # (Although you expect it to fail on an incorrect request) - expect(tube_creation_request).to have_been_made end scenario 'detects tag clash' do stub_v2_plate(example_plate_3) + fill_in_swipecard_and_barcode(user_swipecard, plate_barcode_1) plate_title = find('#plate-title') expect(plate_title).to have_text('example-purpose') diff --git a/spec/features/pooling_multiple_plates_spec.rb b/spec/features/pooling_multiple_plates_spec.rb index b7a49849f..e86f00458 100644 --- a/spec/features/pooling_multiple_plates_spec.rb +++ b/spec/features/pooling_multiple_plates_spec.rb @@ -34,29 +34,6 @@ purpose_uuid: 'stock-plate-purpose-uuid' end - let(:child_plate_uuid) { SecureRandom.uuid } - let(:child_plate) do - create :v2_plate, - purpose_uuid: 'child-purpose-0', - purpose_name: 'Pool Plate', - uuid: child_plate_uuid, - barcode_number: 3 - end - - let!(:pooled_plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: 'child-purpose-0', - parents: [plate_uuid, plate_uuid_2] - } - }, - body: json(:plate_creation, child_uuid: child_plate_uuid) - ) - end - let!(:bulk_transfer_request) do stub_api_post( 'bulk_transfers', @@ -67,25 +44,44 @@ { 'source_uuid' => plate_uuid, 'source_location' => 'A1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'A1' }, { 'source_uuid' => plate_uuid_2, 'source_location' => 'A1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'B1' }, { 'source_uuid' => plate_uuid_2, 'source_location' => 'B1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'B1' } ] } }, - body: json(:plate_creation, child_uuid: child_plate_uuid) + body: json(:plate_creation, child_uuid: child_plate.uuid) + ) + end + + let(:child_plate) { create :v2_plate, purpose_name: 'Pool Plate', barcode_number: 3 } + + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [ + { child_purpose_uuid: child_plate.purpose.uuid, parent_uuids: [plate_uuid, plate_uuid_2], user_uuid: user_uuid } + ], + [pooled_plate_creation] ) end @@ -94,7 +90,7 @@ create :purpose_config, creator_class: 'LabwareCreators::MultiPlatePool', name: 'Pool Plate', - uuid: 'child-purpose-0' + uuid: child_plate.purpose.uuid create :pipeline, relationships: { 'Pooled example' => 'Pool Plate' } # We look up the user @@ -108,6 +104,8 @@ end scenario 'creates multiple plates' do + expect_pooled_plate_creation + fill_in_swipecard_and_barcode(user_swipecard, plate_barcode_1) plate_title = find('#plate-title') expect(plate_title).to have_text('Pooled example') @@ -119,7 +117,6 @@ expect(page).to have_content('DN2: A1, B1') click_on('Make Pre-Cap pool Plate') expect(page).to have_text('New empty labware added to the system') - expect(pooled_plate_creation_request).to have_been_made expect(bulk_transfer_request).to have_been_made expect(page).to have_text('Pool Plate') end diff --git a/spec/features/pooling_multiple_tubes_into_one_tube_spec.rb b/spec/features/pooling_multiple_tubes_into_one_tube_spec.rb index a877b28cb..b1a45b360 100644 --- a/spec/features/pooling_multiple_tubes_into_one_tube_spec.rb +++ b/spec/features/pooling_multiple_tubes_into_one_tube_spec.rb @@ -86,7 +86,7 @@ child_purpose: purpose_uuid } }, - body: json(:tube_creation, child_uuid: child_uuid) + body: json(:tube_creation, child_uuid:) ) end @@ -145,22 +145,21 @@ end before do - allow(Sequencescape::Api::V2::Tube).to receive(:find_all) - .with( - include_used: false, - purpose_name: ['example-purpose'], - includes: 'purpose', - paginate: { - size: 30, - number: 1 - } - ) - .and_return([example_v2_tube, example_v2_tube2]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_all).with( + include_used: false, + purpose_name: ['example-purpose'], + includes: 'purpose', + paginate: { + size: 30, + number: 1 + } + ).and_return([example_v2_tube, example_v2_tube2]) # Parent lookup - allow(Sequencescape::Api::V2::Tube).to receive(:find_all) - .with(barcode: [tube_barcode_1, tube_barcode_2], includes: []) - .and_return([example_v2_tube, example_v2_tube2]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_all).with( + barcode: [tube_barcode_1, tube_barcode_2], + includes: [] + ).and_return([example_v2_tube, example_v2_tube2]) # Allow parent plates to be found in API v2 stub_v2_plate(parent_1, stub_search: false) @@ -186,22 +185,21 @@ stub_v2_tube(example_v2_tube2) # Available tubes search - allow(Sequencescape::Api::V2::Tube).to receive(:find_all) - .with( - include_used: false, - purpose_name: ['example-purpose'], - includes: 'purpose', - paginate: { - size: 30, - number: 1 - } - ) - .and_return([example_v2_tube, example_v2_tube2]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_all).with( + include_used: false, + purpose_name: ['example-purpose'], + includes: 'purpose', + paginate: { + size: 30, + number: 1 + } + ).and_return([example_v2_tube, example_v2_tube2]) # Parent lookup - allow(Sequencescape::Api::V2::Tube).to receive(:find_all) - .with(barcode: [tube_barcode_1, tube_barcode_2], includes: []) - .and_return([example_v2_tube, example_v2_tube2]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_all).with( + barcode: [tube_barcode_1, tube_barcode_2], + includes: [] + ).and_return([example_v2_tube, example_v2_tube2]) # Old API still used when loading parent stub_api_get(tube_uuid, body: example_tube) diff --git a/spec/features/viewing_a_minimal_plate_spec.rb b/spec/features/viewing_a_minimal_plate_spec.rb index 383a86d8b..74d660178 100644 --- a/spec/features/viewing_a_minimal_plate_spec.rb +++ b/spec/features/viewing_a_minimal_plate_spec.rb @@ -64,7 +64,7 @@ scenario 'there is a warning' do fill_in_swipecard_and_barcode user_swipecard, plate_barcode expect(find('.asset-warnings')).to have_content( - 'Libraries on this plate have already been completed. ' \ + 'Submission (active) is not present for this labware. ' \ 'Any further work conducted from this plate may run into issues at the end of the pipeline.' ) end @@ -76,7 +76,7 @@ scenario 'there is a warning' do fill_in_swipecard_and_barcode user_swipecard, plate_barcode expect(find('.asset-warnings')).to have_content( - 'Libraries on this plate have already been failed (A1-E1). You should not carry out further work. ' \ + 'Submission on this plate has already been failed (A1-E1). You should not carry out further work. ' \ 'Any further work conducted from this plate will run into issues at the end of the pipeline.' ) end @@ -105,7 +105,7 @@ scenario 'there is a warning' do fill_in_swipecard_and_barcode user_swipecard, plate_barcode expect(find('.asset-warnings')).to have_content( - 'Libraries on this plate have already been completed. ' \ + 'Submission (active) is not present for this labware. ' \ 'Any further work conducted from this plate may run into issues at the end of the pipeline.' ) end diff --git a/spec/features/viewing_a_plate_spec.rb b/spec/features/viewing_a_plate_spec.rb index 253f643a1..222c4ef11 100644 --- a/spec/features/viewing_a_plate_spec.rb +++ b/spec/features/viewing_a_plate_spec.rb @@ -109,7 +109,7 @@ scenario 'there is a warning' do fill_in_swipecard_and_barcode user_swipecard, plate_barcode expect(find('.asset-warnings')).to have_content( - 'Libraries on this plate have already been completed. ' \ + 'Submission (active) is not present for this labware. ' \ 'Any further work conducted from this plate may run into issues at the end of the pipeline.' ) end diff --git a/spec/helpers/barcode_labels_helper_spec.rb b/spec/helpers/barcode_labels_helper_spec.rb index 8f86888b4..be355d26e 100644 --- a/spec/helpers/barcode_labels_helper_spec.rb +++ b/spec/helpers/barcode_labels_helper_spec.rb @@ -22,20 +22,12 @@ end it 'renders a partial' do - barcode_printing_form( - labels: labels, - redirection_url: redirection_url, - default_printer_name: default_printer_name - ) + barcode_printing_form(labels:, redirection_url:, default_printer_name:) expect(rendered).to be_truthy end it 'has the right locals set' do - barcode_printing_form( - labels: labels, - redirection_url: redirection_url, - default_printer_name: default_printer_name - ) + barcode_printing_form(labels:, redirection_url:, default_printer_name:) printer_types = labels.map(&:printer_type) printers = @printers.select { |printer| printer_types.include?(printer.barcode_type) } diff --git a/spec/models/labels/plate_label_96_lysate_spec.rb b/spec/models/labels/plate_label_96_lysate_spec.rb index 59dcead95..9434c821a 100644 --- a/spec/models/labels/plate_label_96_lysate_spec.rb +++ b/spec/models/labels/plate_label_96_lysate_spec.rb @@ -9,8 +9,8 @@ # current partner ids have the format ABCD_123 i.e. 4 characters, an underscore, and 3 numbers let(:partner_id) { 'ABCD_123' } let(:sample_metadata) { create :v2_sample_metadata, sample_description: partner_id } - let(:sample) { create(:v2_sample, sample_metadata: sample_metadata) } - let(:aliquot) { create :v2_aliquot, sample: sample } + let(:sample) { create(:v2_sample, sample_metadata:) } + let(:aliquot) { create :v2_aliquot, sample: } let(:well_c6) { create(:v2_well, position: { 'name' => 'C6' }, aliquots: [aliquot]) } let(:labware) { create :v2_plate, wells: [well_c6] } diff --git a/spec/models/labware_creators/baited_plate_spec.rb b/spec/models/labware_creators/baited_plate_spec.rb index 798f39901..df6761193 100644 --- a/spec/models/labware_creators/baited_plate_spec.rb +++ b/spec/models/labware_creators/baited_plate_spec.rb @@ -21,7 +21,9 @@ let(:transfer_template_uuid) { 'custom-pooling' } let(:transfer_template) { json :transfer_template, uuid: transfer_template_uuid } - let(:form_attributes) { { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid: } } + + let(:bait_library_layout) { create :bait_library_layout } let(:transfer_requests) do WellHelpers.column_order(96)[0, 6].map do |well_name| @@ -36,32 +38,6 @@ context 'create plate' do has_a_working_api - let!(:bait_library_layout_preview_request) do - stub_api_post( - 'bait_library_layouts/preview', - payload: { - bait_library_layout: { - plate: parent_uuid, - user: user_uuid - } - }, - body: json(:bait_library_layout) - ) - end - - let!(:bait_library_layout_request) do - stub_api_post( - 'bait_library_layouts', - payload: { - bait_library_layout: { - plate: 'child-uuid', - user: user_uuid - } - }, - body: json(:bait_library_layout) - ) - end - let!(:plate_creation_request) do stub_api_post( 'plate_creations', @@ -79,6 +55,9 @@ before do stub_v2_plate(parent, stub_search: false) stub_v2_plate(child, stub_search: false) + + stub_api_v2_post('BaitLibraryLayout') + stub_api_v2_post('BaitLibraryLayout', [bait_library_layout], method: :preview) end let!(:transfer_creation_request) do diff --git a/spec/models/labware_creators/common_file_handling/csv_file/row_base_spec.rb b/spec/models/labware_creators/common_file_handling/csv_file/row_base_spec.rb index 0f7b4f2c7..f9c83288d 100644 --- a/spec/models/labware_creators/common_file_handling/csv_file/row_base_spec.rb +++ b/spec/models/labware_creators/common_file_handling/csv_file/row_base_spec.rb @@ -47,6 +47,60 @@ ) end end + + context 'when row_data contains valid characters with invisible spaces' do + let(:row_barcode) { "some\u00A0 data" } # \u00A0 is a non-breaking space + + it 'adds an error for the invisible space' do + subject.check_for_invalid_characters + expect(subject.errors.full_messages).to include( + "contains invalid character(s) at column 2 in #{subject}, " \ + 'please use only standard characters and UTF-8 encoding for your csv file' + ) + end + end + + context 'when row_data contains only spaces' do + let(:row_barcode) { ' ' } + + it 'does not add any errors' do + subject.check_for_invalid_characters + expect(subject.errors.full_messages).to be_empty + end + end + + context 'when row_data contains spaces with invisible characters' do + let(:row_barcode) { " \u200B \u200B " } # \u200B is a zero-width space + + it 'adds an error for the invisible space' do + subject.check_for_invalid_characters + expect(subject.errors.full_messages).to include( + "contains invalid character(s) at column 2 in #{subject}, " \ + 'please use only standard characters and UTF-8 encoding for your csv file' + ) + end + end + + context 'when row_data contains invalid invisible characters' do + let(:row_barcode) { "\u200Csome data\u200C" } # \u200C is a zero-width non-joiner + + it 'adds an error for the invalid invisible character' do + subject.check_for_invalid_characters + expect(subject.errors.full_messages).to include( + "contains invalid character(s) at column 2 in #{subject}, " \ + 'please use only standard characters and UTF-8 encoding for your csv file' + ) + end + end + + context 'when row_data contains valid characters and nil cells' do + let(:row_data) { ['A1', '', nil] } + + it 'does not add any errors' do + subject.check_for_invalid_characters + expect(subject.errors.full_messages).to be_empty + end + end end # Testing the validation for the number of columns diff --git a/spec/models/labware_creators/concentration_binned_plate_spec.rb b/spec/models/labware_creators/concentration_binned_plate_spec.rb index 34072a6ae..875905a39 100644 --- a/spec/models/labware_creators/concentration_binned_plate_spec.rb +++ b/spec/models/labware_creators/concentration_binned_plate_spec.rb @@ -85,10 +85,12 @@ let(:user_uuid) { 'user-uuid' } before do - create :concentration_binning_purpose_config, - uuid: child_purpose_uuid, - name: child_purpose_name, - library_type_name: library_type_name + create( + :concentration_binning_purpose_config, + uuid: child_purpose_uuid, + name: child_purpose_name, + library_type_name: library_type_name + ) stub_v2_plate(child_plate, stub_search: false) stub_v2_plate( parent_plate, diff --git a/spec/models/labware_creators/concentration_normalised_plate_spec.rb b/spec/models/labware_creators/concentration_normalised_plate_spec.rb index 009b8e168..edaaf4d93 100644 --- a/spec/models/labware_creators/concentration_normalised_plate_spec.rb +++ b/spec/models/labware_creators/concentration_normalised_plate_spec.rb @@ -115,9 +115,9 @@ it 'makes the expected requests' do # NB. qc assay post is done using v2 Api, whereas plate creation and transfers posts are using v1 Api - expect(Sequencescape::Api::V2::QcAssay).to receive(:create) - .with(qc_results: dest_well_qc_attributes) - .and_return(true) + expect(Sequencescape::Api::V2::QcAssay).to receive(:create).with( + qc_results: dest_well_qc_attributes + ).and_return(true) expect(subject.save!).to eq true expect(plate_creation_request).to have_been_made expect(transfer_creation_request).to have_been_made diff --git a/spec/models/labware_creators/custom_pooled_tubes_spec.rb b/spec/models/labware_creators/custom_pooled_tubes_spec.rb index c9ed9f2e9..b8fff5277 100644 --- a/spec/models/labware_creators/custom_pooled_tubes_spec.rb +++ b/spec/models/labware_creators/custom_pooled_tubes_spec.rb @@ -25,7 +25,7 @@ let(:parent_uuid) { SecureRandom.uuid } let(:parent) { json :plate, uuid: parent_uuid, stock_plate_barcode: 5, qc_files_actions: %w[read create] } let(:v2_plate) { create(:v2_plate, uuid: parent_uuid) } - let(:form_attributes) { { purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { purpose_uuid:, parent_uuid: } } let(:wells_json) { json :well_collection, size: 16, default_state: 'passed' } @@ -53,49 +53,46 @@ content end - let(:form_attributes) { { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid, file: file } } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid:, file: } } let(:stub_qc_file_creation) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="robot_pooling_file.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'pooling_file.csv'), - headers: { - 'content-type' => 'application/json' - } - ) - end - - let(:tube_creation_request_uuid) { SecureRandom.uuid } - - let(:tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid, purpose_uuid], - tube_attributes: [{ name: 'DN5 A1:B2' }, { name: 'DN5 C1:G2' }] - } - }, - body: json(:specific_tube_creation, uuid: tube_creation_request_uuid, children_count: 2) + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="robot_pooling_file.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'pooling_file.csv'), + headers: { + 'content-type' => 'application/json' + } ) end - # Find out what tubes we've just made! - let(:tube_creation_children_request) do - stub_api_get( - tube_creation_request_uuid, - 'children', - body: json(:tube_collection, names: ['DN5 A1:B2', 'DN5 C1:G2']) + def expect_specific_tube_creation + child_tubes = [ + create(:v2_tube, name: 'DN5 A1:B2', uuid: 'tube-0'), + create(:v2_tube, name: 'DN5 C1:G2', uuid: 'tube-1') + ] + + # Create a mock for the specific tube creation. + specific_tube_creation = double + allow(specific_tube_creation).to receive(:children).and_return(child_tubes) + + # Expect the post request and return the mock. + expect_api_v2_posts( + 'SpecificTubeCreation', + [ + { + child_purpose_uuids: [purpose_uuid, purpose_uuid], + parent_uuids: [parent_uuid], + tube_attributes: child_tubes.map { |tube| { name: tube.name } }, + user_uuid: user_uuid + } + ], + [specific_tube_creation] ) end @@ -138,8 +135,6 @@ before do stub_parent_request stub_qc_file_creation - tube_creation_children_request - tube_creation_request transfer_creation_request end @@ -149,9 +144,10 @@ end it 'pools according to the file' do + expect_specific_tube_creation + expect(subject.save).to be_truthy expect(stub_qc_file_creation).to have_been_made.once - expect(tube_creation_request).to have_been_made.once expect(transfer_creation_request).to have_been_made.once end end diff --git a/spec/models/labware_creators/custom_tagged_plate_spec.rb b/spec/models/labware_creators/custom_tagged_plate_spec.rb index 4c605f864..5a1ecd5a9 100644 --- a/spec/models/labware_creators/custom_tagged_plate_spec.rb +++ b/spec/models/labware_creators/custom_tagged_plate_spec.rb @@ -95,49 +95,69 @@ context 'On create' do let(:tag_plate_uuid) { 'tag-plate' } let(:tag_template_uuid) { 'tag-layout-template' } - let(:child_plate_uuid) { SecureRandom.uuid } let(:parents) { [plate_uuid, tag_plate_uuid] } - let!(:plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - parents: parents, - child_purpose: child_purpose_uuid, - user: user_uuid - } - }, - body: json(:plate_creation, child_uuid: child_plate_uuid) + let(:expected_transfers) { WellHelpers.stamp_hash(96) } + + let(:child_plate) { create :v2_plate } + + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [{ child_purpose_uuid: child_purpose_uuid, parent_uuids: parents, user_uuid: user_uuid }], + [pooled_plate_creation] ) end - let(:expected_transfers) { WellHelpers.stamp_hash(96) } + def expect_state_change_creation + expect_api_v2_posts( + 'StateChange', + [ + { + reason: 'Used in Library creation', + target_uuid: tag_plate_uuid, + target_state: 'exhausted', + user_uuid: user_uuid + } + ] + ) + end - def expect_transfer_creation + def expect_tag_layout_creation expect_api_v2_posts( - 'Transfer', + 'TagLayout', [ { user_uuid: user_uuid, - source_uuid: plate_uuid, - destination_uuid: child_plate_uuid, - transfer_template_uuid: transfer_template_uuid, - transfers: expected_transfers + plate_uuid: child_plate.uuid, + tag_group_uuid: 'tag-group-uuid', + tag2_group_uuid: 'tag2-group-uuid', + direction: 'column', + walking_by: 'manual by plate', + initial_tag: '1', + tags_per_well: 1 } ] ) end - def expect_state_change_creation + def expect_transfer_creation expect_api_v2_posts( - 'StateChange', + 'Transfer', [ { - reason: 'Used in Library creation', - target_uuid: tag_plate_uuid, - target_state: 'exhausted', - user_uuid: user_uuid + user_uuid: user_uuid, + source_uuid: plate_uuid, + destination_uuid: child_plate.uuid, + transfer_template_uuid: transfer_template_uuid, + transfers: expected_transfers } ] ) @@ -157,13 +177,14 @@ def expect_state_change_creation state: tag_plate_state }, tag_layout: { - user: 'user-uuid', - tag_group: 'tag-group-uuid', - tag2_group: 'tag2-group-uuid', + user_uuid: 'user-uuid', + tag_group_uuid: 'tag-group-uuid', + tag2_group_uuid: 'tag2-group-uuid', direction: 'column', walking_by: 'manual by plate', initial_tag: '1', - substitutions: {}, + substitutions: { + }, tags_per_well: 1 } } @@ -176,54 +197,38 @@ def expect_state_change_creation it_behaves_like 'it has a custom page', 'custom_tagged_plate' context 'on save' do - let!(:custom_tag_layout_creation_request) do - stub_api_post( - 'tag_layouts', - payload: { - tag_layout: { - user: 'user-uuid', - plate: child_plate_uuid, - tag_group: 'tag-group-uuid', - tag2_group: 'tag2-group-uuid', - direction: 'column', - walking_by: 'manual by plate', - initial_tag: '1', - tags_per_well: 1 - } - } - ) - end - context 'with an available tag plate' do let(:tag_plate_state) { 'available' } it 'creates a tag plate' do - expect_transfer_creation + expect_pooled_plate_creation expect_state_change_creation + expect_tag_layout_creation + expect_transfer_creation expect(subject.save).to be true - expect(plate_creation_request).to have_been_made.once - expect(custom_tag_layout_creation_request).to have_been_made.once end it 'has the correct child (and uuid)' do + stub_api_v2_post('PooledPlateCreation', pooled_plate_creation) + stub_api_v2_post('TagLayout') stub_api_v2_post('Transfer') stub_api_v2_post('StateChange') expect(subject.save).to be true # This will be our new plate - expect(subject.child.uuid).to eq(child_plate_uuid) + expect(subject.child.uuid).to eq(child_plate.uuid) end context 'when a user has exhausted the plate in another tab' do it 'creates a tag plate' do - expect_transfer_creation + expect_pooled_plate_creation expect_state_change_creation + expect_tag_layout_creation + expect_transfer_creation expect(subject.save).to be true - expect(plate_creation_request).to have_been_made.once - expect(custom_tag_layout_creation_request).to have_been_made.once end end end @@ -232,23 +237,25 @@ def expect_state_change_creation let(:tag_plate_state) { 'exhausted' } it 'creates a tagged plate' do + # This one will be VERY different + expect_tag_layout_creation + + expect_pooled_plate_creation expect_transfer_creation expect(Sequencescape::Api::V2::StateChange).not_to receive(:create!) expect(subject.save).to be true - expect(plate_creation_request).to have_been_made.once - - # This one will be VERY different - expect(custom_tag_layout_creation_request).to have_been_made.once end it 'has the correct child (and uuid)' do + stub_api_v2_post('PooledPlateCreation', pooled_plate_creation) + stub_api_v2_post('TagLayout') stub_api_v2_post('Transfer') expect(subject.save).to be true # This will be our new plate - expect(subject.child.uuid).to eq(child_plate_uuid) + expect(subject.child.uuid).to eq(child_plate.uuid) end end @@ -258,19 +265,21 @@ def expect_state_change_creation let(:parents) { [plate_uuid] } it 'creates a tag plate' do + expect_pooled_plate_creation + expect_tag_layout_creation expect_transfer_creation expect(Sequencescape::Api::V2::StateChange).not_to receive(:create!) expect(subject.save).to be true - expect(plate_creation_request).to have_been_made.once - expect(custom_tag_layout_creation_request).to have_been_made.once end it 'has the correct child (and uuid)' do + stub_api_v2_post('PooledPlateCreation', pooled_plate_creation) + stub_api_v2_post('TagLayout') stub_api_v2_post('Transfer') expect(subject.save).to be true - expect(subject.child.uuid).to eq(child_plate_uuid) + expect(subject.child.uuid).to eq(child_plate.uuid) end end end diff --git a/spec/models/labware_creators/donor_pooling_plate_spec.rb b/spec/models/labware_creators/donor_pooling_plate_spec.rb index 843f690ff..e5a5723e7 100644 --- a/spec/models/labware_creators/donor_pooling_plate_spec.rb +++ b/spec/models/labware_creators/donor_pooling_plate_spec.rb @@ -76,9 +76,10 @@ create(:donor_pooling_plate_purpose_config, uuid: child_purpose_uuid) # Allow the API call to return two plates by default. - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ barcode: barcodes }, includes: described_class::SOURCE_PLATE_INCLUDES) - .and_return(source_plates) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with( + { barcode: barcodes }, + includes: described_class::SOURCE_PLATE_INCLUDES + ).and_return(source_plates) end describe '.attributes' do @@ -695,9 +696,10 @@ describe '#source_barcodes_must_be_different' do before do - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ barcode: barcodes }, includes: described_class::SOURCE_PLATE_INCLUDES) - .and_return([parent_1_plate]) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with( + { barcode: barcodes }, + includes: described_class::SOURCE_PLATE_INCLUDES + ).and_return([parent_1_plate]) end let(:barcodes) { [parent_1_plate.human_barcode] * 2 } it 'reports the error' do @@ -720,9 +722,10 @@ [well] end before do - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ barcode: barcodes }, includes: described_class::SOURCE_PLATE_INCLUDES) - .and_return([parent_1_plate]) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with( + { barcode: barcodes }, + includes: described_class::SOURCE_PLATE_INCLUDES + ).and_return([parent_1_plate]) end let(:barcodes) { [parent_1_plate.human_barcode] } it 'allows plate creation' do @@ -735,9 +738,10 @@ describe '#source_plates_must_exist' do let(:barcodes) { [parent_1_plate.human_barcode, 'NOT-A-PLATE-BARCODE'] } before do - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ barcode: barcodes }, includes: described_class::SOURCE_PLATE_INCLUDES) - .and_return([parent_1_plate]) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with( + { barcode: barcodes }, + includes: described_class::SOURCE_PLATE_INCLUDES + ).and_return([parent_1_plate]) end it 'reports the error' do expect(subject).not_to be_valid diff --git a/spec/models/labware_creators/final_tube_from_plate_spec.rb b/spec/models/labware_creators/final_tube_from_plate_spec.rb index 371189bcb..077d4bb62 100644 --- a/spec/models/labware_creators/final_tube_from_plate_spec.rb +++ b/spec/models/labware_creators/final_tube_from_plate_spec.rb @@ -16,7 +16,7 @@ let(:parent_uuid) { SecureRandom.uuid } let(:parent) { json :plate, uuid: parent_uuid, pool_sizes: [3, 3] } - let(:form_attributes) { { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid: } } context '#save!' do has_a_working_api diff --git a/spec/models/labware_creators/fixed_normalised_plate_spec.rb b/spec/models/labware_creators/fixed_normalised_plate_spec.rb index aad996d2e..29e477651 100644 --- a/spec/models/labware_creators/fixed_normalised_plate_spec.rb +++ b/spec/models/labware_creators/fixed_normalised_plate_spec.rb @@ -85,10 +85,12 @@ let(:user_uuid) { 'user-uuid' } before do - create :fixed_normalisation_purpose_config, - uuid: child_purpose_uuid, - name: child_purpose_name, - library_type_name: library_type_name + create( + :fixed_normalisation_purpose_config, + uuid: child_purpose_uuid, + name: child_purpose_name, + library_type_name: library_type_name + ) stub_v2_plate(child_plate, stub_search: false) stub_v2_plate( diff --git a/spec/models/labware_creators/merged_plate_spec.rb b/spec/models/labware_creators/merged_plate_spec.rb index 987c79ff7..f67c4e403 100644 --- a/spec/models/labware_creators/merged_plate_spec.rb +++ b/spec/models/labware_creators/merged_plate_spec.rb @@ -54,15 +54,6 @@ creator_class: 'LabwareCreators::MergedPlate' end - let(:child_plate) do - create :v2_plate, - uuid: 'child-uuid', - barcode_number: '4', - size: plate_size, - outer_requests: requests, - purpose: child_purpose - end - let(:requests) do Array.new(plate_size) { |i| create :library_request, state: 'started', uuid: "request-#{i}", submission_id: 1 } end @@ -70,7 +61,6 @@ let(:user_uuid) { 'user-uuid' } before do - stub_v2_plate(child_plate, stub_search: false) stub_v2_plate(source_plate_1, stub_search: false) stub_v2_plate(source_plate_2, stub_search: false) end @@ -81,27 +71,13 @@ describe '#save!' do before do allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with( - { barcode: [source_plate_1.barcode.machine, source_plate_2.barcode.machine] }, - includes: plate_includes - ) - .and_return([source_plate_1, source_plate_2]) + receive(:find_all).with( + { barcode: [source_plate_1.barcode.machine, source_plate_2.barcode.machine] }, + includes: plate_includes + ).and_return([source_plate_1, source_plate_2]) ) - end - let!(:plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: child_purpose_uuid, - parents: [source_plate_1.uuid, source_plate_2.uuid] - } - }, - body: json(:plate_creation, child_uuid: child_plate.uuid) - ) + stub_v2_plate(child_plate, stub_search: false) end let!(:transfer_creation_request) do @@ -117,10 +93,42 @@ ) end + let(:child_plate) do + create :v2_plate, + uuid: 'child-uuid', + barcode_number: '4', + size: plate_size, + outer_requests: requests, + purpose: child_purpose + end + + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [ + { + child_purpose_uuid: child_purpose_uuid, + parent_uuids: [source_plate_1.uuid, source_plate_2.uuid], + user_uuid: user_uuid + } + ], + [pooled_plate_creation] + ) + end + it 'makes the expected requests' do + expect_pooled_plate_creation + expect(subject).to be_valid expect(subject.save!).to eq true - expect(plate_creation_request).to have_been_made + expect(transfer_creation_request).to have_been_made end end @@ -209,9 +217,10 @@ ) stub_v2_plate(source_plate_3, stub_search: false) allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with({ barcode: [source_plate_1.barcode.machine, source_plate_3.barcode.machine] }, includes: plate_includes) - .and_return([source_plate_1, source_plate_3]) + receive(:find_all).with( + { barcode: [source_plate_1.barcode.machine, source_plate_3.barcode.machine] }, + includes: plate_includes + ).and_return([source_plate_1, source_plate_3]) ) end @@ -251,9 +260,10 @@ ) stub_v2_plate(source_plate_3, stub_search: false) allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with({ barcode: [source_plate_1.barcode.machine, source_plate_3.barcode.machine] }, includes: plate_includes) - .and_return([source_plate_1, source_plate_3]) + receive(:find_all).with( + { barcode: [source_plate_1.barcode.machine, source_plate_3.barcode.machine] }, + includes: plate_includes + ).and_return([source_plate_1, source_plate_3]) ) end @@ -279,9 +289,9 @@ source_purposes: ['Source 1 Purpose', 'Source 2 Purpose'] ) allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with({ barcode: [source_plate_1.barcode.machine] }, includes: plate_includes) - .and_return([source_plate_1]) + receive(:find_all).with({ barcode: [source_plate_1.barcode.machine] }, includes: plate_includes).and_return( + [source_plate_1] + ) ) end @@ -309,9 +319,10 @@ source_purposes: ['Source 1 Purpose', 'Source 2 Purpose'] ) allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with({ barcode: [source_plate_1.barcode.machine, source_plate_1.barcode.machine] }, includes: plate_includes) - .and_return([source_plate_1]) + receive(:find_all).with( + { barcode: [source_plate_1.barcode.machine, source_plate_1.barcode.machine] }, + includes: plate_includes + ).and_return([source_plate_1]) ) end @@ -349,9 +360,10 @@ source_purposes: ['Source 1 Purpose', 'Source 2 Purpose'] ) allow(Sequencescape::Api::V2::Plate).to( - receive(:find_all) - .with({ barcode: [source_plate_1.barcode.machine, source_plate_4.barcode.machine] }, includes: plate_includes) - .and_return([source_plate_1, source_plate_4]) + receive(:find_all).with( + { barcode: [source_plate_1.barcode.machine, source_plate_4.barcode.machine] }, + includes: plate_includes + ).and_return([source_plate_1, source_plate_4]) ) end diff --git a/spec/models/labware_creators/multi_plate_pool_spec.rb b/spec/models/labware_creators/multi_plate_pool_spec.rb index adcca6f6e..0f9c6ac2e 100644 --- a/spec/models/labware_creators/multi_plate_pool_spec.rb +++ b/spec/models/labware_creators/multi_plate_pool_spec.rb @@ -53,7 +53,7 @@ end context 'on create' do - subject { LabwareCreators::MultiPlatePool.new(api, form_attributes.merge(user_uuid: user_uuid)) } + subject { LabwareCreators::MultiPlatePool.new(api, form_attributes.merge(user_uuid:)) } let(:plate_b_uuid) { 'example-plate-b-uuid' } let(:plate_b_barcode) { SBCF::SangerBarcode.new(prefix: 'DN', number: 2).machine_barcode.to_s } @@ -77,18 +77,13 @@ } end - let!(:pooled_plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: child_purpose_uuid, - parents: [plate_uuid, plate_b_uuid] - } - }, - body: json(:plate_creation, child_uuid: child_plate_uuid) - ) + let(:child_plate) { create :v2_plate } + + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response end let!(:bulk_transfer_request) do @@ -101,38 +96,48 @@ { 'source_uuid' => plate_uuid, 'source_location' => 'A1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'A1' }, { 'source_uuid' => plate_uuid, 'source_location' => 'B1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'A1' }, { 'source_uuid' => plate_b_uuid, 'source_location' => 'A1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'B1' }, { 'source_uuid' => plate_b_uuid, 'source_location' => 'B1', - 'destination_uuid' => child_plate_uuid, + 'destination_uuid' => child_plate.uuid, 'destination_location' => 'B1' } ] } }, - body: json(:plate_creation, child_uuid: child_plate_uuid) + body: json(:plate_creation, child_uuid: child_plate.uuid) + ) + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [{ child_purpose_uuid: child_purpose_uuid, parent_uuids: [plate_uuid, plate_b_uuid], user_uuid: user_uuid }], + [pooled_plate_creation] ) end context '#save!' do it 'creates a plate!' do + expect_pooled_plate_creation + subject.save! - expect(pooled_plate_creation_request).to have_been_made.once + expect(bulk_transfer_request).to have_been_made.once end end diff --git a/spec/models/labware_creators/multi_stamp_spec.rb b/spec/models/labware_creators/multi_stamp_spec.rb index b7126d1c5..e1da3803d 100644 --- a/spec/models/labware_creators/multi_stamp_spec.rb +++ b/spec/models/labware_creators/multi_stamp_spec.rb @@ -11,7 +11,6 @@ let(:parent1_uuid) { 'parent1-plate-uuid' } let(:parent2_uuid) { 'parent2-plate-uuid' } - let(:child_uuid) { 'child-uuid' } let(:requests_parent1) { Array.new(24) { |i| create :library_request, state: 'started', uuid: "request-p1-#{i}" } } let(:requests_parent2) { Array.new(24) { |i| create :library_request, state: 'started', uuid: "request-p2-#{i}" } } @@ -41,21 +40,19 @@ stock_plate: stock_plate2 ) end - let(:child_plate_v2) { create :v2_plate, uuid: child_uuid, barcode_number: '5', size: 96 } - let(:child_plate_v1) { json :stock_plate_with_metadata, stock_plate: { barcode: '5', uuid: child_uuid } } + let(:child_plate) { create :v2_plate, barcode_number: '5', size: 96 } let(:child_purpose_uuid) { 'child-purpose' } let(:child_purpose_name) { 'Child Purpose' } let(:user_uuid) { 'user-uuid' } - let(:user) { json :v1_user, uuid: user_uuid } before do create :purpose_config, name: child_purpose_name, uuid: child_purpose_uuid stub_v2_plate(parent1, stub_search: false) stub_v2_plate(parent2, stub_search: false) - stub_v2_plate(child_plate_v2, stub_search: false, custom_query: [:plate_with_wells, child_plate_v2.uuid]) + stub_v2_plate(child_plate, stub_search: false, custom_query: [:plate_with_wells, child_plate.uuid]) end context 'on new' do @@ -77,7 +74,7 @@ end context 'on create' do - subject { LabwareCreators::MultiStamp.new(api, form_attributes.merge(user_uuid: user_uuid)) } + subject { LabwareCreators::MultiStamp.new(api, form_attributes.merge(user_uuid:)) } let(:form_attributes) do { @@ -484,7 +481,7 @@ parents: [parent1_uuid, parent2_uuid] } }, - body: json(:plate_creation, child_uuid: child_uuid) + body: json(:plate_creation, child_uuid: child_plate.uuid) ) end @@ -554,19 +551,33 @@ ) end + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [{ child_purpose_uuid: child_purpose_uuid, parent_uuids: [parent1_uuid, parent2_uuid], user_uuid: user_uuid }], + [pooled_plate_creation] + ) + end + context '#save!' do setup do - stub_api_get(child_plate_v2.uuid, body: child_plate_v1) - - stub_api_get('user-uuid', body: user) - stub_api_get('asset-uuid', body: child_plate_v1) + # stub_api_get('user-uuid', body: user) end it 'creates a plate!' do + expect_pooled_plate_creation + subject.save! - expect(pooled_plate_creation_request).to have_been_made.once + expect(transfer_creation_request).to have_been_made.once - expect(subject.child.uuid).to eq(child_uuid) + expect(subject.child.uuid).to eq(child_plate.uuid) expect(subject).to be_valid expect(subject.errors.messages).to be_empty end diff --git a/spec/models/labware_creators/multi_stamp_tubes_spec.rb b/spec/models/labware_creators/multi_stamp_tubes_spec.rb index 9cb244efa..5d0df5a90 100644 --- a/spec/models/labware_creators/multi_stamp_tubes_spec.rb +++ b/spec/models/labware_creators/multi_stamp_tubes_spec.rb @@ -32,13 +32,8 @@ receptacle: parent2_receptacle end - let(:child_uuid) { 'child-uuid' } let(:child_purpose_uuid) { 'child-purpose' } let(:child_purpose_name) { 'Child Purpose' } - let(:child_plate_v2) do - create :v2_plate_for_submission, uuid: child_uuid, purpose_name: child_purpose_name, barcode_number: '5', size: 96 - end - let(:child_plate_v1) { json :stock_plate_with_metadata, stock_plate: { barcode: '5', uuid: child_uuid } } let(:user_uuid) { 'user-uuid' } let(:user) { json :v1_user, uuid: user_uuid } @@ -51,7 +46,6 @@ Settings.submission_templates = { 'example' => example_template_uuid } stub_v2_tube(parent1, stub_search: false) stub_v2_tube(parent2, stub_search: false) - stub_v2_plate(child_plate_v2, stub_search: false, custom_includes: 'wells,wells.aliquots,wells.aliquots.study') end context 'on new' do @@ -73,7 +67,7 @@ end context 'on create' do - subject { LabwareCreators::MultiStampTubes.new(api, form_attributes.merge(user_uuid: user_uuid)) } + subject { LabwareCreators::MultiStampTubes.new(api, form_attributes.merge(user_uuid:)) } let(:form_attributes) do { @@ -86,20 +80,6 @@ } end - let!(:ms_plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: child_purpose_uuid, - parents: [parent1_tube_uuid, parent2_tube_uuid] - } - }, - body: json(:plate_creation, child_uuid: child_uuid) - ) - end - let(:transfer_requests) do [ { source_asset: 'tube1', target_asset: '5-well-A1', outer_request: 'outer-request-1' }, @@ -119,6 +99,32 @@ body: '{}' ) end + + let(:child_plate) do + create :v2_plate_for_submission, purpose_name: child_purpose_name, barcode_number: '5', size: 96 + end + + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [ + { + child_purpose_uuid: child_purpose_uuid, + parent_uuids: [parent1_tube_uuid, parent2_tube_uuid], + user_uuid: user_uuid + } + ], + [pooled_plate_creation] + ) + end + context 'when the submission is created' do describe 'internal methods' do it 'determines the configuration for the submission' do @@ -185,31 +191,7 @@ context '#save!' do setup do - stub_api_get(child_plate_v2.uuid, body: child_plate_v1) - stub_api_get( - 'custom_metadatum_collection-uuid', - body: json(:v1_custom_metadatum_collection, uuid: 'custom_metadatum_collection-uuid') - ) - stub_api_get('user-uuid', body: user) - stub_api_get('asset-uuid', body: child_plate_v1) - expect(subject).to receive(:parent_tubes).and_return([parent1, parent2]) - - metadata = attributes_for(:v1_custom_metadatum_collection).fetch(:metadata, {}) - - stub_api_put( - 'custom_metadatum_collection-uuid', - payload: { - custom_metadatum_collection: { - metadata: metadata - } - }, - body: json(:v1_custom_metadatum_collection) - ) - - expect('Sequencescape::Api::V2'.constantize).to receive(:plate_with_wells) - .with(child_uuid) - .and_return(child_plate_v2) expect(subject).to receive(:source_tube_outer_request_uuid).with(parent1).and_return('outer-request-1') expect(subject).to receive(:source_tube_outer_request_uuid).with(parent2).and_return('outer-request-2') end @@ -242,19 +224,6 @@ aliquots: [aliquot2] end - let(:child_aliquot1) { create :v2_aliquot, study_id: 1 } - let(:child_aliquot2) { create :v2_aliquot, study_id: 2 } - let(:child_well1) { create :v2_stock_well, location: 'A1', uuid: '5-well-A1', aliquots: [child_aliquot1] } - let(:child_well2) { create :v2_stock_well, location: 'B1', uuid: '5-well-B1', aliquots: [child_aliquot2] } - let(:child_plate_v2) do - create :v2_plate_for_submission, - uuid: child_uuid, - purpose_name: child_purpose_name, - barcode_number: '5', - size: 96, - wells: [child_well1, child_well2] - end - let!(:order_request) do stub_api_get(example_template_uuid, body: json(:submission_template, uuid: example_template_uuid)) stub_api_post( @@ -291,8 +260,10 @@ end it 'creates a plate!' do + expect_pooled_plate_creation + subject.save! - expect(ms_plate_creation_request).to have_been_made.once + expect(transfer_creation_request).to have_been_made.once expect(order_request).to have_been_made.once expect(submission_request).to have_been_made.once diff --git a/spec/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan_spec.rb b/spec/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan_spec.rb index e0d46906c..6c4d584fe 100644 --- a/spec/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan_spec.rb +++ b/spec/models/labware_creators/multi_stamp_tubes_using_tube_rack_scan_spec.rb @@ -84,30 +84,10 @@ [:purpose, 'receptacle.aliquots.request.request_type', 'receptacle.requests_as_source.request_type'] end - # child aliquots - let(:child_aliquot1) { create :v2_aliquot } - let(:child_aliquot2) { create :v2_aliquot } - - # child wells - let(:child_well1) { create :v2_well, location: 'A1', uuid: '5-well-A1', aliquots: [child_aliquot1] } - let(:child_well2) { create :v2_well, location: 'B1', uuid: '5-well-B1', aliquots: [child_aliquot2] } - # child plate - let(:child_plate_uuid) { 'child-uuid' } let(:child_plate_purpose_uuid) { 'child-purpose' } let(:child_plate_purpose_name) { 'Child Purpose' } - let(:child_plate_v2) do - create :v2_plate, - uuid: child_plate_uuid, - purpose_name: child_plate_purpose_name, - barcode_number: '5', - size: 96, - wells: [child_well1, child_well2] - end - - let(:child_plate_v2) do - create :v2_plate, uuid: child_plate_uuid, purpose_name: child_plate_purpose_name, barcode_number: '5', size: 96 - end + let(:child_plate) { create :v2_plate, purpose_name: child_plate_purpose_name, barcode_number: '5', size: 96 } let(:user_uuid) { 'user-uuid' } let(:user) { json :v1_user, uuid: user_uuid } @@ -132,39 +112,37 @@ end let(:stub_upload_file_creation) do - stub_request(:post, api_url_for(child_plate_uuid, 'qc_files')) - .with( - body: file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="tube_rack_scan.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'tube_rack_scan.csv'), - headers: { - 'content-type' => 'application/json' - } - ) + stub_request(:post, api_url_for(child_plate.uuid, 'qc_files')).with( + body: file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="tube_rack_scan.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'tube_rack_scan.csv'), + headers: { + 'content-type' => 'application/json' + } + ) end let(:child_plate_v1) do # qc_files are created through the API V1. The actions attribute for qcfiles is required by the API V1. - json :plate, uuid: child_plate_uuid, purpose_uuid: child_plate_purpose_uuid, qc_files_actions: %w[read create] + json :plate, uuid: child_plate.uuid, purpose_uuid: child_plate_purpose_uuid, qc_files_actions: %w[read create] end before do - allow(Sequencescape::Api::V2::Tube).to receive(:find_by) - .with(barcode: 'AB10000001', includes: tube_includes) - .and_return(parent_tube_1) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by) - .with(barcode: 'AB10000002', includes: tube_includes) - .and_return(parent_tube_2) - - stub_v2_plate(child_plate_v2, stub_search: false, custom_query: [:plate_with_wells, child_plate_v2.uuid]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with( + barcode: 'AB10000001', + includes: tube_includes + ).and_return(parent_tube_1) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with( + barcode: 'AB10000002', + includes: tube_includes + ).and_return(parent_tube_2) - stub_api_get(child_plate_uuid, body: child_plate_v1) + stub_api_get(child_plate.uuid, body: child_plate_v1) stub_upload_file_creation @@ -194,20 +172,6 @@ { user_uuid: user_uuid, purpose_uuid: child_plate_purpose_uuid, parent_uuid: parent_tube_1_uuid, file: file } end - let!(:ms_plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: child_plate_purpose_uuid, - parents: [parent_tube_1_uuid, parent_tube_2_uuid] - } - }, - body: json(:plate_creation, child_plate_uuid: child_plate_uuid) - ) - end - let(:transfer_requests) do [ { source_asset: 'tube-1-uuid', target_asset: '5-well-A1', outer_request: 'request-1' }, @@ -228,6 +192,27 @@ ) end + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) + + response + end + + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [ + { + child_purpose_uuid: child_plate_purpose_uuid, + parent_uuids: [parent_tube_1_uuid, parent_tube_2_uuid], + user_uuid: user_uuid + } + ], + [pooled_plate_creation] + ) + end + subject { LabwareCreators::MultiStampTubesUsingTubeRackScan.new(api, form_attributes) } it 'creates a plate!' do @@ -235,10 +220,11 @@ subject.labware.barcode.machine = 'AB10000001' subject.labware.barcode.ean13 = nil + expect_pooled_plate_creation + subject.save - expect(subject.errors.full_messages).to be_empty - expect(ms_plate_creation_request).to have_been_made.once + expect(subject.errors.full_messages).to be_empty expect(transfer_creation_request).to have_been_made.once end end @@ -284,9 +270,10 @@ subject { LabwareCreators::MultiStampTubesUsingTubeRackScan.new(api, form_attributes) } before do - allow(Sequencescape::Api::V2::Tube).to receive(:find_by) - .with(barcode: 'AB10000003', includes: tube_includes) - .and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with( + barcode: 'AB10000003', + includes: tube_includes + ).and_return(nil) subject.validate end diff --git a/spec/models/labware_creators/normalised_binned_plate_spec.rb b/spec/models/labware_creators/normalised_binned_plate_spec.rb index d8936c495..82742d946 100644 --- a/spec/models/labware_creators/normalised_binned_plate_spec.rb +++ b/spec/models/labware_creators/normalised_binned_plate_spec.rb @@ -85,10 +85,12 @@ let(:user_uuid) { 'user-uuid' } before do - create :normalised_binning_purpose_config, - uuid: child_purpose_uuid, - name: child_purpose_name, - library_type_name: library_type_name + create( + :normalised_binning_purpose_config, + uuid: child_purpose_uuid, + name: child_purpose_name, + library_type_name: library_type_name + ) stub_v2_plate(child_plate, stub_search: false) stub_v2_plate( parent_plate, diff --git a/spec/models/labware_creators/pcr_cycles_binned_plate_for_duplex_seq_spec.rb b/spec/models/labware_creators/pcr_cycles_binned_plate_for_duplex_seq_spec.rb index 641b0964f..5bf07429d 100644 --- a/spec/models/labware_creators/pcr_cycles_binned_plate_for_duplex_seq_spec.rb +++ b/spec/models/labware_creators/pcr_cycles_binned_plate_for_duplex_seq_spec.rb @@ -277,21 +277,19 @@ end let(:stub_upload_file_creation) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="duplex_seq_customer_file.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'duplex_seq_dil_file.csv'), - headers: { - 'content-type' => 'application/json' - } - ) + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="duplex_seq_customer_file.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'duplex_seq_dil_file.csv'), + headers: { + 'content-type' => 'application/json' + } + ) end let(:stub_parent_request) { stub_api_get(parent_uuid, body: parent_plate_v1) } @@ -299,10 +297,12 @@ before do stub_parent_request - create :duplex_seq_customer_csv_file_upload_purpose_config, - uuid: child_purpose_uuid, - name: child_purpose_name, - library_type_name: library_type_name + create( + :duplex_seq_customer_csv_file_upload_purpose_config, + uuid: child_purpose_uuid, + name: child_purpose_name, + library_type_name: library_type_name + ) stub_v2_plate( parent_plate, diff --git a/spec/models/labware_creators/pcr_cycles_binned_plate_for_t_nano_seq_spec.rb b/spec/models/labware_creators/pcr_cycles_binned_plate_for_t_nano_seq_spec.rb index b84cd48ce..0f96b8fb6 100644 --- a/spec/models/labware_creators/pcr_cycles_binned_plate_for_t_nano_seq_spec.rb +++ b/spec/models/labware_creators/pcr_cycles_binned_plate_for_t_nano_seq_spec.rb @@ -313,21 +313,19 @@ end let(:stub_upload_file_creation) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="targeted_nano_seq_customer_file.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'targeted_nano_seq_dil_file.csv'), - headers: { - 'content-type' => 'application/json' - } - ) + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="targeted_nano_seq_customer_file.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'targeted_nano_seq_dil_file.csv'), + headers: { + 'content-type' => 'application/json' + } + ) end let(:stub_parent_request) { stub_api_get(parent_uuid, body: parent_plate_v1) } diff --git a/spec/models/labware_creators/plate_split_to_tube_racks_spec.rb b/spec/models/labware_creators/plate_split_to_tube_racks_spec.rb index 98622ea45..0e88bd6af 100644 --- a/spec/models/labware_creators/plate_split_to_tube_racks_spec.rb +++ b/spec/models/labware_creators/plate_split_to_tube_racks_spec.rb @@ -116,89 +116,68 @@ { user_uuid: user_uuid, purpose_uuid: child_sequencing_tube_purpose_uuid, parent_uuid: parent_uuid } end - # child tubes for lookup after creation - let(:child_tube_1_uuid) { SecureRandom.uuid } - let(:child_tube_1_aliquot) { create(:v2_aliquot, sample: sample1) } - let(:child_tube_1_v2) do - create( - :v2_stock_tube, - state: 'passed', - purpose_name: child_sequencing_tube_purpose_name, - aliquots: [child_tube_1_aliquot], - barcode_prefix: 'FX', - barcode_number: 1, - uuid: child_tube_1_uuid + let(:sequencing_file) do + fixture_file_upload( + 'spec/fixtures/files/scrna_core/scrna_core_sequencing_tube_rack_scan.csv', + 'sequencescape/qc_file' ) end - let(:child_tube_2_uuid) { SecureRandom.uuid } - let(:child_tube_2_aliquot) { create(:v2_aliquot, sample: sample2) } - let(:child_tube_2_v2) do - create( - :v2_stock_tube, - state: 'passed', - purpose_name: child_sequencing_tube_purpose_name, - aliquots: [child_tube_2_aliquot], - barcode_prefix: 'FX', - barcode_number: 2, - uuid: child_tube_2_uuid + let(:contingency_file) do + fixture_file_upload( + 'spec/fixtures/files/scrna_core/scrna_core_contingency_tube_rack_scan.csv', + 'sequencescape/qc_file' ) end - let(:child_tube_3_uuid) { SecureRandom.uuid } - let(:child_tube_3_aliquot) { create(:v2_aliquot, sample: sample1) } - let(:child_tube_3_v2) do - create( - :v2_stock_tube, - state: 'passed', - purpose_name: child_contingency_tube_purpose_name, - aliquots: [child_tube_3_aliquot], - barcode_prefix: 'FX', - barcode_number: 11, - uuid: child_tube_3_uuid - ) - end + def prepare_created_child_tubes(tube_attributes) + # Prepare child tubes and stub their lookups. + child_tubes = + tube_attributes.map { |attrs| create(:v2_tube, name: attrs[:name], foreign_barcode: attrs[:foreign_barcode]) } + child_tubes.each { |child_tube| stub_v2_labware(child_tube) } - let(:child_tube_4_uuid) { SecureRandom.uuid } - let(:child_tube_4_aliquot) { create(:v2_aliquot, sample: sample1) } - let(:child_tube_4_v2) do - create( - :v2_stock_tube, - state: 'passed', - purpose_name: child_contingency_tube_purpose_name, - aliquots: [child_tube_4_aliquot], - barcode_prefix: 'FX', - barcode_number: 12, - uuid: child_tube_4_uuid - ) + child_tubes end - let(:child_tube_5_uuid) { SecureRandom.uuid } - let(:child_tube_5_aliquot) { create(:v2_aliquot, sample: sample2) } - let(:child_tube_5_v2) do - create( - :v2_stock_tube, - state: 'passed', - purpose_name: child_contingency_tube_purpose_name, - aliquots: [child_tube_5_aliquot], - barcode_prefix: 'FX', - barcode_number: 13, - uuid: child_tube_5_uuid - ) - end + def expect_specific_tube_creation(child_purpose_uuid, child_tubes) + # Create a mock for the specific tube creation. + specific_tube_creation = double + allow(specific_tube_creation).to receive(:children).and_return(child_tubes) - let(:sequencing_file) do - fixture_file_upload( - 'spec/fixtures/files/scrna_core/scrna_core_sequencing_tube_rack_scan.csv', - 'sequencescape/qc_file' + # Expect the post request and return the mock. + expect_api_v2_posts( + 'SpecificTubeCreation', + [ + { + child_purpose_uuids: [child_purpose_uuid] * child_tubes.size, + parent_uuids: [parent_uuid], + tube_attributes: child_tubes.map { |tube| { name: tube.name, foreign_barcode: tube.foreign_barcode } }, + user_uuid: user_uuid + } + ], + [specific_tube_creation] ) end - let(:contingency_file) do - fixture_file_upload( - 'spec/fixtures/files/scrna_core/scrna_core_contingency_tube_rack_scan.csv', - 'sequencescape/qc_file' - ) + # tubes_hash should be a hash with tube rack barcodes as keys and arrays of tubes as values. + def expect_custom_metadatum_collection_posts(tubes_hash) + # Prepare the expected call arguments. + expected_call_args = + tubes_hash.flat_map do |tube_rack_barcode, tubes| + tubes.map do |tube| + { + user_id: user.id, + asset_id: tube.id, + metadata: { + tube_rack_barcode: tube_rack_barcode, + tube_rack_position: tube.name.split(':').last + } + } + end + end + + # Expect the post requests. + expect_api_v2_posts('CustomMetadatumCollection', expected_call_args) end before do @@ -221,12 +200,14 @@ stub_v2_tube(ancestor_tube_1_v2, stub_search: false) stub_v2_tube(ancestor_tube_2_v2, stub_search: false) - # child tube lookups - stub_v2_tube(child_tube_1_v2, stub_search: false) - stub_v2_tube(child_tube_2_v2, stub_search: false) - stub_v2_tube(child_tube_3_v2, stub_search: false) - stub_v2_tube(child_tube_4_v2, stub_search: false) - stub_v2_tube(child_tube_5_v2, stub_search: false) + # Block finding tubes by given barcodes. + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000001').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000002').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000011').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000012').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000013').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000014').and_return(nil) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000015').and_return(nil) end context 'on new' do @@ -373,13 +354,6 @@ 'wells.aliquots,wells.aliquots.sample,wells.downstream_tubes,' \ 'wells.downstream_tubes.custom_metadatum_collection' ) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000001').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000002').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000011').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000012').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000013').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000014').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000015').and_return(nil) end context 'when files are not present' do @@ -498,13 +472,6 @@ 'wells.aliquots,wells.aliquots.sample,wells.downstream_tubes,' \ 'wells.downstream_tubes.custom_metadatum_collection' ) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000001').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000002').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000011').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000012').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000013').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000014').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000015').and_return(nil) end context 'when files are not present' do @@ -611,9 +578,9 @@ context 'when the tube barcode already exists in the LIMS' do before do - allow(Sequencescape::Api::V2::Tube).to receive(:find_by) - .with(barcode: foreign_barcode) - .and_return(existing_tube) + allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: foreign_barcode).and_return( + existing_tube + ) end it 'adds an error to the errors collection' do @@ -635,7 +602,42 @@ end context '#save' do - let!(:stub_sequencing_tube_creation_request_uuid) { SecureRandom.uuid } + # body for stubbing the contingency file upload + let(:contingency_file_content) do + content = contingency_file.read + contingency_file.rewind + content + end + + # stub the contingency file upload + let!(:stub_contingency_file_upload) do + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: contingency_file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="scrna_core_contingency_tube_rack_scan.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'scrna_core_contingency_tube_rack_scan.csv'), + headers: { + 'content-type' => 'application/json' + } + ) + end + + let(:contingency_tubes) do + prepare_created_child_tubes( + [ + # sample 1 from well A2 to contingency tube 1 in A1 + { name: 'SPR:NT1O:A1', foreign_barcode: 'FX00000011' }, + # sample 2 from well B2 to contingency tube 2 in B1 + { name: 'SPR:NT2P:B1', foreign_barcode: 'FX00000012' }, + # sample 1 from well A3 to contingency tube 3 in C1 + { name: 'SPR:NT1O:C1', foreign_barcode: 'FX00000013' } + ] + ) + end before do stub_v2_plate( @@ -646,13 +648,6 @@ 'wells.downstream_tubes.custom_metadatum_collection' ) stub_api_get(parent_uuid, body: parent_v1) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000001').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000002').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000011').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000012').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000013').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000014').and_return(nil) - allow(Sequencescape::Api::V2::Tube).to receive(:find_by).with(barcode: 'FX00000015').and_return(nil) end context 'with both sequencing and contingency files' do @@ -666,51 +661,6 @@ } end - # stub the contingency tube creation - let!(:stub_contingency_tube_creation_request_uuid) { SecureRandom.uuid } - let!(:stub_contingency_tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - child_purposes: [ - child_contingency_tube_purpose_uuid, - child_contingency_tube_purpose_uuid, - child_contingency_tube_purpose_uuid - ], - tube_attributes: [ - # sample 1 from well A2 to contingency tube 1 in A1 - { name: 'SPR:NT1O:A1', foreign_barcode: 'FX00000011' }, - # sample 2 from well B2 to contingency tube 2 in B1 - { name: 'SPR:NT2P:B1', foreign_barcode: 'FX00000012' }, - # sample 1 from well A3 to contingency tube 3 in C1 - { name: 'SPR:NT1O:C1', foreign_barcode: 'FX00000013' } - ], - user: user_uuid, - parent: parent_uuid - } - }, - body: json(:specific_tube_creation, uuid: stub_contingency_tube_creation_request_uuid, children_count: 3) - ) - end - - # stub what contingency tubes were just made - let!(:stub_contingency_tube_creation_children_request) do - stub_api_get( - stub_contingency_tube_creation_request_uuid, - 'children', - body: - json( - :tube_collection_with_barcodes_specified, - size: 3, - names: %w[SPR:NT1O:A1 SPR:NT2P:B1 SPR:NT1O:C1], - barcode_prefix: 'FX', - barcode_numbers: [11, 12, 13], - uuid_index_offset: 2 - ) - ) - end - # body for stubbing the contingency file upload let(:contingency_file_content) do content = contingency_file.read @@ -720,21 +670,19 @@ # stub the contingency file upload let!(:stub_contingency_file_upload) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: contingency_file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="scrna_core_contingency_tube_rack_scan.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'scrna_core_contingency_tube_rack_scan.csv'), - headers: { - 'content-type' => 'application/json' - } - ) + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: contingency_file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="scrna_core_contingency_tube_rack_scan.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'scrna_core_contingency_tube_rack_scan.csv'), + headers: { + 'content-type' => 'application/json' + } + ) end # body for stubbing the sequencing file upload @@ -744,106 +692,54 @@ content end - # stub the sequencing file upload - let!(:stub_sequencing_file_upload) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: sequencing_file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="scrna_core_sequencing_tube_rack_scan.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'scrna_core_sequencing_tube_rack_scan.csv'), - headers: { - 'content-type' => 'application/json' - } - ) - end - - # stub the sequencing tube creation - let!(:stub_sequencing_tube_creation_request_uuid) { SecureRandom.uuid } - let!(:stub_sequencing_tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - child_purposes: [child_sequencing_tube_purpose_uuid, child_sequencing_tube_purpose_uuid], - tube_attributes: [ - # sample 1 in well A1 to seq tube 1 in A1 - { name: 'SEQ:NT1O:A1', foreign_barcode: 'FX00000001' }, - # sample 2 in well B1 to seq tube 2 in B1 - { name: 'SEQ:NT2P:B1', foreign_barcode: 'FX00000002' } - ], - user: user_uuid, - parent: parent_uuid - } - }, - body: json(:specific_tube_creation, uuid: stub_sequencing_tube_creation_request_uuid, children_count: 2) + let(:sequencing_tubes) do + prepare_created_child_tubes( + [ + # sample 1 in well A1 to seq tube 1 in A1 + { name: 'SEQ:NT1O:A1', foreign_barcode: 'FX00000001' }, + # sample 2 in well B1 to seq tube 2 in B1 + { name: 'SEQ:NT2P:B1', foreign_barcode: 'FX00000002' } + ] ) end - # stub what sequencing tubes were just made - let!(:stub_sequencing_tube_creation_children_request) do - stub_api_get( - stub_sequencing_tube_creation_request_uuid, - 'children', - body: - json( - :tube_collection_with_barcodes_specified, - size: 2, - names: %w[SEQ:NT1O:A1 SEQ:NT2P:B1], - barcode_prefix: 'FX', - barcode_numbers: [1, 2] - ) + # stub the sequencing file upload + let!(:stub_sequencing_file_upload) do + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: sequencing_file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="scrna_core_sequencing_tube_rack_scan.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'scrna_core_sequencing_tube_rack_scan.csv'), + headers: { + 'content-type' => 'application/json' + } ) end # stub the transfer creation let!(:stub_transfer_creation_request) do + parent_wells = [parent_well_a1, parent_well_b1, parent_well_a2, parent_well_b2, parent_well_a3] + target_tubes = sequencing_tubes + contingency_tubes + transfer_requests = + parent_wells.map.with_index do |parent_well, index| + { 'submission_id' => '2', 'source_asset' => parent_well.uuid, 'target_asset' => target_tubes[index].uuid } + end stub_api_post( 'transfer_request_collections', payload: { transfer_request_collection: { user: user_uuid, - transfer_requests: [ - { 'submission_id' => '2', 'source_asset' => parent_well_a1.uuid, 'target_asset' => 'tube-0' }, - { 'submission_id' => '2', 'source_asset' => parent_well_b1.uuid, 'target_asset' => 'tube-1' }, - { 'submission_id' => '2', 'source_asset' => parent_well_a2.uuid, 'target_asset' => 'tube-2' }, - { 'submission_id' => '2', 'source_asset' => parent_well_b2.uuid, 'target_asset' => 'tube-3' }, - { 'submission_id' => '2', 'source_asset' => parent_well_a3.uuid, 'target_asset' => 'tube-4' } - ] + transfer_requests: transfer_requests } }, body: '{}' ) end - # need api v1 versions of child tubes - let(:child_tube_1_v1) { json :tube, uuid: child_tube_1_uuid, barcode_prefix: 'FX', barcode_number: 1 } - let(:child_tube_2_v1) { json :tube, uuid: child_tube_2_uuid, barcode_prefix: 'FX', barcode_number: 2 } - let(:child_tube_3_v1) { json :tube, uuid: child_tube_3_uuid, barcode_prefix: 'FX', barcode_number: 11 } - let(:child_tube_4_v1) { json :tube, uuid: child_tube_4_uuid, barcode_prefix: 'FX', barcode_number: 12 } - let(:child_tube_5_v1) { json :tube, uuid: child_tube_5_uuid, barcode_prefix: 'FX', barcode_number: 13 } - - # Metadata expected to be sent in POST requests - let!(:metadata_for_tube_1) { { tube_rack_barcode: 'TR00000001', tube_rack_position: 'A1' } } - let(:tube_1_create_args) { { user_id: user.id, asset_id: child_tube_1_v2.id, metadata: metadata_for_tube_1 } } - - let!(:metadata_for_tube_2) { { tube_rack_barcode: 'TR00000001', tube_rack_position: 'B1' } } - let(:tube_2_create_args) { { user_id: user.id, asset_id: child_tube_2_v2.id, metadata: metadata_for_tube_2 } } - - let!(:metadata_for_tube_3) { { tube_rack_barcode: 'TR00000002', tube_rack_position: 'A1' } } - let(:tube_3_create_args) { { user_id: user.id, asset_id: child_tube_3_v2.id, metadata: metadata_for_tube_3 } } - - let!(:metadata_for_tube_4) { { tube_rack_barcode: 'TR00000002', tube_rack_position: 'B1' } } - let(:tube_4_create_args) { { user_id: user.id, asset_id: child_tube_4_v2.id, metadata: metadata_for_tube_4 } } - - let!(:metadata_for_tube_5) { { tube_rack_barcode: 'TR00000002', tube_rack_position: 'C1' } } - let(:tube_5_create_args) { { user_id: user.id, asset_id: child_tube_5_v2.id, metadata: metadata_for_tube_5 } } - let(:contingency_file) do fixture_file_upload( 'spec/fixtures/files/scrna_core/scrna_core_contingency_tube_rack_scan_3_tubes.csv', @@ -851,28 +747,20 @@ ) end - before do - stub_v2_user(user) - - stub_v2_labware(child_tube_1_v2) - stub_v2_labware(child_tube_2_v2) - stub_v2_labware(child_tube_3_v2) - stub_v2_labware(child_tube_4_v2) - stub_v2_labware(child_tube_5_v2) - end + before { stub_v2_user(user) } it 'creates the child tubes' do - expect_api_v2_posts( - 'CustomMetadatumCollection', - [tube_1_create_args, tube_2_create_args, tube_3_create_args, tube_4_create_args, tube_5_create_args] + expect_specific_tube_creation(child_sequencing_tube_purpose_uuid, sequencing_tubes) + expect_specific_tube_creation(child_contingency_tube_purpose_uuid, contingency_tubes) + + expect_custom_metadatum_collection_posts( + { 'TR00000001' => sequencing_tubes, 'TR00000002' => contingency_tubes } ) expect(subject.valid?).to be_truthy expect(subject.save).to be_truthy expect(stub_sequencing_file_upload).to have_been_made.once - expect(stub_sequencing_tube_creation_request).to have_been_made.once expect(stub_contingency_file_upload).to have_been_made.once - expect(stub_contingency_tube_creation_request).to have_been_made.once expect(stub_transfer_creation_request).to have_been_made.once end @@ -882,94 +770,20 @@ create(:v2_well, location: 'A1', aliquots: [parent_aliquot_sample1_aliquot1], state: 'failed') end - # as A1 is failed order of samples is changed - let!(:stub_sequencing_tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - child_purposes: [child_sequencing_tube_purpose_uuid, child_sequencing_tube_purpose_uuid], - tube_attributes: [ - # sample 2 in well B1 to seq tube 1 in A1 - { name: 'SEQ:NT2P:A1', foreign_barcode: 'FX00000001' }, - # sample 1 in well A2 to seq tube 2 in B1 - { name: 'SEQ:NT1O:B1', foreign_barcode: 'FX00000002' } - ], - user: user_uuid, - parent: parent_uuid - } - }, - body: json(:specific_tube_creation, uuid: stub_sequencing_tube_creation_request_uuid, children_count: 2) - ) - end - - # stub what sequencing tubes were just made (order changed) - let!(:stub_sequencing_tube_creation_children_request) do - stub_api_get( - stub_sequencing_tube_creation_request_uuid, - 'children', - body: - json( - :tube_collection_with_barcodes_specified, - size: 2, - names: %w[SEQ:NT2P:A1 SEQ:NT1O:B1], - barcode_prefix: 'FX', - barcode_numbers: [1, 2] - ) - ) - end - - # only 2 contingency tubes will be needed - let!(:stub_contingency_tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - child_purposes: [child_contingency_tube_purpose_uuid, child_contingency_tube_purpose_uuid], - tube_attributes: [ - # sample 2 from well B2 to contingency tube 1 in A1 - { name: 'SPR:NT2P:A1', foreign_barcode: 'FX00000011' }, - # sample 1 from well A3 to contingency tube 2 in B1 - { name: 'SPR:NT1O:B1', foreign_barcode: 'FX00000012' } - ], - user: user_uuid, - parent: parent_uuid - } - }, - body: json(:specific_tube_creation, uuid: stub_contingency_tube_creation_request_uuid, children_count: 3) - ) - end - - # stub what contingency tubes were just made (just 2) - let!(:stub_contingency_tube_creation_children_request) do - stub_api_get( - stub_contingency_tube_creation_request_uuid, - 'children', - body: - json( - :tube_collection_with_barcodes_specified, - size: 2, - names: %w[SPR:NT2P:A1 SPR:NT1O:B1], - barcode_prefix: 'FX', - barcode_numbers: [11, 12], - uuid_index_offset: 2 - ) - ) - end - # one fewer transfer request let!(:stub_transfer_creation_request) do + parent_wells = [parent_well_b1, parent_well_a2, parent_well_b2, parent_well_a3] + target_tubes = sequencing_tubes + contingency_tubes + transfer_requests = + parent_wells.map.with_index do |parent_well, index| + { 'submission_id' => '2', 'source_asset' => parent_well.uuid, 'target_asset' => target_tubes[index].uuid } + end stub_api_post( 'transfer_request_collections', payload: { transfer_request_collection: { user: user_uuid, - transfer_requests: [ - { 'submission_id' => '2', 'source_asset' => parent_well_b1.uuid, 'target_asset' => 'tube-0' }, - { 'submission_id' => '2', 'source_asset' => parent_well_a2.uuid, 'target_asset' => 'tube-1' }, - { 'submission_id' => '2', 'source_asset' => parent_well_b2.uuid, 'target_asset' => 'tube-2' }, - { 'submission_id' => '2', 'source_asset' => parent_well_a3.uuid, 'target_asset' => 'tube-3' } - ] + transfer_requests: transfer_requests } }, body: '{}' @@ -983,30 +797,40 @@ ) end - before do - stub_get_labware_metadata(child_tube_1_v2.barcode.machine, child_tube_1_v1) - stub_get_labware_metadata(child_tube_2_v2.barcode.machine, child_tube_2_v1) - stub_get_labware_metadata(child_tube_3_v2.barcode.machine, child_tube_3_v1) - stub_get_labware_metadata(child_tube_4_v2.barcode.machine, child_tube_4_v1) + let(:sequencing_tubes) do + prepare_created_child_tubes( + [ + # sample 2 in well B1 to seq tube 1 in A1 + { name: 'SEQ:NT2P:A1', foreign_barcode: 'FX00000001' }, + # sample 1 in well A2 to seq tube 2 in B1 + { name: 'SEQ:NT1O:B1', foreign_barcode: 'FX00000002' } + ] + ) + end - stub_asset_search(child_tube_1_v2.barcode.machine, child_tube_1_v1) - stub_asset_search(child_tube_2_v2.barcode.machine, child_tube_2_v1) - stub_asset_search(child_tube_3_v2.barcode.machine, child_tube_3_v1) - stub_asset_search(child_tube_4_v2.barcode.machine, child_tube_4_v1) + let(:contingency_tubes) do + prepare_created_child_tubes( + [ + # sample 2 from well B2 to contingency tube 1 in A1 + { name: 'SPR:NT2P:A1', foreign_barcode: 'FX00000011' }, + # sample 1 from well A3 to contingency tube 2 in B1 + { name: 'SPR:NT1O:B1', foreign_barcode: 'FX00000012' } + ] + ) end it 'does not create a tube for the failed well' do - expect_api_v2_posts( - 'CustomMetadatumCollection', - [tube_1_create_args, tube_2_create_args, tube_3_create_args, tube_4_create_args] # no tube 5 + expect_specific_tube_creation(child_sequencing_tube_purpose_uuid, sequencing_tubes) + expect_specific_tube_creation(child_contingency_tube_purpose_uuid, contingency_tubes) + + expect_custom_metadatum_collection_posts( + { 'TR00000001' => sequencing_tubes, 'TR00000002' => contingency_tubes } ) expect(subject.valid?).to be_truthy expect(subject.save).to be_truthy expect(stub_sequencing_file_upload).to have_been_made.once - expect(stub_sequencing_tube_creation_request).to have_been_made.once expect(stub_contingency_file_upload).to have_been_made.once - expect(stub_contingency_tube_creation_request).to have_been_made.once expect(stub_transfer_creation_request).to have_been_made.once end end @@ -1031,103 +855,65 @@ # stub the sequencing file upload let!(:stub_sequencing_file_upload) do - stub_request(:post, api_url_for(parent_uuid, 'qc_files')) - .with( - body: sequencing_file_content, - headers: { - 'Content-Type' => 'sequencescape/qc_file', - 'Content-Disposition' => 'form-data; filename="scrna_core_sequencing_tube_rack_scan.csv"' - } - ) - .to_return( - status: 201, - body: json(:qc_file, filename: 'scrna_core_sequencing_tube_rack_scan.csv'), - headers: { - 'content-type' => 'application/json' - } - ) - end - - # stub the sequencing tube creation - let!(:stub_sequencing_tube_creation_request_uuid) { SecureRandom.uuid } - let!(:stub_sequencing_tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - child_purposes: [child_sequencing_tube_purpose_uuid, child_sequencing_tube_purpose_uuid], - tube_attributes: [ - # sample 1 in well A1 to seq tube 1 in A1 - { name: 'SEQ:NT1O:A1', foreign_barcode: 'FX00000001' }, - # sample 2 in well B1 to seq tube 2 in B1 - { name: 'SEQ:NT2P:B1', foreign_barcode: 'FX00000002' } - ], - user: user_uuid, - parent: parent_uuid - } - }, - body: json(:specific_tube_creation, uuid: stub_sequencing_tube_creation_request_uuid, children_count: 2) + stub_request(:post, api_url_for(parent_uuid, 'qc_files')).with( + body: sequencing_file_content, + headers: { + 'Content-Type' => 'sequencescape/qc_file', + 'Content-Disposition' => 'form-data; filename="scrna_core_sequencing_tube_rack_scan.csv"' + } + ).to_return( + status: 201, + body: json(:qc_file, filename: 'scrna_core_sequencing_tube_rack_scan.csv'), + headers: { + 'content-type' => 'application/json' + } ) end - # stub what sequencing tubes were just made - let!(:stub_sequencing_tube_creation_children_request) do - stub_api_get( - stub_sequencing_tube_creation_request_uuid, - 'children', - body: - json( - :tube_collection_with_barcodes_specified, - size: 2, - names: %w[SEQ:NT1O:A1 SEQ:NT2P:B1], - barcode_prefix: 'FX', - barcode_numbers: [1, 2] - ) + let(:sequencing_tubes) do + prepare_created_child_tubes( + [ + # sample 1 from well A1 to sequencing tube 1 in A1 + { name: 'SEQ:NT1O:A1', foreign_barcode: 'FX00000001' }, + # sample 2 from well B1 to sequencing tube 2 in B1 + { name: 'SEQ:NT2P:B1', foreign_barcode: 'FX00000002' } + ] ) end # stub the transfer creation let!(:stub_transfer_creation_request) do + parent_wells = [parent_well_a1, parent_well_b1] + transfer_requests = + parent_wells.map.with_index do |parent_well, index| + { + 'submission_id' => '2', + 'source_asset' => parent_well.uuid, + 'target_asset' => sequencing_tubes[index].uuid + } + end stub_api_post( 'transfer_request_collections', payload: { transfer_request_collection: { user: user_uuid, - transfer_requests: [ - { 'submission_id' => '2', 'source_asset' => parent_well_a1.uuid, 'target_asset' => 'tube-0' }, - { 'submission_id' => '2', 'source_asset' => parent_well_b1.uuid, 'target_asset' => 'tube-1' } - ] + transfer_requests: transfer_requests } }, body: '{}' ) end - # need api v1 versions of child tubes - let(:child_tube_1_v1) { json :tube, uuid: child_tube_1_uuid, barcode_prefix: 'FX', barcode_number: 1 } - let(:child_tube_2_v1) { json :tube, uuid: child_tube_2_uuid, barcode_prefix: 'FX', barcode_number: 2 } - - # need to stub the creation of the tube metadata - let!(:metadata_for_tube_1) { { tube_rack_barcode: 'TR00000001', tube_rack_position: 'A1' } } - let(:tube_1_create_args) { { user_id: user.id, asset_id: child_tube_1_v2.id, metadata: metadata_for_tube_1 } } - - let!(:metadata_for_tube_2) { { tube_rack_barcode: 'TR00000001', tube_rack_position: 'B1' } } - let(:tube_2_create_args) { { user_id: user.id, asset_id: child_tube_2_v2.id, metadata: metadata_for_tube_2 } } - - before do - stub_v2_user(user) - - stub_v2_labware(child_tube_1_v2) - stub_v2_labware(child_tube_2_v2) - end + before { stub_v2_user(user) } it 'creates the child tubes' do - expect_api_v2_posts('CustomMetadatumCollection', [tube_1_create_args, tube_2_create_args]) + # Contingency tubes creation + expect_specific_tube_creation(child_sequencing_tube_purpose_uuid, sequencing_tubes) + expect_custom_metadatum_collection_posts({ 'TR00000001' => sequencing_tubes }) expect(subject.valid?).to be_truthy expect(subject.save).to be_truthy expect(stub_sequencing_file_upload).to have_been_made.once - expect(stub_sequencing_tube_creation_request).to have_been_made.once expect(stub_transfer_creation_request).to have_been_made.once end end diff --git a/spec/models/labware_creators/plate_with_primer_panel_spec.rb b/spec/models/labware_creators/plate_with_primer_panel_spec.rb index 4f9c6d4c7..4d5b9bff9 100644 --- a/spec/models/labware_creators/plate_with_primer_panel_spec.rb +++ b/spec/models/labware_creators/plate_with_primer_panel_spec.rb @@ -31,7 +31,7 @@ end let(:child) { create :v2_plate_with_primer_panels, barcode_number: '3', size: plate_size, uuid: 'child-uuid' } - let(:form_attributes) { { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid: } } before { create :purpose_config, pcr_stage: 'pcr 1', uuid: purpose_uuid } diff --git a/spec/models/labware_creators/pooled_tubes_by_submission_spec.rb b/spec/models/labware_creators/pooled_tubes_by_submission_spec.rb index f358503a5..48cf5ae39 100644 --- a/spec/models/labware_creators/pooled_tubes_by_submission_spec.rb +++ b/spec/models/labware_creators/pooled_tubes_by_submission_spec.rb @@ -11,6 +11,8 @@ RSpec.describe LabwareCreators::PooledTubesBySubmission do include FeatureHelpers + has_a_working_api + it_behaves_like 'it only allows creation from charged and passed plates with defined downstream pools' subject { LabwareCreators::PooledTubesBySubmission.new(api, form_attributes) } @@ -24,17 +26,32 @@ let(:parent) { json :plate, uuid: parent_uuid, pool_sizes: [3, 6], stock_plate_barcode: 5, for_multiplexing: true } let(:source_plate) { create :v2_plate, uuid: parent_uuid } - let(:form_attributes) { { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid: } } let(:wells_json) { json :well_collection, size: 9, default_state: 'passed' } before { stub_v2_plate(source_plate, stub_search: false) } context '#save!' do - has_a_working_api - - let(:child_1_name) { 'DN5 A1:C1' } - let(:child_2_name) { 'DN5 D1:A2' } + def expect_specific_tube_creation(child_tubes) + # Create a mock for the specific tube creation. + specific_tube_creation = double + allow(specific_tube_creation).to receive(:children).and_return(child_tubes) + + # Expect the post request and return the mock. + expect_api_v2_posts( + 'SpecificTubeCreation', + [ + { + child_purpose_uuids: [purpose_uuid] * child_tubes.size, + parent_uuids: [parent_uuid], + tube_attributes: child_tubes.map { |tube| { name: tube.name } }, + user_uuid: user_uuid + } + ], + [specific_tube_creation] + ) + end # Used to fetch the pools. This is the kind of thing we could pass through from a custom form let!(:parent_request) do @@ -42,40 +59,20 @@ stub_api_get(parent_uuid, 'wells', body: wells_json) end - let(:creation_payload) do - { - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid, purpose_uuid], - tube_attributes: [{ name: child_1_name }, { name: child_2_name }] - } - end + let(:child_1_name) { 'DN5 A1:C1' } + let(:child_2_name) { 'DN5 D1:A2' } - let(:tube_creation_request_uuid) { SecureRandom.uuid } + let(:tube_attributes) { [{ name: child_1_name }, { name: child_2_name }] } - let!(:tube_creation_request) do - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: creation_payload - }, - body: - json( - :specific_tube_creation, - uuid: tube_creation_request_uuid, - children_count: 2, - names: [child_1_name, child_2_name] - ) - ) - end + let(:child_tubes) do + # Prepare child tubes and stub their lookups. + child_tubes = + tube_attributes.each_with_index.map do |attrs, index| + create(:v2_tube, name: attrs[:name], uuid: "tube-#{index}") + end + child_tubes.each { |child_tube| stub_v2_labware(child_tube) } - # Find out what tubes we've just made! - let!(:tube_creation_children_request) do - stub_api_get( - tube_creation_request_uuid, - 'children', - body: json(:tube_collection, names: [child_1_name, child_2_name]) - ) + child_tubes end let(:transfer_requests) do @@ -106,9 +103,10 @@ end context 'without parent metadata' do + before { expect_specific_tube_creation(child_tubes) } + it 'pools by submission' do expect(subject.save!).to be_truthy - expect(tube_creation_request).to have_been_made.once expect(transfer_creation_request).to have_been_made.once end @@ -133,24 +131,11 @@ for_multiplexing: true end - setup do - stub_get_labware_metadata('DN10', parent, metadata: { stock_barcode: 'DN6' }) - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: creation_payload - }, - body: - json( - :specific_tube_creation, - uuid: tube_creation_request_uuid, - children_count: 2, - names: [child_1_name, child_2_name] - ) - ) - end + setup { stub_get_labware_metadata('DN10', parent, metadata: { stock_barcode: 'DN6' }) } it 'sets the correct tube name' do + expect_specific_tube_creation(child_tubes) + expect(subject.save!).to be_truthy expect(subject.child_stock_tubes.length).to eq(2) expect(subject.child_stock_tubes).to have_key(child_1_name) @@ -172,6 +157,9 @@ { 'source_asset' => 'example-well-uuid-7', 'target_asset' => 'tube-1', 'submission' => 'pool-2-uuid' } ] end + + before { expect_specific_tube_creation(child_tubes) } + it 'pools by submission' do expect(subject.save!).to be_truthy expect(transfer_creation_request).to have_been_made.once @@ -191,14 +179,9 @@ ] end - let(:creation_payload) do - { - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid], - tube_attributes: [{ name: child_1_name }] - } - end + let(:tube_attributes) { [{ name: child_1_name }] } + + before { expect_specific_tube_creation(child_tubes) } it 'pools by submission' do expect(subject.save!).to be_truthy diff --git a/spec/models/labware_creators/pooled_tubes_from_whole_plates_spec.rb b/spec/models/labware_creators/pooled_tubes_from_whole_plates_spec.rb index e5ce80273..1ee701ebc 100644 --- a/spec/models/labware_creators/pooled_tubes_from_whole_plates_spec.rb +++ b/spec/models/labware_creators/pooled_tubes_from_whole_plates_spec.rb @@ -43,64 +43,51 @@ it_behaves_like 'it has a custom page', 'pooled_tubes_from_whole_plates' has_a_working_api - let(:form_attributes) { { purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { purpose_uuid:, parent_uuid: } } end describe '#save!' do has_a_working_api - let(:form_attributes) do - { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid, barcodes: barcodes } - end - - let(:tube_creation_request_uuid) { SecureRandom.uuid } + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid:, barcodes: } } - let(:tube_creation_request) do - # TODO: In reality we want to link in all four parents. - stub_api_post( - 'specific_tube_creations', - payload: { - specific_tube_creation: { - user: user_uuid, - parent: parent_uuid, - child_purposes: [purpose_uuid], - tube_attributes: [{ name: 'DN2+' }] - } - }, - body: json(:specific_tube_creation, uuid: tube_creation_request_uuid, children_count: 1) - ) - end + let(:child_tube) { create :v2_tube } + let(:specific_tube_creation) do + response = double + allow(response).to receive(:children).and_return([child_tube]) - # Find out what tubes we've just made! - let(:tube_creation_children_request) do - stub_api_get(tube_creation_request_uuid, 'children', body: json(:tube_collection, names: ['DN2+'])) + response end - # Used to fetch the pools. This is the kind of thing we could pass through from a custom form - let(:stub_barcode_searches) { stub_asset_search(barcodes, [parent, parent2, parent3, parent4]) } - - before do - stub_barcode_searches - tube_creation_children_request - tube_creation_request - end + before { stub_asset_search(barcodes, [parent, parent2, parent3, parent4]) } context 'with compatible plates' do it 'pools from all the plates' do + expect_api_v2_posts( + 'SpecificTubeCreation', + [ + { + child_purpose_uuids: [purpose_uuid], + parent_uuids: [parent_uuid], + tube_attributes: [{ name: 'DN2+' }], + user_uuid: user_uuid + } + ], + [specific_tube_creation] + ) expect_api_v2_posts( 'Transfer', [parent_uuid, parent2_uuid, parent3_uuid, parent4_uuid].map do |source_uuid| { user_uuid: user_uuid, source_uuid: source_uuid, - destination_uuid: 'tube-0', + destination_uuid: child_tube.uuid, transfer_template_uuid: 'whole-plate-to-tube' } end ) expect(subject.save!).to be_truthy - expect(tube_creation_request).to have_been_made.once end end end diff --git a/spec/models/labware_creators/pooled_tubes_from_whole_tubes_spec.rb b/spec/models/labware_creators/pooled_tubes_from_whole_tubes_spec.rb index 2530a67af..297c1be30 100644 --- a/spec/models/labware_creators/pooled_tubes_from_whole_tubes_spec.rb +++ b/spec/models/labware_creators/pooled_tubes_from_whole_tubes_spec.rb @@ -46,15 +46,13 @@ it_behaves_like 'it has a custom page', 'pooled_tubes_from_whole_tubes' has_a_working_api - let(:form_attributes) { { purpose_uuid: purpose_uuid, parent_uuid: parent_uuid } } + let(:form_attributes) { { purpose_uuid:, parent_uuid: } } end describe '#save!' do has_a_working_api - let(:form_attributes) do - { user_uuid: user_uuid, purpose_uuid: purpose_uuid, parent_uuid: parent_uuid, barcodes: barcodes } - end + let(:form_attributes) { { user_uuid:, purpose_uuid:, parent_uuid:, barcodes: } } let(:tube_creation_request_uuid) { SecureRandom.uuid } @@ -69,7 +67,7 @@ child_purpose: purpose_uuid } }, - body: json(:tube_creation, child_uuid: child_uuid) + body: json(:tube_creation, child_uuid:) ) end @@ -99,9 +97,9 @@ end before do - allow(Sequencescape::Api::V2::Tube).to receive(:find_all) - .with(barcode: barcodes, includes: []) - .and_return([parent, parent2]) + allow(Sequencescape::Api::V2::Tube).to receive(:find_all).with(barcode: barcodes, includes: []).and_return( + [parent, parent2] + ) tube_creation_request tube_creation_children_request diff --git a/spec/models/labware_creators/quadrant_split_plate_spec.rb b/spec/models/labware_creators/quadrant_split_plate_spec.rb index 353e79369..1719daa54 100644 --- a/spec/models/labware_creators/quadrant_split_plate_spec.rb +++ b/spec/models/labware_creators/quadrant_split_plate_spec.rb @@ -130,9 +130,10 @@ before do create(:purpose_config, name: child_purpose_name, uuid: child_purpose_uuid) - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ uuid: %w[child-a-uuid child-b-uuid child-c-uuid child-d-uuid] }, includes: ['wells']) - .and_return([child_plate_a, child_plate_b, child_plate_c, child_plate_d]) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with( + { uuid: %w[child-a-uuid child-b-uuid child-c-uuid child-d-uuid] }, + includes: ['wells'] + ).and_return([child_plate_a, child_plate_b, child_plate_c, child_plate_d]) stub_v2_plate(plate, stub_search: false) end diff --git a/spec/models/labware_creators/quadrant_stamp_primer_panel_spec.rb b/spec/models/labware_creators/quadrant_stamp_primer_panel_spec.rb index 3e56ef4dc..488f372c8 100644 --- a/spec/models/labware_creators/quadrant_stamp_primer_panel_spec.rb +++ b/spec/models/labware_creators/quadrant_stamp_primer_panel_spec.rb @@ -13,7 +13,6 @@ let(:parent1_uuid) { 'example-plate-uuid' } let(:parent2_uuid) { 'example-plate2-uuid' } - let(:child_uuid) { 'child-uuid' } let(:requests) { Array.new(96) { |i| create :gbs_library_request, state: 'started', uuid: "request-#{i}" } } let(:requests2) { Array.new(96) { |i| create :gbs_library_request, state: 'started', uuid: "request-#{i}" } } let(:stock_plate1) { create :v2_stock_plate_for_plate, barcode_number: '1' } @@ -40,20 +39,18 @@ stock_plate: stock_plate2 ) end - let(:child_plate_v2) { create :v2_plate, uuid: child_uuid, barcode_number: '5', size: 384 } - let(:child_plate_v1) { json :stock_plate_with_metadata, stock_plate: { barcode: '5', uuid: child_uuid } } + let(:child_plate) { create :v2_plate, barcode_number: '5', size: 384 } let(:child_purpose_uuid) { 'child-purpose' } let(:child_purpose_name) { 'Child Purpose' } - let(:user_uuid) { 'user-uuid' } - let(:v1_user) { json :v1_user, uuid: user_uuid } - let(:user) { create :user, uuid: user_uuid } + let(:user) { create :user } before do create :purpose_config, name: child_purpose_name + stub_v2_user(user) stub_v2_plate(parent1, stub_search: false) stub_v2_plate(parent2, stub_search: false) - stub_v2_plate(child_plate_v2, stub_search: false, custom_query: [:plate_with_wells, child_plate_v2.uuid]) + stub_v2_plate(child_plate, stub_search: false, custom_query: [:plate_with_wells, child_plate.uuid]) end context 'on new' do @@ -75,7 +72,7 @@ end context 'on create' do - subject { LabwareCreators::QuadrantStampPrimerPanel.new(api, form_attributes.merge(user_uuid: user_uuid)) } + subject { LabwareCreators::QuadrantStampPrimerPanel.new(api, form_attributes.merge(user_uuid: user.uuid)) } let(:form_attributes) do { @@ -246,20 +243,6 @@ } end - let!(:pooled_plate_creation_request) do - stub_api_post( - 'pooled_plate_creations', - payload: { - pooled_plate_creation: { - user: user_uuid, - child_purpose: child_purpose_uuid, - parents: [parent1_uuid, parent2_uuid] - } - }, - body: json(:plate_creation, child_uuid: child_uuid) - ) - end - let(:transfer_requests) do [ { source_asset: '3-well-A1', outer_request: 'request-0', target_asset: '5-well-A1' }, @@ -290,7 +273,7 @@ 'transfer_request_collections', payload: { transfer_request_collection: { - user: user_uuid, + user: user.uuid, transfer_requests: transfer_requests } }, @@ -298,36 +281,44 @@ ) end - context '#save!' do - setup do - stub_api_get(child_plate_v2.uuid, body: child_plate_v1) - stub_api_get( - 'custom_metadatum_collection-uuid', - body: json(:v1_custom_metadatum_collection, uuid: 'custom_metadatum_collection-uuid') - ) - stub_api_get('user-uuid', body: v1_user) - stub_v2_user(user) - stub_api_get('asset-uuid', body: child_plate_v1) + let(:pooled_plate_creation) do + response = double + allow(response).to receive(:child).and_return(child_plate) - metadata = - attributes_for(:v1_custom_metadatum_collection) - .fetch(:metadata, {}) - .merge(stock_barcode_q0: stock_plate1.barcode.human, stock_barcode_q1: stock_plate2.barcode.human) + response + end - stub_api_put( - 'custom_metadatum_collection-uuid', - payload: { - custom_metadatum_collection: { - metadata: metadata - } - }, - body: json(:v1_custom_metadatum_collection) - ) - end + def expect_pooled_plate_creation + expect_api_v2_posts( + 'PooledPlateCreation', + [{ child_purpose_uuid: child_purpose_uuid, parent_uuids: [parent1_uuid, parent2_uuid], user_uuid: user.uuid }], + [pooled_plate_creation] + ) + end + def expect_custom_metadatum_collection_creation + expect_api_v2_posts( + 'CustomMetadatumCollection', + [ + { + asset_id: child_plate.id, + metadata: { + stock_barcode_q0: stock_plate1.barcode.human, + stock_barcode_q1: stock_plate2.barcode.human + }, + user_id: user.id + } + ] + ) + end + + context '#save!' do it 'creates a plate!' do + expect_pooled_plate_creation + expect_custom_metadatum_collection_creation + subject.save! - expect(pooled_plate_creation_request).to have_been_made.once + expect(transfer_creation_request).to have_been_made.once end end diff --git a/spec/models/labware_creators/shared_examples.rb b/spec/models/labware_creators/shared_examples.rb index 393b5c2ca..88f523dc1 100644 --- a/spec/models/labware_creators/shared_examples.rb +++ b/spec/models/labware_creators/shared_examples.rb @@ -154,7 +154,7 @@ end context 'with a previously passed library and a new repool' do - let(:parent) { build :plate, pools: pools } + let(:parent) { build :plate, pools: } let(:tagged) { true } before { expect(parent).to receive(:tagged?).and_return(tagged) } let(:pools) do @@ -266,9 +266,9 @@ it 'makes the expected requests' do # NB. qc assay post is done using v2 Api, whereas plate creation and transfers posts are using v1 Api - expect(Sequencescape::Api::V2::QcAssay).to receive(:create) - .with(qc_results: dest_well_qc_attributes) - .and_return(true) + expect(Sequencescape::Api::V2::QcAssay).to receive(:create).with(qc_results: dest_well_qc_attributes).and_return( + true + ) expect(subject.save!).to eq true expect(plate_creation_request).to have_been_made expect(transfer_creation_request).to have_been_made diff --git a/spec/models/labware_creators/stamped_plate_reordering_columns_to_rows_spec.rb b/spec/models/labware_creators/stamped_plate_reordering_columns_to_rows_spec.rb index 1282c83a2..b92847b12 100644 --- a/spec/models/labware_creators/stamped_plate_reordering_columns_to_rows_spec.rb +++ b/spec/models/labware_creators/stamped_plate_reordering_columns_to_rows_spec.rb @@ -43,9 +43,11 @@ allow(Sequencescape::Api::V2::Plate).to receive(:find_by).with(uuid: parent_uuid).and_return(parent) - allow(api).to receive_message_chain(:plate_creation, :create!) - .with(parent: parent_uuid, child_purpose: child_purpose_uuid, user: user_uuid) - .and_return(double(child: child_plate)) + allow(api).to receive_message_chain(:plate_creation, :create!).with( + parent: parent_uuid, + child_purpose: child_purpose_uuid, + user: user_uuid + ).and_return(double(child: child_plate)) allow(Sequencescape::Api::V2::Plate).to receive(:find_by).with(uuid: child_uuid).and_return(child_plate) end diff --git a/spec/models/labware_creators/tagged_plate_spec.rb b/spec/models/labware_creators/tagged_plate_spec.rb index 2926c706d..ea2cfd797 100644 --- a/spec/models/labware_creators/tagged_plate_spec.rb +++ b/spec/models/labware_creators/tagged_plate_spec.rb @@ -30,10 +30,12 @@ let(:disable_cross_plate_pool_detection) { false } before do - create :purpose_config, - name: child_purpose_name, - uuid: child_purpose_uuid, - disable_cross_plate_pool_detection: disable_cross_plate_pool_detection + create( + :purpose_config, + name: child_purpose_name, + uuid: child_purpose_uuid, + disable_cross_plate_pool_detection: disable_cross_plate_pool_detection + ) plate_request wells_request end diff --git a/spec/models/labware_creators/tube_from_tube_spec.rb b/spec/models/labware_creators/tube_from_tube_spec.rb index 144cdd1ff..8ed70b32c 100644 --- a/spec/models/labware_creators/tube_from_tube_spec.rb +++ b/spec/models/labware_creators/tube_from_tube_spec.rb @@ -52,7 +52,7 @@ user: 'user-uuid' } }, - body: json(:tube_creation, child_uuid: child_uuid) + body: json(:tube_creation, child_uuid:) ) end diff --git a/spec/models/labware_metadata_spec.rb b/spec/models/labware_metadata_spec.rb index a1efc0d81..bb82795cd 100644 --- a/spec/models/labware_metadata_spec.rb +++ b/spec/models/labware_metadata_spec.rb @@ -43,9 +43,7 @@ it 'updates metadata' do metadata = attributes_for(:custom_metadatum_collection).fetch(:metadata, {}).merge(updated_metadata) - expect(plate_with_metadata.custom_metadatum_collection).to receive(:update!) - .with(metadata: metadata) - .and_return(true) + expect(plate_with_metadata.custom_metadatum_collection).to receive(:update!).with(metadata:).and_return(true) LabwareMetadata.new(labware: plate_with_metadata, user_uuid: user.uuid).update!(updated_metadata) end @@ -63,13 +61,11 @@ it 'updates metadata' do metadata = attributes_for(:custom_metadatum_collection).fetch(:metadata, {}).merge(updated_metadata) - expect(plate_with_metadata.custom_metadatum_collection).to receive(:update!) - .with(metadata: metadata) - .and_return(true) + expect(plate_with_metadata.custom_metadatum_collection).to receive(:update!).with(metadata:).and_return(true) - LabwareMetadata - .new(barcode: plate_with_metadata.barcode.machine, user_uuid: user.uuid) - .update!(updated_metadata) + LabwareMetadata.new(barcode: plate_with_metadata.barcode.machine, user_uuid: user.uuid).update!( + updated_metadata + ) end end end @@ -95,9 +91,7 @@ it 'updates metadata' do metadata = attributes_for(:custom_metadatum_collection).fetch(:metadata, {}).merge(updated_metadata) - expect(tube_with_metadata.custom_metadatum_collection).to receive(:update!) - .with(metadata: metadata) - .and_return(true) + expect(tube_with_metadata.custom_metadatum_collection).to receive(:update!).with(metadata:).and_return(true) LabwareMetadata.new(labware: tube_with_metadata, user_uuid: user.uuid).update!(updated_metadata) end @@ -115,9 +109,7 @@ it 'updates metadata' do metadata = attributes_for(:custom_metadatum_collection).fetch(:metadata, {}).merge(updated_metadata) - expect(tube_with_metadata.custom_metadatum_collection).to receive(:update!) - .with(metadata: metadata) - .and_return(true) + expect(tube_with_metadata.custom_metadatum_collection).to receive(:update!).with(metadata:).and_return(true) LabwareMetadata.new(barcode: tube_with_metadata.barcode.machine, user_uuid: user.uuid).update!(updated_metadata) end diff --git a/spec/models/presenters/banking_plate_presenter_spec.rb b/spec/models/presenters/banking_plate_presenter_spec.rb index 090011616..00d85f63d 100644 --- a/spec/models/presenters/banking_plate_presenter_spec.rb +++ b/spec/models/presenters/banking_plate_presenter_spec.rb @@ -10,8 +10,8 @@ let(:purpose_name) { 'banking-plate-purpose' } let(:purpose) { create :v2_purpose, name: purpose_name } - let(:labware) { create :v2_plate, purpose: purpose } - let(:presenter) { described_class.new(labware: labware) } + let(:labware) { create :v2_plate, purpose: } + let(:presenter) { described_class.new(labware:) } describe '#csv_file_links' do let(:download_in_passed_state_name) { 'Download PBMC Bank Tubes Content Report' } diff --git a/spec/models/presenters/concentration_binned_plate_presenter_spec.rb b/spec/models/presenters/concentration_binned_plate_presenter_spec.rb index 53d1adf42..358878b45 100644 --- a/spec/models/presenters/concentration_binned_plate_presenter_spec.rb +++ b/spec/models/presenters/concentration_binned_plate_presenter_spec.rb @@ -56,7 +56,7 @@ before { stub_v2_plate(labware, stub_search: false, custom_includes: 'wells.aliquots,wells.qc_results') } - subject(:presenter) { Presenters::ConcentrationBinnedPlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::ConcentrationBinnedPlatePresenter.new(labware:) } context 'when binning configuration is missing' do it 'throws an exception' do diff --git a/spec/models/presenters/donor_pooling_plate_presenter_spec.rb b/spec/models/presenters/donor_pooling_plate_presenter_spec.rb index 077bbdaff..3a79a5cd4 100644 --- a/spec/models/presenters/donor_pooling_plate_presenter_spec.rb +++ b/spec/models/presenters/donor_pooling_plate_presenter_spec.rb @@ -74,7 +74,7 @@ let(:option_key) { 'scrna_core_pbmc_donor_pooling_required_number_of_cells' } let(:default_cell_count) { 5000 } - subject { Presenters::DonorPoolingPlatePresenter.new(labware: labware) } + subject { Presenters::DonorPoolingPlatePresenter.new(labware:) } before do Settings.purposes = { diff --git a/spec/models/presenters/final_tube_presenter_spec.rb b/spec/models/presenters/final_tube_presenter_spec.rb index 68297a9ba..bdb366666 100644 --- a/spec/models/presenters/final_tube_presenter_spec.rb +++ b/spec/models/presenters/final_tube_presenter_spec.rb @@ -25,7 +25,7 @@ end let(:sidebar_partial) { 'default' } - subject { Presenters::FinalTubePresenter.new(labware: labware) } + subject { Presenters::FinalTubePresenter.new(labware:) } it_behaves_like 'a labware presenter' end diff --git a/spec/models/presenters/minimal_pcr_plate_presenter_spec.rb b/spec/models/presenters/minimal_pcr_plate_presenter_spec.rb index 08a177ae0..1de7b156d 100644 --- a/spec/models/presenters/minimal_pcr_plate_presenter_spec.rb +++ b/spec/models/presenters/minimal_pcr_plate_presenter_spec.rb @@ -31,7 +31,7 @@ end let(:sidebar_partial) { 'default' } - subject(:presenter) { Presenters::MinimalPcrPlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::MinimalPcrPlatePresenter.new(labware:) } before do create(:purpose_config, uuid: labware.purpose.uuid) diff --git a/spec/models/presenters/minimal_plate_presenter_spec.rb b/spec/models/presenters/minimal_plate_presenter_spec.rb index eba217064..3245a160e 100644 --- a/spec/models/presenters/minimal_plate_presenter_spec.rb +++ b/spec/models/presenters/minimal_plate_presenter_spec.rb @@ -35,7 +35,7 @@ create :stock_plate_config, uuid: 'stock-plate-purpose-uuid' end - subject(:presenter) { Presenters::MinimalPlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::MinimalPlatePresenter.new(labware:) } it 'returns label attributes' do expected_label = { diff --git a/spec/models/presenters/minimal_stock_plate_presenter_spec.rb b/spec/models/presenters/minimal_stock_plate_presenter_spec.rb index ce55c0b28..947208bc1 100644 --- a/spec/models/presenters/minimal_stock_plate_presenter_spec.rb +++ b/spec/models/presenters/minimal_stock_plate_presenter_spec.rb @@ -33,7 +33,7 @@ before { create :stock_plate_config, uuid: labware.purpose.uuid, name: purpose_name } - subject(:presenter) { Presenters::MinimalStockPlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::MinimalStockPlatePresenter.new(labware:) } it 'returns label attributes' do expected_label = { diff --git a/spec/models/presenters/normalised_binned_plate_presenter_spec.rb b/spec/models/presenters/normalised_binned_plate_presenter_spec.rb index 3388763cb..1f4a6a5f4 100644 --- a/spec/models/presenters/normalised_binned_plate_presenter_spec.rb +++ b/spec/models/presenters/normalised_binned_plate_presenter_spec.rb @@ -57,7 +57,7 @@ before { stub_v2_plate(labware, stub_search: false, custom_includes: 'wells.aliquots,wells.qc_results') } - subject(:presenter) { Presenters::NormalisedBinnedPlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::NormalisedBinnedPlatePresenter.new(labware:) } context 'when configuration is missing' do it 'throws an exception' do diff --git a/spec/models/presenters/pcr_cycles_binned_plate_using_request_metadata_presenter_spec.rb b/spec/models/presenters/pcr_cycles_binned_plate_using_request_metadata_presenter_spec.rb index fb20d6127..0cdf30e8b 100644 --- a/spec/models/presenters/pcr_cycles_binned_plate_using_request_metadata_presenter_spec.rb +++ b/spec/models/presenters/pcr_cycles_binned_plate_using_request_metadata_presenter_spec.rb @@ -110,7 +110,7 @@ ) end - subject(:presenter) { Presenters::PcrCyclesBinnedPlateUsingRequestMetadataPresenter.new(labware: labware) } + subject(:presenter) { Presenters::PcrCyclesBinnedPlateUsingRequestMetadataPresenter.new(labware:) } context 'when binning' do it_behaves_like 'a labware presenter' diff --git a/spec/models/presenters/pcr_cycles_binned_plate_using_well_metadata_presenter_spec.rb b/spec/models/presenters/pcr_cycles_binned_plate_using_well_metadata_presenter_spec.rb index 1c8d9ac3f..5293c69ee 100644 --- a/spec/models/presenters/pcr_cycles_binned_plate_using_well_metadata_presenter_spec.rb +++ b/spec/models/presenters/pcr_cycles_binned_plate_using_well_metadata_presenter_spec.rb @@ -84,7 +84,7 @@ before { stub_v2_plate(labware, stub_search: false, custom_includes: 'wells.aliquots,wells.qc_results') } - subject(:presenter) { Presenters::PcrCyclesBinnedPlateUsingWellMetadataPresenter.new(labware: labware) } + subject(:presenter) { Presenters::PcrCyclesBinnedPlateUsingWellMetadataPresenter.new(labware:) } context 'when binning' do it_behaves_like 'a labware presenter' diff --git a/spec/models/presenters/permissive_presenter_spec.rb b/spec/models/presenters/permissive_presenter_spec.rb index 9eb4cb12a..c64484a9c 100644 --- a/spec/models/presenters/permissive_presenter_spec.rb +++ b/spec/models/presenters/permissive_presenter_spec.rb @@ -4,7 +4,7 @@ let(:purpose_name) { 'Example purpose' } let(:labware) { create :v2_plate, state: state, purpose_name: purpose_name, pool_sizes: [1] } - subject { Presenters::PermissivePresenter.new(labware: labware) } + subject { Presenters::PermissivePresenter.new(labware:) } before(:each) do create :purpose_config, uuid: 'child-purpose', name: 'Child purpose' diff --git a/spec/models/presenters/plate_presenter_spec.rb b/spec/models/presenters/plate_presenter_spec.rb index 3a4e90622..40c8a357a 100644 --- a/spec/models/presenters/plate_presenter_spec.rb +++ b/spec/models/presenters/plate_presenter_spec.rb @@ -38,7 +38,7 @@ create(:stock_plate_config, uuid: 'stock-plate-purpose-uuid') end - subject(:presenter) { Presenters::PlatePresenter.new(labware: labware) } + subject(:presenter) { Presenters::PlatePresenter.new(labware:) } describe '#custom_metadata_fields' do context 'with custom_metadata_fields' do diff --git a/spec/models/presenters/qc_threshold_presenter_spec.rb b/spec/models/presenters/qc_threshold_presenter_spec.rb index 4b4ac280c..cdfa7d814 100644 --- a/spec/models/presenters/qc_threshold_presenter_spec.rb +++ b/spec/models/presenters/qc_threshold_presenter_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Presenters::QcThresholdPresenter do subject(:presenter) { described_class.new(plate, configuration) } - let(:plate) { instance_double(Sequencescape::Api::V2::Plate, wells: wells) } + let(:plate) { instance_double(Sequencescape::Api::V2::Plate, wells:) } let(:wells) { qc_results.map { |results| instance_double(Sequencescape::Api::V2::Well, all_latest_qc: results) } } let(:qc_results) do [ diff --git a/spec/models/presenters/rvi_cnda_xp_presenter_spec.rb b/spec/models/presenters/rvi_cnda_xp_presenter_spec.rb index 96d9aa76f..171a3d85e 100644 --- a/spec/models/presenters/rvi_cnda_xp_presenter_spec.rb +++ b/spec/models/presenters/rvi_cnda_xp_presenter_spec.rb @@ -4,7 +4,7 @@ let(:purpose_name) { 'Example purpose' } let(:labware) { create :v2_plate, state: state, purpose_name: purpose_name, pool_sizes: [1] } - subject { Presenters::RviCdnaXpPresenter.new(labware: labware) } + subject { Presenters::RviCdnaXpPresenter.new(labware:) } before(:each) do create :purpose_config, uuid: 'child-purpose', name: 'Child purpose' diff --git a/spec/models/presenters/simple_tube_spec.rb b/spec/models/presenters/simple_tube_spec.rb index cd4e60834..f560d7d42 100644 --- a/spec/models/presenters/simple_tube_spec.rb +++ b/spec/models/presenters/simple_tube_spec.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true RSpec.describe Presenters::SimpleTubePresenter do - let(:labware) { build :v2_tube, state: state } + let(:labware) { build :v2_tube, state: } - subject { Presenters::SimpleTubePresenter.new(labware: labware) } + subject { Presenters::SimpleTubePresenter.new(labware:) } before do create(:purpose_config, name: 'Example Plate Purpose', uuid: 'example-purpose-uuid-1') diff --git a/spec/models/presenters/single_child_permissive_presenter_spec.rb b/spec/models/presenters/single_child_permissive_presenter_spec.rb index 3fc336f4f..bfdce323e 100644 --- a/spec/models/presenters/single_child_permissive_presenter_spec.rb +++ b/spec/models/presenters/single_child_permissive_presenter_spec.rb @@ -6,7 +6,7 @@ let(:child_purpose) { 'Child purpose' } let(:child_plate) { create :v2_plate, purpose_name: child_purpose } - subject { Presenters::SingleChildPermissivePresenter.new(labware: labware) } + subject { Presenters::SingleChildPermissivePresenter.new(labware:) } before(:each) do create :purpose_config, uuid: 'child-purpose', name: child_purpose diff --git a/spec/models/presenters/standard_presenter_spec.rb b/spec/models/presenters/standard_presenter_spec.rb index 09a36dff6..a97b65bab 100644 --- a/spec/models/presenters/standard_presenter_spec.rb +++ b/spec/models/presenters/standard_presenter_spec.rb @@ -39,7 +39,7 @@ end let(:suggest_passes) { nil } - subject { Presenters::StandardPresenter.new(labware: labware) } + subject { Presenters::StandardPresenter.new(labware:) } it 'returns the priority' do expect(subject.priority).to eq(2) diff --git a/spec/models/presenters/stock_plate_presenter_spec.rb b/spec/models/presenters/stock_plate_presenter_spec.rb index 57641d1b3..9a2e921d0 100644 --- a/spec/models/presenters/stock_plate_presenter_spec.rb +++ b/spec/models/presenters/stock_plate_presenter_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Presenters::StockPlatePresenter do let(:labware) { create :v2_stock_plate } - subject { Presenters::StockPlatePresenter.new(labware: labware) } + subject { Presenters::StockPlatePresenter.new(labware:) } let(:barcode_string) { labware.human_barcode } diff --git a/spec/models/presenters/submission_plate_presenter_spec.rb b/spec/models/presenters/submission_plate_presenter_spec.rb index c24588e46..17a416937 100644 --- a/spec/models/presenters/submission_plate_presenter_spec.rb +++ b/spec/models/presenters/submission_plate_presenter_spec.rb @@ -4,7 +4,7 @@ require_relative 'shared_labware_presenter_examples' RSpec.describe Presenters::SubmissionPlatePresenter do - subject(:presenter) { described_class.new(labware: labware) } + subject(:presenter) { described_class.new(labware:) } let(:submission_options) do { @@ -220,7 +220,7 @@ direct_submissions: submissions, state: state end - let(:submissions) { create_list :v2_submission, 1, state: state } + let(:submissions) { create_list :v2_submission, 1, state: } let(:barcode_string) { 'DN2T' } let(:purpose_name) { 'Test Plate' } let(:title) { purpose_name } @@ -262,7 +262,7 @@ direct_submissions: submissions, state: state end - let(:submissions) { create_list :v2_submission, 1, state: state } + let(:submissions) { create_list :v2_submission, 1, state: } let(:barcode_string) { 'DN2T' } let(:purpose_name) { 'Test Plate' } let(:title) { purpose_name } diff --git a/spec/models/presenters/tag_plate_384_presenter_spec.rb b/spec/models/presenters/tag_plate_384_presenter_spec.rb index 6b6c3d823..e501fe03e 100644 --- a/spec/models/presenters/tag_plate_384_presenter_spec.rb +++ b/spec/models/presenters/tag_plate_384_presenter_spec.rb @@ -11,7 +11,7 @@ let(:purpose_name) { 'Tag Plate - 384' } let(:purpose) { create :v2_purpose, name: purpose_name } let(:labware) { create :v2_plate, purpose: purpose, size: 384, stock_plate: nil } - let(:presenter) { described_class.new(labware: labware) } + let(:presenter) { described_class.new(labware:) } it 'can be looked up for labware' do expect(Presenters.lookup_for(labware)).to be(described_class) diff --git a/spec/models/presenters/tube_presenter_spec.rb b/spec/models/presenters/tube_presenter_spec.rb index a7e8260ff..9a37d3c35 100644 --- a/spec/models/presenters/tube_presenter_spec.rb +++ b/spec/models/presenters/tube_presenter_spec.rb @@ -27,7 +27,7 @@ create(:qc_result, key: 'molarity', value: '5.5', units: 'nM') ] end - let(:receptacle) { create :v2_receptacle, qc_results: qc_results } + let(:receptacle) { create :v2_receptacle, qc_results: } let(:summary_tab) do [ ['Barcode', 'NT6T 3980000006844'], @@ -39,7 +39,7 @@ end let(:sidebar_partial) { 'default' } - subject { Presenters::TubePresenter.new(labware: labware) } + subject { Presenters::TubePresenter.new(labware:) } it_behaves_like 'a labware presenter' diff --git a/spec/models/presenters/tube_rack_presenter_spec.rb b/spec/models/presenters/tube_rack_presenter_spec.rb index 676527bba..24293626d 100644 --- a/spec/models/presenters/tube_rack_presenter_spec.rb +++ b/spec/models/presenters/tube_rack_presenter_spec.rb @@ -47,7 +47,7 @@ create(:stock_plate_config, uuid: 'stock-plate-purpose-uuid') end - subject(:presenter) { described_class.new(labware: labware) } + subject(:presenter) { described_class.new(labware:) } it_behaves_like 'a labware presenter' diff --git a/spec/models/presenters/unknown_plate_presenter_spec.rb b/spec/models/presenters/unknown_plate_presenter_spec.rb index 53f7dbd74..4460fe4d0 100644 --- a/spec/models/presenters/unknown_plate_presenter_spec.rb +++ b/spec/models/presenters/unknown_plate_presenter_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Presenters::UnknownPlatePresenter do let(:labware) { create :v2_plate, purpose_name: 'Other plate' } - subject { described_class.new(labware: labware) } + subject { described_class.new(labware:) } it 'prevents state change' do expect { |b| subject.default_state_change(&b) }.not_to yield_control diff --git a/spec/models/print_job_spec.rb b/spec/models/print_job_spec.rb index 7a0ffbf07..162c88b2d 100644 --- a/spec/models/print_job_spec.rb +++ b/spec/models/print_job_spec.rb @@ -157,17 +157,32 @@ end it 'should not execute if pmb is down' do - stub_request(:get, "http://localhost:3002#{label_template_url}").to_raise(JsonApiClient::Errors::ConnectionError) - stub_request(:post, 'http://localhost:3002/v1/print_jobs').to_raise(JsonApiClient::Errors::ConnectionError) + pj = + PrintJob.new( + printer_name: printer_pmb.name, + printer: printer_pmb, + label_templates_by_service: label_templates_by_service, + labels: [{ label: { barcode: '12345', test_attr: 'test' } }], + number_of_copies: 1 + ) + allow(PMB::LabelTemplate).to receive(:where).and_raise(JsonApiClient::Errors::ConnectionError.new('error')) + expect(pj.execute).to be false + expect(pj.errors.full_messages[0]).to eq('Pmb PrintMyBarcode service is down') + end + it 'should not execute if the pmb label template cannot be found' do pj = PrintJob.new( printer_name: printer_pmb.name, printer: printer_pmb, + label_templates_by_service: label_templates_by_service, labels: [{ label: { barcode: '12345', test_attr: 'test' } }], number_of_copies: 1 ) + + allow(PMB::LabelTemplate).to receive(:where).and_return([]) expect(pj.execute).to be false + expect(pj.errors.full_messages[0]).to eq("Pmb Unable to find label template: #{label_template_name_pmb}") end end diff --git a/spec/models/robots/plate_to_tube_racks_robot_spec.rb b/spec/models/robots/plate_to_tube_racks_robot_spec.rb index 0955e4dd9..0b82ae934 100644 --- a/spec/models/robots/plate_to_tube_racks_robot_spec.rb +++ b/spec/models/robots/plate_to_tube_racks_robot_spec.rb @@ -200,7 +200,7 @@ } end - let(:robot) { described_class.new(robot_config.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { described_class.new(robot_config.merge(api:, user_uuid:)) } let(:scanned_layout) do { diff --git a/spec/models/robots/pooling_and_splitting_robot_spec.rb b/spec/models/robots/pooling_and_splitting_robot_spec.rb index 355883d39..1e615cbf0 100644 --- a/spec/models/robots/pooling_and_splitting_robot_spec.rb +++ b/spec/models/robots/pooling_and_splitting_robot_spec.rb @@ -73,7 +73,7 @@ end let(:target_plate_2) { create :v2_plate, target_plate_2_attributes } - let(:robot) { Robots::PoolingAndSplittingRobot.new(robot_spec.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { Robots::PoolingAndSplittingRobot.new(robot_spec.merge(api:, user_uuid:)) } let(:robot_spec) do { diff --git a/spec/models/robots/pooling_robot_spec.rb b/spec/models/robots/pooling_robot_spec.rb index ae8fa0854..9199b8c66 100644 --- a/spec/models/robots/pooling_robot_spec.rb +++ b/spec/models/robots/pooling_robot_spec.rb @@ -45,10 +45,10 @@ let(:target_plate) { create :v2_plate, target_plate_attributes } let(:target_plate_parents) { [source_plate] } - let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: metadata } + let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: } let(:metadata) { { 'other_key' => 'value' } } - let(:robot) { Robots::PoolingRobot.new(robot_spec.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { Robots::PoolingRobot.new(robot_spec.merge(api:, user_uuid:)) } let(:robot_spec) do { diff --git a/spec/models/robots/quadrant_robot_spec.rb b/spec/models/robots/quadrant_robot_spec.rb index 8badd8386..f31d579bb 100644 --- a/spec/models/robots/quadrant_robot_spec.rb +++ b/spec/models/robots/quadrant_robot_spec.rb @@ -43,10 +43,10 @@ let(:target_plate) { create :v2_plate, target_plate_attributes } let(:target_plate_parents) { [source_plate] } - let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: metadata } + let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: } let(:metadata) { { 'other_key' => 'value' } } - let(:robot) { Robots::QuadrantRobot.new(robot_spec.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { Robots::QuadrantRobot.new(robot_spec.merge(api:, user_uuid:)) } let(:robot_spec) do { diff --git a/spec/models/robots/robot_spec.rb b/spec/models/robots/robot_spec.rb index 5d3fe1c43..5620c1a36 100644 --- a/spec/models/robots/robot_spec.rb +++ b/spec/models/robots/robot_spec.rb @@ -36,10 +36,10 @@ end let(:target_plate_parents) { [source_plate] } let(:target_tube_parents) { [source_plate] } - let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: metadata } + let(:custom_metadatum_collection) { create :custom_metadatum_collection, metadata: } let(:metadata) { { 'other_key' => 'value' } } - let(:robot) { Robots::Robot.new(robot_spec.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { Robots::Robot.new(robot_spec.merge(api:, user_uuid:)) } shared_examples 'a robot' do context 'with an unknown plate' do diff --git a/spec/models/robots/splitting_robot_spec.rb b/spec/models/robots/splitting_robot_spec.rb index 7f8e5995f..5728076a5 100644 --- a/spec/models/robots/splitting_robot_spec.rb +++ b/spec/models/robots/splitting_robot_spec.rb @@ -27,7 +27,7 @@ let(:metadata_uuid) { SecureRandom.uuid } let(:custom_metadatum_collection) { create :custom_metdatum_collection, uuid: metadata_uuid } - let(:robot) { Robots::SplittingRobot.new(robot_spec.merge(api: api, user_uuid: user_uuid)) } + let(:robot) { Robots::SplittingRobot.new(robot_spec.merge(api:, user_uuid:)) } describe '#verify' do subject { robot.verify(bed_labwares: scanned_layout) } diff --git a/spec/models/sequencescape_submission_spec.rb b/spec/models/sequencescape_submission_spec.rb index 33282d487..480b46fb7 100644 --- a/spec/models/sequencescape_submission_spec.rb +++ b/spec/models/sequencescape_submission_spec.rb @@ -73,17 +73,17 @@ let(:plate2) { create(:passed_plate) } it 'returns the uuids of the labwares wells' do obj = described_class.new(attributes.merge(extra_barcodes: %w[1234 5678])) - allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter) - .with(barcode: %w[1234 5678]) - .and_return([plate, plate2]) + allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter).with( + barcode: %w[1234 5678] + ).and_return([plate, plate2]) # There are 4 non-empty wells in each labware expect(obj.extra_assets.count).to eq(8) end it 'removes duplicates uuids in the returned list' do - allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter) - .with(barcode: %w[1234 1234 5678]) - .and_return([plate, plate, plate2]) + allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter).with( + barcode: %w[1234 1234 5678] + ).and_return([plate, plate, plate2]) obj = described_class.new(attributes.merge(extra_barcodes: %w[1234 1234 5678])) expect(obj.extra_assets.count).to eq(8) expect(obj.extra_assets.uniq.count).to eq(8) @@ -104,9 +104,9 @@ let(:plate2) { create(:passed_plate) } before do - allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter) - .with(barcode: %w[1234 5678]) - .and_return([plate, plate2]) + allow(Sequencescape::Api::V2).to receive(:additional_plates_for_presenter).with( + barcode: %w[1234 5678] + ).and_return([plate, plate2]) end it 'returns the current assets plus the extra assets' do diff --git a/spec/models/tube_rack_walking_spec.rb b/spec/models/tube_rack_walking_spec.rb index ba539837c..7951b061b 100644 --- a/spec/models/tube_rack_walking_spec.rb +++ b/spec/models/tube_rack_walking_spec.rb @@ -6,7 +6,7 @@ subject { TubeRackWalking::Walker.new(rack) } context 'A v2 rack' do - let(:rack) { build :tube_rack, tubes: tubes } + let(:rack) { build :tube_rack, tubes: } let(:tubes) { { 'A1' => create(:v2_tube), 'B1' => create(:v2_tube), 'H10' => create(:v2_tube) } } diff --git a/spec/models/utility/cell_count_spot_checking_spec.rb b/spec/models/utility/cell_count_spot_checking_spec.rb index 57b445b29..019b1a145 100644 --- a/spec/models/utility/cell_count_spot_checking_spec.rb +++ b/spec/models/utility/cell_count_spot_checking_spec.rb @@ -22,13 +22,13 @@ suffix = ((index - 1) / 3) + 1 uuid = "sample-uuid-#{suffix}" # Match the samples of tubes supplier_name = ancestor_tubes[uuid].barcode.human - sample_metadata = create(:v2_sample_metadata, supplier_name: supplier_name) - sample = create(:v2_sample, uuid: uuid, sample_metadata: sample_metadata) - aliquots = [create(:v2_aliquot, sample: sample)] + sample_metadata = create(:v2_sample_metadata, supplier_name:) + sample = create(:v2_sample, uuid:, sample_metadata:) + aliquots = [create(:v2_aliquot, sample:)] location = WellHelpers.well_at_column_index(index - 1) - array << create(:v2_well, aliquots: aliquots, location: location) + array << create(:v2_well, aliquots:, location:) end - create(:v2_plate, wells: wells) + create(:v2_plate, wells:) end let(:plate_wells_grouped_by_barcode) do diff --git a/spec/sequencescape/api/v2/plate_spec.rb b/spec/sequencescape/api/v2/plate_spec.rb index ad63ee1cb..b68382890 100644 --- a/spec/sequencescape/api/v2/plate_spec.rb +++ b/spec/sequencescape/api/v2/plate_spec.rb @@ -83,32 +83,30 @@ describe '::find_by' do it 'finds a plate' do - stub_request(:get, 'http://example.com:3000/api/v2/plates') - .with( - query: { - fields: { - sample_metadata: 'sample_common_name,collected_by,sample_description', - submissions: 'lanes_of_sequencing' - }, - filter: { - uuid: '8681e102-b737-11ec-8ace-acde48001122' - }, - # This is a bit brittle, as it depends on the exact order. - include: - 'purpose,child_plates.purpose,wells.downstream_tubes.purpose,' \ - 'wells.requests_as_source.request_type,wells.requests_as_source.primer_panel,' \ - 'wells.requests_as_source.pre_capture_pool,wells.requests_as_source.submission,' \ - 'wells.aliquots.sample.sample_metadata,wells.aliquots.request.request_type,' \ - 'wells.aliquots.request.primer_panel,wells.aliquots.request.pre_capture_pool,' \ - 'wells.aliquots.request.submission,' \ - 'wells.transfer_requests_as_target.source_asset' + stub_request(:get, 'http://example.com:3000/api/v2/plates').with( + query: { + fields: { + sample_metadata: 'sample_common_name,collected_by,sample_description', + submissions: 'lanes_of_sequencing' }, - headers: { - 'Accept' => 'application/vnd.api+json', - 'Content-Type' => 'application/vnd.api+json' - } - ) - .to_return(File.new('./spec/contracts/v2-plate-by-uuid-for-presenter.txt')) + filter: { + uuid: '8681e102-b737-11ec-8ace-acde48001122' + }, + # This is a bit brittle, as it depends on the exact order. + include: + 'purpose,child_plates.purpose,wells.downstream_tubes.purpose,' \ + 'wells.requests_as_source.request_type,wells.requests_as_source.primer_panel,' \ + 'wells.requests_as_source.pre_capture_pool,wells.requests_as_source.submission,' \ + 'wells.aliquots.sample.sample_metadata,wells.aliquots.request.request_type,' \ + 'wells.aliquots.request.primer_panel,wells.aliquots.request.pre_capture_pool,' \ + 'wells.aliquots.request.submission,' \ + 'wells.transfer_requests_as_target.source_asset' + }, + headers: { + 'Accept' => 'application/vnd.api+json', + 'Content-Type' => 'application/vnd.api+json' + } + ).to_return(File.new('./spec/contracts/v2-plate-by-uuid-for-presenter.txt')) expect( Sequencescape::Api::V2::Plate.find_by(uuid: '8681e102-b737-11ec-8ace-acde48001122') ).to be_a Sequencescape::Api::V2::Plate diff --git a/spec/sequencescape/api/v2/shared_examples.rb b/spec/sequencescape/api/v2/shared_examples.rb index f695a7147..2c8e67d47 100644 --- a/spec/sequencescape/api/v2/shared_examples.rb +++ b/spec/sequencescape/api/v2/shared_examples.rb @@ -60,12 +60,12 @@ let(:alternative_workline_name) { 'Some other plate with some stuff inside' } before do - allow(SearchHelper).to receive(:alternative_workline_reference_name) - .with(the_labware) - .and_return(alternative_workline_name) - allow(ancestors_scope).to receive(:where) - .with(purpose_name: alternative_workline_name) - .and_return(alternative_workline_reference_plates) + allow(SearchHelper).to receive(:alternative_workline_reference_name).with(the_labware).and_return( + alternative_workline_name + ) + allow(ancestors_scope).to receive(:where).with(purpose_name: alternative_workline_name).and_return( + alternative_workline_reference_plates + ) end it 'returns the last alternative workline reference' do diff --git a/spec/support/api_url_helper.rb b/spec/support/api_url_helper.rb index 4894b46af..38bfc39ba 100644 --- a/spec/support/api_url_helper.rb +++ b/spec/support/api_url_helper.rb @@ -28,9 +28,13 @@ def api_url_for(*components) # @param [Int] status: the response status, defaults to 200 # @return mocked_request def stub_api_get(*components, status: 200, body: '{}') - stub_request(:get, api_url_for(*components)) - .with(headers: { 'Accept' => 'application/json' }) - .to_return(status: status, body: body, headers: { 'content-type' => 'application/json' }) + stub_request(:get, api_url_for(*components)).with(headers: { 'Accept' => 'application/json' }).to_return( + status: status, + body: body, + headers: { + 'content-type' => 'application/json' + } + ) end # Generate an API stub for a post request. @@ -50,22 +54,21 @@ def stub_api_get(*components, status: 200, body: '{}') # @param [Int] status: the response status, defaults to 201 # @return mocked_request def stub_api_post(*components, status: 201, body: '{}', payload: {}) - stub_api_modify(*components, status: status, body: body, payload: payload) + stub_api_modify(*components, status:, body:, payload:) end def stub_api_modify(*components, body:, payload:, action: :post, status: 201) - Array(body) - .reduce( - stub_request(action, api_url_for(*components)).with( - headers: { - 'Accept' => 'application/json', - 'content-type' => 'application/json' - }, - body: payload - ) - ) do |request, response| - request.to_return(status: status, body: response, headers: { 'content-type' => 'application/json' }) - end + Array(body).reduce( + stub_request(action, api_url_for(*components)).with( + headers: { + 'Accept' => 'application/json', + 'content-type' => 'application/json' + }, + body: payload + ) + ) do |request, response| + request.to_return(status: status, body: response, headers: { 'content-type' => 'application/json' }) + end end def stub_api_put(*components, body:, payload:) @@ -89,16 +92,16 @@ def stub_api_v2_save(klass) allow_any_instance_of(receiving_class).to receive(:save).and_return(true) end - def stub_api_v2_post(klass, return_value = nil) - # intercepts the 'create!' method for any class beginning with - # 'Sequencescape::Api::V2::' and returns the given value or else true. + def stub_api_v2_post(klass, return_value = nil, method: :create!) + # intercepts the specified `method` for any class beginning with + # 'Sequencescape::Api::V2::' and returns the given `return_value`, or else `true`. receiving_class = "Sequencescape::Api::V2::#{klass}".constantize return_value ||= true - allow(receiving_class).to receive(:create!).and_return(return_value) + allow(receiving_class).to receive(method).and_return(return_value) end - def expect_api_v2_posts(klass, args_list, return_values = []) - # Expects the 'create!' method for any class beginning with + def expect_api_v2_posts(klass, args_list, return_values = [], method: :create!) + # Expects the specified `method` for any class beginning with # 'Sequencescape::Api::V2::' to be called with given arguments, in sequence, and returns the given values. # If return_values is empty, it will return true. receiving_class = "Sequencescape::Api::V2::#{klass}".constantize @@ -106,7 +109,7 @@ def expect_api_v2_posts(klass, args_list, return_values = []) .zip(return_values) .each do |args, ret| ret ||= true - expect(receiving_class).to receive(:create!).with(args).and_return(ret) + expect(receiving_class).to receive(method).with(args).and_return(ret) end end @@ -132,9 +135,10 @@ def stub_v2_plate(plate, stub_search: true, custom_query: nil, custom_includes: if custom_query allow(Sequencescape::Api::V2).to receive(custom_query.first).with(*custom_query.last).and_return(plate) elsif custom_includes - allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes) - .with(custom_includes, { uuid: plate.uuid }) - .and_return(plate) + allow(Sequencescape::Api::V2).to receive(:plate_with_custom_includes).with( + custom_includes, + { uuid: plate.uuid } + ).and_return(plate) else allow(Sequencescape::Api::V2).to receive(:plate_for_presenter).with(uuid: plate.uuid).and_return(plate) end diff --git a/spec/support/contract_helper.rb b/spec/support/contract_helper.rb index 426877b33..9d740f39a 100644 --- a/spec/support/contract_helper.rb +++ b/spec/support/contract_helper.rb @@ -16,7 +16,8 @@ def initialize(root_directory) # rubocop:todo Lint/MissingCopEnableDirective # rubocop:todo Layout/LineLength # rubocop:enable Lint/MissingCopEnableDirective - REQUEST_REGEXP = %r{ # rubocop:todo Lint/MixedRegexpCaptureTypes # rubocop:todo Lint/MixedRegexpCaptureTypes # rubocop:todo Lint/MixedRegexpCaptureTypes + REQUEST_REGEXP = + %r{ # rubocop:todo Lint/MixedRegexpCaptureTypes # rubocop:todo Lint/MixedRegexpCaptureTypes # rubocop:todo Lint/MixedRegexpCaptureTypes # rubocop:enable Layout/LineLength (? \r\n|\r|\n){0} (? GET|PUT|POST|DELETE){0} @@ -67,11 +68,11 @@ def setup_request_and_response_mock private - def contract(contract_name, &block) + def contract(contract_name, &) path = @root.dup until path.empty? filename = File.join(path, 'contracts', "#{contract_name}.txt") - return File.open(filename, 'r', &block) if File.file?(filename) + return File.open(filename, 'r', &) if File.file?(filename) path.pop end @@ -94,15 +95,15 @@ def self.included(base) end module ClassMethods - def expect_request_from(request_filename, &block) + def expect_request_from(request_filename, &) stubbed_request = StubRequestBuilder.new(File.join(File.dirname(__FILE__), %w[.. contracts])) stubbed_request.request(request_filename) - stubbed_request.instance_eval(&block) + stubbed_request.instance_eval(&) stubbed_request.inject_into(self) end def has_a_working_api(times: :any) - expect_request_from('retrieve-api-root') { response('api-root', times: times) } + expect_request_from('retrieve-api-root') { response('api-root', times:) } let(:api) do Sequencescape::Api.new( url: 'http://example.com:3000/', diff --git a/spec/support/factory_bot_extensions.rb b/spec/support/factory_bot_extensions.rb index 54c26c611..0a35ed26f 100644 --- a/spec/support/factory_bot_extensions.rb +++ b/spec/support/factory_bot_extensions.rb @@ -31,8 +31,9 @@ def with_has_many_associations(*names, actions: ['read']) send(association) do {}.tap do |h| h['size'] = send(:"#{association}_count") if send(:"#{association}_actions").include?('read') - h['actions'] = - send(:"#{association}_actions").index_with { |_action_name| "#{resource_url}/#{association}" } + h['actions'] = send(:"#{association}_actions").index_with do |_action_name| + "#{resource_url}/#{association}" + end end end end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 54e533488..68c32423c 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -9,9 +9,9 @@ def stub_search_and_single_result(search, query, result = nil) stub_api_post(search_uuid, 'first', status: 301, payload: query, body: result) else search_url = "http://example.com:3000/#{search_uuid}" - stub_request(:post, "#{search_url}/first") - .with(body: query.to_json) - .to_raise(Sequencescape::Api::ResourceNotFound) + stub_request(:post, "#{search_url}/first").with(body: query.to_json).to_raise( + Sequencescape::Api::ResourceNotFound + ) end end @@ -70,7 +70,7 @@ def stub_update_labware_metadata(barcode, labware_v1, user, metadata) 'custom_metadatum_collection-uuid', payload: { custom_metadatum_collection: { - metadata: metadata + metadata: } }, body: json(:v1_custom_metadatum_collection, uuid: 'custom_metadatum_collection-uuid', metadata: metadata) @@ -111,7 +111,7 @@ def fill_in_with_terminate(terminate, field, options) end def ean13(number, prefix = 'DN') - SBCF::SangerBarcode.new(prefix: prefix, number: number).machine_barcode.to_s + SBCF::SangerBarcode.new(prefix:, number:).machine_barcode.to_s end # Because wells can get quite small on 384 well plates, we use a tooltip diff --git a/spec/support/robot_helpers.rb b/spec/support/robot_helpers.rb index 7441d1f6f..1b86fd797 100644 --- a/spec/support/robot_helpers.rb +++ b/spec/support/robot_helpers.rb @@ -6,9 +6,10 @@ def bed_labware_lookup(labware, includes = %i[purpose parents]) end def bed_labware_lookup_with_barcode(barcode, result, includes = %i[purpose parents]) - allow(Sequencescape::Api::V2::Labware).to receive(:find_all) - .with({ barcode: Array(barcode) }, includes: includes) - .and_return(result) + allow(Sequencescape::Api::V2::Labware).to receive(:find_all).with( + { barcode: Array(barcode) }, + includes: + ).and_return(result) end def bed_plate_lookup(plate, includes = %i[purpose parents]) @@ -16,8 +17,8 @@ def bed_plate_lookup(plate, includes = %i[purpose parents]) end def bed_plate_lookup_with_barcode(barcode, result, includes = %i[purpose parents]) - allow(Sequencescape::Api::V2::Plate).to receive(:find_all) - .with({ barcode: Array(barcode) }, includes: includes) - .and_return(result) + allow(Sequencescape::Api::V2::Plate).to receive(:find_all).with({ barcode: Array(barcode) }, includes:).and_return( + result + ) end end diff --git a/spec/views/exports/bioscan_mbrave.tsv.erb_spec.rb b/spec/views/exports/bioscan_mbrave.tsv.erb_spec.rb index b2c335a35..deea94e29 100644 --- a/spec/views/exports/bioscan_mbrave.tsv.erb_spec.rb +++ b/spec/views/exports/bioscan_mbrave.tsv.erb_spec.rb @@ -57,7 +57,7 @@ tag2: create(:v2_tag, tag_group: create(:v2_tag_group, name: 'Bioscan_reverse_4_24_v2')) ) ] - create(:v2_tube, aliquots: aliquots) + create(:v2_tube, aliquots:) end before { assign(:tube, labware) } diff --git a/spec/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb_spec.rb b/spec/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb_spec.rb index d55abded2..e171ff9d4 100644 --- a/spec/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_gem_x_5p_chip_loading.csv.erb_spec.rb @@ -54,9 +54,9 @@ source_well_a1.location, dest_plate.barcode.human, mapping[dest_well_a1.location], - '13.81', - '37.50', - '0.00' + '13.8', + '37.5', + '0.0' ] end @@ -67,9 +67,9 @@ source_well_b1.location, dest_plate.barcode.human, mapping[dest_well_a2.location], - '109.05', - '37.50', - '0.00' + '109.0', + '37.5', + '0.0' ] end diff --git a/spec/views/exports/hamilton_lrc_pbmc_bank_to_cellaca_common.csv.erb_spec.rb b/spec/views/exports/hamilton_lrc_pbmc_bank_to_cellaca_common.csv.erb_spec.rb index f263c8acd..0a651d56c 100644 --- a/spec/views/exports/hamilton_lrc_pbmc_bank_to_cellaca_common.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_lrc_pbmc_bank_to_cellaca_common.csv.erb_spec.rb @@ -20,13 +20,13 @@ suffix = ((index - 1) / 3) + 1 uuid = "sample-uuid-#{suffix}" # Match the samples of tubes supplier_name = ancestor_tubes[uuid].barcode.human - sample_metadata = create(:v2_sample_metadata, supplier_name: supplier_name) - sample = create(:v2_sample, uuid: uuid, sample_metadata: sample_metadata) - aliquots = [create(:v2_aliquot, sample: sample)] + sample_metadata = create(:v2_sample_metadata, supplier_name:) + sample = create(:v2_sample, uuid:, sample_metadata:) + aliquots = [create(:v2_aliquot, sample:)] location = WellHelpers.well_at_column_index(index - 1) - array << create(:v2_well, aliquots: aliquots, location: location) + array << create(:v2_well, aliquots:, location:) end - create(:v2_plate, wells: wells) + create(:v2_plate, wells:) end let(:workflow) { 'scRNA Core LRC PBMC Bank Cell Count' } @@ -39,7 +39,7 @@ context 'with first replicates' do let(:template) { 'exports/hamilton_lrc_pbmc_bank_to_cellaca_first_count' } it 'renders the expected content' do - render(template: template) + render(template:) content = CSV.parse(rendered) selected_wells = Utility::CellCountSpotChecking.new(plate).first_replicates expect(content).to eq(expected_content(selected_wells)) @@ -49,7 +49,7 @@ context 'with second replicates' do let(:template) { 'exports/hamilton_lrc_pbmc_bank_to_cellaca_second_count' } it 'renders the expected content' do - render(template: template) + render(template:) content = CSV.parse(rendered) selected_wells = Utility::CellCountSpotChecking.new(plate).second_replicates expect(content).to eq(expected_content(selected_wells)) diff --git a/spec/views/exports/hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare.csv.erb_spec.rb b/spec/views/exports/hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare.csv.erb_spec.rb index 30adfccb2..0044cc0f6 100644 --- a/spec/views/exports/hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare.csv.erb_spec.rb @@ -196,24 +196,16 @@ assign(:workflow, workflow_name) # stub the v2 child tube lookups - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube1.barcode.machine) - .and_return(dest_tube1) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube2.barcode.machine) - .and_return(dest_tube2) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube3.barcode.machine) - .and_return(dest_tube3) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube4.barcode.machine) - .and_return(dest_tube4) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube5.barcode.machine) - .and_return(dest_tube5) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube6.barcode.machine) - .and_return(dest_tube6) + custom_includes = 'custom_metadatum_collection' + dest_tubes = [dest_tube1, dest_tube2, dest_tube3, dest_tube4, dest_tube5, dest_tube6] + + dest_tubes.each do |dest_tube| + allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes).with( + custom_includes, + nil, + barcode: dest_tube.barcode.machine + ).and_return(dest_tube) + end end it 'renders the expected content' do diff --git a/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_cellaca_count.csv.erb_spec.rb b/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_cellaca_count.csv.erb_spec.rb index 417c31e95..1163ee23b 100644 --- a/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_cellaca_count.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_cellaca_count.csv.erb_spec.rb @@ -4,13 +4,13 @@ has_a_working_api let(:wells) do - (1..12).map do |index| # one-based index + (1..12).map do |index| # one-based index supplier_name = "vac-tube-barcode-#{index}" - sample_metadata = create(:v2_sample_metadata, supplier_name: supplier_name) - sample = create(:v2_sample, sample_metadata: sample_metadata) - aliquots = [create(:v2_aliquot, sample: sample)] + sample_metadata = create(:v2_sample_metadata, supplier_name:) + sample = create(:v2_sample, sample_metadata:) + aliquots = [create(:v2_aliquot, sample:)] location = WellHelpers.well_at_column_index(index - 1) - create(:v2_well, aliquots: aliquots, location: location) + create(:v2_well, aliquots:, location:) end end @@ -23,7 +23,7 @@ wells[2].state = 'failed' wells[3].state = 'failed' - create(:v2_plate, wells: wells) + create(:v2_plate, wells:) end let(:workflow) { 'scRNA Core LRC PBMC Defrost PBS Cell Count' } @@ -35,7 +35,7 @@ ['Plate Barcode', 'Well Position', 'Vac Tube Barcode', 'Sample Name', 'Well Name'] ] body = - (5..12).map do |index| # one-based index + (5..12).map do |index| # one-based index well = plate.wells_in_columns[index - 1] sample = well.aliquots.first.sample [plate.labware_barcode.human, well.location, sample.sample_metadata.supplier_name, sample.name, well.name] diff --git a/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb_spec.rb b/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb_spec.rb index 8bc52ae7f..5918977e4 100644 --- a/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_lrc_pbmc_defrost_pbs_to_lrc_pbmc_pools.csv.erb_spec.rb @@ -10,20 +10,20 @@ let(:plate1_barcode) { 'DN1S' } let(:plate2_barcode) { 'DN2T' } - let(:total_cell_count_a1) { create(:qc_result, key: 'total_cell_count', value: '1_000_000', units: 'cells/ml') } - let(:total_cell_count_b1) { create(:qc_result, key: 'total_cell_count', value: '2_000_000', units: 'cells/ml') } - let(:total_cell_count_c1) { create(:qc_result, key: 'total_cell_count', value: '3_000_000', units: 'cells/ml') } - let(:total_cell_count_d1) { create(:qc_result, key: 'total_cell_count', value: '4_000_000', units: 'cells/ml') } + let(:total_cell_count_a1) { create(:qc_result, key: 'total_cell_count', value: '100_000', units: 'cells/ml') } + let(:total_cell_count_b1) { create(:qc_result, key: 'total_cell_count', value: '200_000', units: 'cells/ml') } + let(:total_cell_count_c1) { create(:qc_result, key: 'total_cell_count', value: '300_000', units: 'cells/ml') } + let(:total_cell_count_d1) { create(:qc_result, key: 'total_cell_count', value: '400_000', units: 'cells/ml') } - let(:total_cell_count_a2) { create(:qc_result, key: 'total_cell_count', value: '5_000_000', units: 'cells/ml') } - let(:total_cell_count_b2) { create(:qc_result, key: 'total_cell_count', value: '6_000_000', units: 'cells/ml') } - let(:total_cell_count_c2) { create(:qc_result, key: 'total_cell_count', value: '7_000_000', units: 'cells/ml') } - let(:total_cell_count_d2) { create(:qc_result, key: 'total_cell_count', value: '8_000_000', units: 'cells/ml') } + let(:total_cell_count_a2) { create(:qc_result, key: 'total_cell_count', value: '500_000', units: 'cells/ml') } + let(:total_cell_count_b2) { create(:qc_result, key: 'total_cell_count', value: '600_000', units: 'cells/ml') } + let(:total_cell_count_c2) { create(:qc_result, key: 'total_cell_count', value: '700_000', units: 'cells/ml') } + let(:total_cell_count_d2) { create(:qc_result, key: 'total_cell_count', value: '800_000', units: 'cells/ml') } - let(:total_cell_count_a3) { create(:qc_result, key: 'total_cell_count', value: '9_000_000', units: 'cells/ml') } - let(:total_cell_count_b3) { create(:qc_result, key: 'total_cell_count', value: '10_000_000', units: 'cells/ml') } - let(:total_cell_count_c3) { create(:qc_result, key: 'total_cell_count', value: '11_000_000', units: 'cells/ml') } - let(:total_cell_count_d3) { create(:qc_result, key: 'total_cell_count', value: '12_000_000', units: 'cells/ml') } + let(:total_cell_count_a3) { create(:qc_result, key: 'total_cell_count', value: '900_000', units: 'cells/ml') } + let(:total_cell_count_b3) { create(:qc_result, key: 'total_cell_count', value: '1_000_000', units: 'cells/ml') } + let(:total_cell_count_c3) { create(:qc_result, key: 'total_cell_count', value: '1_100_000', units: 'cells/ml') } + let(:total_cell_count_d3) { create(:qc_result, key: 'total_cell_count', value: '1_200_000', units: 'cells/ml') } let(:source_well_a1) do create(:v2_well, location: 'A1', qc_results: [total_cell_count_a1], plate_barcode: plate1_barcode) @@ -130,18 +130,18 @@ 'Sample Volume (µL)', 'Resuspension Volume (µL)' ], - %w[DN1S A1 DN3U A1 5.00 11.90], - %w[DN1S B1 DN3U B1 2.50 11.90], - %w[DN1S A2 DN3U A1 1.00 11.90], - %w[DN1S B2 DN3U B1 0.83 11.90], - %w[DN1S A3 DN3U A1 0.56 11.90], - %w[DN1S B3 DN3U B1 0.50 11.90], - %w[DN2T C1 DN3U A1 1.67 11.90], - %w[DN2T D1 DN3U B1 1.25 11.90], - %w[DN2T C2 DN3U A1 0.71 11.90], - %w[DN2T D2 DN3U B1 0.62 11.90], - %w[DN2T C3 DN3U A1 0.45 11.90], - %w[DN2T D3 DN3U B1 0.42 11.90] + %w[DN1S A1 DN3U A1 50.0 11.9], + %w[DN1S B1 DN3U B1 25.0 11.9], + %w[DN1S A2 DN3U A1 10.0 11.9], + %w[DN1S B2 DN3U B1 8.3 11.9], + %w[DN1S A3 DN3U A1 5.6 11.9], + %w[DN1S B3 DN3U B1 5.0 11.9], + %w[DN2T C1 DN3U A1 16.7 11.9], + %w[DN2T D1 DN3U B1 12.5 11.9], + %w[DN2T C2 DN3U A1 7.1 11.9], + %w[DN2T D2 DN3U B1 6.2 11.9], + %w[DN2T C3 DN3U A1 5.0 11.9], + %w[DN2T D3 DN3U B1 5.0 11.9] ] end @@ -175,7 +175,7 @@ context 'with study-specific cell count option' do let!(:study) do - poly_metadatum = create(:poly_metadatum, key: cell_count_key, value: '9000') + poly_metadatum = create(:poly_metadatum, key: cell_count_key, value: '6000') create(:study_with_poly_metadata, poly_metadata: [poly_metadatum]) # poly_metadata with cell count option end @@ -191,18 +191,18 @@ 'Sample Volume (µL)', 'Resuspension Volume (µL)' ], - %w[DN1S A1 DN3U A1 9.00 21.43], - %w[DN1S B1 DN3U B1 4.50 21.43], - %w[DN1S A2 DN3U A1 1.80 21.43], - %w[DN1S B2 DN3U B1 1.50 21.43], - %w[DN1S A3 DN3U A1 1.00 21.43], - %w[DN1S B3 DN3U B1 0.90 21.43], - %w[DN2T C1 DN3U A1 3.00 21.43], - %w[DN2T D1 DN3U B1 2.25 21.43], - %w[DN2T C2 DN3U A1 1.29 21.43], - %w[DN2T D2 DN3U B1 1.12 21.43], - %w[DN2T C3 DN3U A1 0.82 21.43], - %w[DN2T D3 DN3U B1 0.75 21.43] + %w[DN1S A1 DN3U A1 60.0 14.3], + %w[DN1S B1 DN3U B1 30.0 14.3], + %w[DN1S A2 DN3U A1 12.0 14.3], + %w[DN1S B2 DN3U B1 10.0 14.3], + %w[DN1S A3 DN3U A1 6.7 14.3], + %w[DN1S B3 DN3U B1 6.0 14.3], + %w[DN2T C1 DN3U A1 20.0 14.3], + %w[DN2T D1 DN3U B1 15.0 14.3], + %w[DN2T C2 DN3U A1 8.6 14.3], + %w[DN2T D2 DN3U B1 7.5 14.3], + %w[DN2T C3 DN3U A1 5.5 14.3], + %w[DN2T D3 DN3U B1 5.0 14.3] ] end it 'renders the csv' do diff --git a/spec/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb_spec.rb b/spec/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb_spec.rb index ec8bb3fd4..802d79aa7 100644 --- a/spec/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb_spec.rb +++ b/spec/views/exports/hamilton_lrc_pbmc_pools_to_cellaca_count.csv.erb_spec.rb @@ -7,18 +7,18 @@ let(:wells) do # 8 because of the Pools plate. - (1..8).map do |index| # one-based index + (1..8).map do |index| # one-based index aliquots = [] # Initiate 10 aliquots per each well (1..10).each do |_i| supplier_name = "vac-tube-barcode-#{index}" - sample_metadata = create(:v2_sample_metadata, supplier_name: supplier_name) - sample = create(:v2_sample, sample_metadata: sample_metadata) - aliquots << create(:v2_aliquot, sample: sample) + sample_metadata = create(:v2_sample_metadata, supplier_name:) + sample = create(:v2_sample, sample_metadata:) + aliquots << create(:v2_aliquot, sample:) end location = WellHelpers.well_at_column_index(index - 1) - create(:v2_well, aliquots: aliquots, location: location) + create(:v2_well, aliquots:, location:) end end @@ -31,7 +31,7 @@ wells[2].state = 'failed' wells[3].state = 'failed' - create(:v2_plate, wells: wells) + create(:v2_plate, wells:) end let(:required_number_of_cells) { 30_000 } @@ -43,9 +43,9 @@ plate.purpose.uuid => { presenter_class: { args: { - required_number_of_cells: required_number_of_cells, - wastage_factor: wastage_factor, - desired_chip_loading_concentration: desired_chip_loading_concentration + required_number_of_cells:, + wastage_factor:, + desired_chip_loading_concentration: } } } @@ -58,14 +58,14 @@ header = [['Workflow', workflow], [], ['Plate Barcode', 'Well Position', 'Well Name', 'Source Well Volume']] body = # 8 wells - first two wells (empty + failed) - (5..8).map do |index| # one-based index + (5..8).map do |index| # one-based index well = plate.wells_in_columns[index - 1] [ plate.labware_barcode.human, well.location, well.name, format( - '%0.2f', + '%0.1f', ((well.aliquots.size * required_number_of_cells * wastage_factor) / desired_chip_loading_concentration) ) ] diff --git a/spec/views/exports/pbmc_bank_tubes_content_report.csv.erb_spec.rb b/spec/views/exports/pbmc_bank_tubes_content_report.csv.erb_spec.rb index 60240d5a4..bb9aca6fa 100644 --- a/spec/views/exports/pbmc_bank_tubes_content_report.csv.erb_spec.rb +++ b/spec/views/exports/pbmc_bank_tubes_content_report.csv.erb_spec.rb @@ -42,9 +42,9 @@ let(:src_aliquot3_s2) { create(:v2_aliquot, sample: sample2, study: study) } # qc results - let(:live_cell_count_qc) { create(:qc_result, key: 'live_cell_count', value: '20000', units: 'cells/ml') } + let(:total_cell_count_qc) { create(:qc_result, key: 'total_cell_count', value: '20000', units: 'cells/ml') } let(:viability_qc) { create(:qc_result, key: 'viability', value: '75', units: '%') } - let(:qc_results) { [live_cell_count_qc, viability_qc] } + let(:qc_results) { [total_cell_count_qc, viability_qc] } # source wells let(:source_well_attributes) do @@ -200,7 +200,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', @@ -221,24 +221,16 @@ assign(:workflow, workflow_name) # stub the v2 child tube lookups - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube1.barcode.machine) - .and_return(dest_tube1) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube2.barcode.machine) - .and_return(dest_tube2) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube3.barcode.machine) - .and_return(dest_tube3) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube4.barcode.machine) - .and_return(dest_tube4) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube5.barcode.machine) - .and_return(dest_tube5) - allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes) - .with('custom_metadatum_collection', nil, barcode: dest_tube6.barcode.machine) - .and_return(dest_tube6) + custom_includes = 'custom_metadatum_collection' + dest_tubes = [dest_tube1, dest_tube2, dest_tube3, dest_tube4, dest_tube5, dest_tube6] + + dest_tubes.each do |dest_tube| + allow(Sequencescape::Api::V2).to receive(:tube_with_custom_includes).with( + custom_includes, + nil, + barcode: dest_tube.barcode.machine + ).and_return(dest_tube) + end end it 'renders the expected content row by row' do @@ -247,8 +239,8 @@ context 'when some data is missing' do # qc results, no viability_qc - let(:live_cell_count_qc) { create(:qc_result, key: 'live_cell_count', value: nil, units: 'cells/ml') } - let(:qc_results) { [live_cell_count_qc] } + let(:total_cell_count_qc) { create(:qc_result, key: 'total_cell_count', value: nil, units: 'cells/ml') } + let(:qc_results) { [total_cell_count_qc] } # expected file content let(:expected_content) do @@ -262,7 +254,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', @@ -302,7 +294,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', @@ -395,7 +387,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', @@ -490,7 +482,7 @@ 'FluidX barcode', 'Extraction and freeze date', 'Sequencing or contingency', - 'Cell count (cells/ml)', + 'Total cell count (cells/ml)', 'Viability (%)', 'Volume (µl)', 'Study name', diff --git a/yarn.lock b/yarn.lock index b1f910f91..9e8731f84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -615,12 +615,10 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== -"@prettier/plugin-ruby@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@prettier/plugin-ruby/-/plugin-ruby-2.1.0.tgz#2df48c1c004fc9dec18a72f441d43d54137b25a6" - integrity sha512-lAoYFoDnwlxM3jl+dS7yrmxD49d3nbKFTBuhHx3VTPoAwmOOKOIO4nRJTTBWF+rS7KUAVn2XPLwRR0Obh/KW6A== - dependencies: - prettier ">=2.3.0" +"@prettier/plugin-ruby@^4.0.0": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@prettier/plugin-ruby/-/plugin-ruby-4.0.4.tgz#73d85fc2a1731a3f62b57ac3116cf1c234027cb6" + integrity sha512-lCpvfS/dQU5WrwN3AQ5vR8qrvj2h5gE41X08NNzAAXvHdM4zwwGRcP2sHSxfu6n6No+ljWCVx95NvJPFTTjCTg== "@rollup/rollup-android-arm-eabi@4.22.4": version "4.22.4" @@ -2807,16 +2805,16 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@>=2.3.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.4.tgz#4723cadeac2ce7c9227de758e5ff9b14e075f283" - integrity sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ== - -"prettier@^1.18.2 || ^2.0.0", prettier@^2.8.8: +"prettier@^1.18.2 || ^2.0.0": version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + pretty@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5"