From 3296f1f47704d0bb7c373e0fd37bded22f96f8a4 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Thu, 12 Dec 2024 10:01:46 -0600 Subject: [PATCH 01/24] create new branch for test refactor --- test/system/projects/samples_test.rb | 1739 +++++++++++++++----------- 1 file changed, 1008 insertions(+), 731 deletions(-) diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index 86d3cff973..320a0668f9 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -11,8 +11,11 @@ class SamplesTest < ApplicationSystemTestCase login_as @user @sample1 = samples(:sample1) @sample2 = samples(:sample2) - @sample3 = samples(:sample30) + @sample30 = samples(:sample30) + @sample32 = samples(:sample32) @project = projects(:project1) + @project2 = projects(:project2) + @project29 = projects(:project29) @namespace = groups(:group_one) Project.reset_counters(@project.id, :samples_count) @@ -25,12 +28,172 @@ class SamplesTest < ApplicationSystemTestCase Searchkick.disable_callbacks end - test 'visiting the index' do + test 'samples index table' do + freeze_time visit namespace_project_samples_url(@namespace, @project) + + # verifies navigation to page assert_selector 'h1', text: I18n.t('projects.samples.index.title') - assert_selector '#samples-table table tbody tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name + + # samples table + within('#samples-table table') do + # headers + within('thead tr:first-child') do + assert_selector 'th:first-child', text: I18n.t('samples.table_component.puid').upcase + assert_selector 'th:nth-child(2)', text: I18n.t('samples.table_component.name').upcase + assert_selector 'th:nth-child(3)', text: I18n.t('samples.table_component.created_at').upcase + assert_selector 'th:nth-child(4)', text: I18n.t('samples.table_component.updated_at').upcase + assert_selector 'th:nth-child(5)', text: I18n.t('samples.table_component.attachments_updated_at').upcase + assert_selector 'th:last-child', text: I18n.t('samples.table_component.action').upcase + end + within('tbody') do + # rows + assert_selector '#samples-table table tbody tr', count: 3 + # row contents + within("tr[id='#{@sample1.id}']") do + assert_selector 'th:first-child', text: @sample1.puid + assert_selector 'td:nth-child(2)', text: @sample1.name + assert_selector 'td:nth-child(3)', text: I18n.l(@sample1.created_at.localtime, format: :full_date) + # assert_selector 'td:nth-child(4)', text: "yesterday at #{Time.now.strftime('%-I:%M%P')}" + assert_selector 'td:nth-child(5)', text: '2 hours ago' + # actions tested by role in separate test + end + end + end + + # pagy + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + end + + test 'edit and delete row actions render for user with role == Owner in samples table' do + visit namespace_project_samples_url(@namespace, @project) + + within("tr[id='#{@sample1.id}'] td:last-child") do + assert_selector 'a', text: I18n.t('projects.samples.index.edit_button') + assert_selector 'a', text: I18n.t('projects.samples.index.remove_button') + end + end + + test 'edit row action render for user with role == Maintainer in samples table' do + login_as users(:joan_doe) + visit namespace_project_samples_url(@namespace, @project) + + within("tr[id='#{@sample1.id}'] td:last-child") do + assert_selector 'a', text: I18n.t('projects.samples.index.edit_button') + assert_no_selector 'a', text: I18n.t('projects.samples.index.remove_button') + end + end + + test 'no row actions for user with role < Maintainer in samples table' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + within('#samples-table table thead tr:first-child') do + # attachments updated at is the last column, action column does not exist + assert_selector 'th:last-child', text: I18n.t('samples.table_component.attachments_updated_at').upcase + assert_no_selector 'th:last-child', text: I18n.t('samples.table_component.action').upcase + end + within("tr[id='#{@sample1.id}'] td:last-child") do + assert_no_selector 'a', text: I18n.t('projects.samples.index.edit_button') + assert_no_selector 'a', text: I18n.t('projects.samples.index.remove_button') + end + end + + test 'User with role >= Maintainer sees select and deselect buttons for samples table' do + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'form#select-all-form' + assert_selector 'form#deselect-all-form' + end + + test 'User with role < Maintainer does not see select and deselect buttons for samples table' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'form#select-all-form' + assert_no_selector 'form#deselect-all-form' + end + + test 'User with role >= Maintainer sees sample table checkboxes' do + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'input#select-page' + assert_selector "input#sample_#{@sample1.id}" + end + + test 'User with role < Maintainer does not see sample table checkboxes' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'input#select-page' + assert_no_selector "input#sample_#{@sample1.id}" + end + + test 'User with role >= Analyst sees workflow execution link in samples index' do + login_as users(:james_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') + end + + test 'User with role < Analyst does not see workflow execution link in samples index' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') + end + + test 'User with role >= Analyst sees create export button in samples index' do + login_as users(:james_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') + end + + test 'User with role < Analyst does not see create export button in samples index' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') + end + + test 'User with role >= Maintainer sees import metadata link in samples index' do + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') + end + + test 'User with role < Maintainer does not see import metadata link in samples index' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') + end + + test 'User with role >= Maintainer sees new sample button in samples index' do + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'a', text: I18n.t('projects.samples.index.new_button') + end + + test 'User with role < Maintainer does not see new sample button in samples index' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'a', text: I18n.t('projects.samples.index.new_button') + end + + test 'User with role >= Maintainer sees delete samples button in samples index' do + visit namespace_project_samples_url(@namespace, @project) + + assert_selector 'a', text: I18n.t('projects.samples.index.delete_samples_button') + end + + test 'User with role < Maintainer does not see delete samples button in samples index' do + login_as users(:ryan_doe) + visit namespace_project_samples_url(@namespace, @project) + + assert_no_selector 'a', text: I18n.t('projects.samples.index.delete_samples_button') end test 'cannot access project samples' do @@ -42,285 +205,297 @@ class SamplesTest < ApplicationSystemTestCase end test 'should create sample' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - assert_selector 'a', text: I18n.t('projects.samples.index.new_button'), count: 1 + ### setup end ### + + ### actions start ### + # launch dialog click_on I18n.t('projects.samples.index.new_button') - fill_in I18n.t('activerecord.attributes.sample.description'), with: @sample1.description + # fill new sample fields + fill_in I18n.t('activerecord.attributes.sample.description'), with: 'A sample description' fill_in I18n.t('activerecord.attributes.sample.name'), with: 'New Name' click_on I18n.t('projects.samples.new.submit_button') + ### actions end ### + ### results start ### + # flash msg assert_text I18n.t('projects.samples.create.success') - assert_text 'New Name' - assert_text @sample1.description + # verify redirect to sample show page after successful sample creation + assert_selector 'h1', text: 'New Name' + # verify sample exists in table + visit namespace_project_samples_url(@namespace, @project) + within('#samples-table table tbody') do + assert_text 'New Name' + end + ### results end ### end test 'should update Sample' do + ### setup start ### visit namespace_project_sample_url(@namespace, @project, @sample1) - assert_selector 'a', text: I18n.t('projects.samples.show.edit_button'), count: 1 - click_on I18n.t('projects.samples.show.edit_button'), match: :first + ### setup end ### - fill_in 'Description', with: @sample1.description + ### actions start ### + # nav to edit sample page + click_on I18n.t('projects.samples.show.edit_button') + + # change current sample properties with new ones + fill_in 'Description', with: 'A new description' fill_in 'Name', with: 'New Sample Name' click_on I18n.t('projects.samples.edit.submit_button') + ### actions end ### + ### results start ### + # flash msg assert_text I18n.t('projects.samples.update.success') - assert_text 'New Sample Name' - assert_text @sample1.description + + # verify redirect to sample show page and updated sample state + assert_selector 'h1', text: 'New Sample Name' + assert_text 'A new description' + ### results end ### end test 'should destroy Sample from sample show page' do + ### setup start ### + # nav to samples index and verify sample exists within table + visit namespace_project_samples_url(@namespace, @project) + assert_selector "#samples-table table tbody tr[id='#{@sample1.id}']" + assert_selector '#samples-table table tbody tr', count: 3 + + # nav to sample show visit namespace_project_sample_url(@namespace, @project, @sample1) - assert_link text: I18n.t('projects.samples.index.remove_button'), count: 1 + ### setup end ### + + ### actions start ## click_link I18n.t(:'projects.samples.index.remove_button') within('#turbo-confirm[open]') do click_button I18n.t(:'components.confirmation.confirm') end + ### actions end ### + ### verify start ### + # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) - - assert_no_selector '#samples-table table tbody tr', text: @sample1.name + # deleted sample row no longer exists + assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" + # redirected to samples index assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 + # remaining samples still appear on table assert_selector '#samples-table table tbody tr', count: 2 - within('tbody tr:first-child th') do - assert_text @sample2.puid - end + ### verify end ### end test 'should destroy Sample from sample listing page' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - table_row = find(:table_row, [@sample1.name]) - - within table_row do - click_link 'Remove' + ### setup end ### + within("tr[id='#{@sample1.id}']") do + click_link I18n.t('projects.samples.index.remove_button') end - within('dialog') do + within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_deletion_dialog.description', sample_name: @sample1.name) click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end + ### setup end ### + ### verify start ### + # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) - - assert_no_selector '#samples-table table tbody tr', text: @sample1.puid - assert_no_selector '#samples-table table tbody tr', text: @sample1.name + # sample no longer exists + assert_no_selector "tr[id='#{@sample1.id}']" + # still on samples index page assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 + # remaining samples still in table assert_selector '#samples-table table tbody tr', count: 2 - within('#samples-table table tbody tr:first-child th') do - assert_text @sample2.puid - end + ### verify end ### end - test 'should transfer multiple samples' do - project2 = projects(:project2) - visit namespace_project_samples_url(@namespace, @project) + test 'should transfer samples' do + ### setup start ### + # show destination project has 20 samples prior to transfer + visit namespace_project_samples_url(@namespace, @project2) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, + locale: @user.locale)) + # originating project has 3 samples prior to transfer + visit namespace_project_samples_url( + @namespace, @project + ) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - within '#samples-table table tbody' do - assert_selector 'tr', count: 3 + ### setup end ### + + ### actions start ### + samples = @project.samples.pluck(:puid, :name) + within('#samples-table table tbody') do all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do + # verify 'plural' form of description renders assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', '3') + # verify sample puid and name are listed in dialog list within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) samples.each do |sample| assert_text sample[0] assert_text sample[1] end end + # select destination project find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end + ### actions end ### + + ### verify start ### + # flash msg + assert_text I18n.t('projects.samples.transfers.create.success') + # originating project no longer has samples + assert_text I18n.t('projects.samples.index.no_samples') + + visit namespace_project_samples_url(@namespace, @project2) + within '#samples-table table tbody' do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + ### verify end ### end - test 'should transfer a single sample' do - project2 = projects(:project2) + test 'transfer dialog with single sample' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type="checkbox"]')[0].click end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.transfer_button') + ### actions end ### + + ### verify start ### + within('#dialog') do assert_text I18n.t('projects.samples.transfers.dialog.description.singular') - within %(turbo-frame[id="list_selections"]) do - assert_text @sample1.name - end - find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click - click_on I18n.t('projects.samples.transfers.dialog.submit_button') end + ### verify end ### end test 'should not transfer samples with session storage cleared' do - project2 = projects(:project2) + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end Capybara.execute_script 'sessionStorage.clear()' - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do - assert_no_selector "turbo-frame[id='list_selections']" + ### actions end ### + + ### verify start ### + # samples listing should no longer appear in dialog + assert_no_selector '#list_selections' + # error msg displayed in dialog assert_text I18n.t('projects.samples.transfers.create.no_samples_transferred_error') - errors = @project.errors.full_messages_for(:samples) - errors.each { |error| assert_text error } end + ### verify end ### end - test 'should not transfer samples' do - project26 = projects(:project26) - sample30 = samples(:sample30) - visit namespace_project_samples_url(@namespace, @project) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - check sample30.name - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - assert_text sample30.name - assert_text sample30.puid - end - find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project26.full_path}']").click - click_on I18n.t('projects.samples.transfers.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do - assert_no_selector "turbo-frame[id='list_selections']" - assert_text I18n.t('projects.samples.transfers.create.error') - errors = @project.errors.full_messages_for(:samples) - errors.each { |error| assert_text error } - end - end + test 'transfer samples with and without same name in destination project' do + # only samples without a matching name will transfer - test 'should transfer some samples' do + ### setup start ### + namespace = groups(:subgroup1) project25 = projects(:project25) + + # verify only 2 samples exist in destination project + visit namespace_project_samples_url(namespace, project25) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 2, count: 2, + locale: @user.locale)) visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end + all('input[type=checkbox]').each do |checkbox| + checkbox.click unless checkbox.checked? end + end + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - within %(turbo-frame[id="samples_dialog"]) do - assert_no_selector "turbo-frame[id='list_selections']" + ### actions end ### + + ### verify start ### + within('#dialog') do + # error messages in dialog assert_text I18n.t('projects.samples.transfers.create.error') - errors = @project.errors.full_messages_for(:samples) - errors.each { |error| assert_text error } + # colon is removed from translation in UI + assert_text I18n.t('services.samples.transfer.sample_exists', sample_puid: @sample30.puid, + sample_name: @sample30.name).gsub(':', '') end - end - test 'should transfer samples for maintainer within hierarchy' do - user = users(:joan_doe) - login_as user - project2 = projects(:project2) - visit namespace_project_samples_url(namespace_id: @namespace.path, project_id: @project.path) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + # verify sample1 and 2 transferred, sample 30 did not + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) + assert_no_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + + # destination project + visit namespace_project_samples_url(namespace, project25) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 4, count: 4, locale: @user.locale)) - within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click - click_on I18n.t('projects.samples.transfers.dialog.submit_button') - end + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + ### verify end ### end test 'sample transfer project listing should be empty for maintainer if no other projects in hierarchy' do - user = users(:user28) - login_as user + ### setup start ### + login_as users(:user28) namespace = groups(:group_hotel) - project2 = projects(:projectHotel) - Project.reset_counters(project2.id, :samples_count) - visit namespace_project_samples_url(namespace, project2) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - within '#samples-table table tbody' do - assert_selector 'tr', count: 1 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = project2.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - assert_no_selector 'option' - end - end - - test 'should not transfer samples for maintainer outside of hierarchy' do - user = users(:joan_doe) - login_as user + project = projects(:projectHotel) + visit namespace_project_samples_url(namespace, project) + ### setup end ### - # Project is a part of Group 8 and not a part of the current project hierarchy - project32 = projects(:project32) - visit namespace_project_samples_url(namespace_id: @namespace.path, project_id: @project.path) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: user.locale)) + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - find('input#select2-input').click - assert_no_selector "button[data-viral--select2-primary-param='#{project32.full_path}']" + click_link I18n.t('projects.samples.index.transfer_button') + ### actions end ### + + ### verify start ### + within('#dialog') do + # no available destination projects + assert_selector "input[placeholder='#{I18n.t('projects.samples.transfers.dialog.no_available_projects')}']" end + ### verify end ### end test 'should update pagination & selection during transfer samples' do @@ -331,8 +506,6 @@ class SamplesTest < ApplicationSystemTestCase samples = [samples(:bulk_sample1), samples(:bulk_sample2)] Project.reset_counters(project38.id, :samples_count) - Project.reset_counters(project2.id, :samples_count) - visit namespace_project_samples_url(namespace17, project38) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 200, locale: @user.locale)) @@ -362,11 +535,10 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - assert_text I18n.t('projects.samples.transfers.create.success') - # Check samples selected are [] and has the proper number of samples assert_text I18n.t(:'projects.samples.index.no_samples') + Project.reset_counters(project2.id, :samples_count) visit namespace_project_samples_url(namespace1, project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 220, @@ -383,845 +555,972 @@ class SamplesTest < ApplicationSystemTestCase end test 'empty state of transfer sample project selection' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - find('input#select2-input').fill_in with: 'invalid project name or puid' - assert_text I18n.t('projects.samples.transfers.dialog.empty_state') - end - end + ### setup end ### - test 'no available destination projects to transfer samples' do - sign_in users(:jean_doe) - namespace = namespaces_user_namespaces(:john_doe_namespace) - project = projects(:john_doe_project2) - Project.reset_counters(project.id, :samples_count) - visit namespace_project_samples_url(namespace, project) + ### actions start ### within '#samples-table table tbody' do + # check samples all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - assert_selector "input[placeholder='#{I18n.t('projects.samples.transfers.dialog.no_available_projects')}']" - end - end - - test 'user with maintainer access should be able to see the transfer samples button' do - user = users(:joan_doe) - login_as user - - visit namespace_project_samples_url(@namespace, @project) - - assert_selector 'a', text: I18n.t('projects.samples.index.transfer_button'), count: 1 - end - test 'user with guest access should not be able to see the transfer samples button' do - user = users(:ryan_doe) - login_as user - - visit namespace_project_samples_url(@namespace, @project) - - assert_selector 'a', text: I18n.t('projects.samples.index.transfer_button'), count: 0 - end - - test 'user should not be able to see the edit button for the sample' do - user = users(:ryan_doe) - login_as user - - visit namespace_project_sample_url(@namespace, @project, @sample1) - - assert_selector 'a', text: I18n.t('projects.samples.show.edit_button'), count: 0 - end - - test 'user should not be able to see the remove button for the sample' do - user = users(:ryan_doe) - login_as user - - visit namespace_project_sample_url(@namespace, @project, @sample1) + # launch dialog + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do + # fill destination input + find('input#select2-input').fill_in with: 'invalid project name or puid' + ### actions end ### - assert_selector 'a', text: I18n.t('projects.samples.index.remove_button'), count: 0 + ### verify start ### + assert_text I18n.t('projects.samples.transfers.dialog.empty_state') + ### verify end ### + end end - test 'visiting the index should not allow the current user only edit action' do - user = users(:joan_doe) - login_as user - + test 'can search the list of samples by name' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + # partial name search + filter_text = @sample1.name[-3..-1] - assert_selector 'a', text: I18n.t('projects.samples.index.new_button'), count: 1 - assert_selector 'h1', text: I18n.t('projects.samples.index.title') assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: user.locale)) + locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 3 - within('tbody tr:first-child') do - assert_selector 'a', text: 'Edit', count: 1 - assert_selector 'a', text: 'Remove', count: 0 - end - assert_text @sample1.name - assert_text @sample2.name - end + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### - test 'visiting the index should not allow the current user any modification actions' do - user = users(:ryan_doe) - login_as user + ### actions start ### + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text + find('input.t-search-component').native.send_keys(:return) + ### actions end ### + ### verify start ### + # verify table only contains sample1 + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) + assert_selector '#samples-table table tbody tr', count: 1 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + ### verify end ### + end + + test 'can search the list of samples by metadata field and value presence when metadata is toggled' do + # also tests that metadata toggle persist through other actions (filter) and page refresh + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + filter_text = 'metadatafield1:value1' - assert_selector 'a', text: I18n.t('projects.samples.index.new_button'), count: 0 - assert_selector 'h1', text: I18n.t('projects.samples.index.title') assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: user.locale)) + locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 3 - assert_selector 'a', text: 'Edit', count: 0 - assert_selector 'a', text: 'Remove', count: 0 - assert_text @sample1.name - assert_text @sample2.name - end - - test 'can search the list of samples by name' do - visit namespace_project_samples_url(@namespace, @project) - filter_text = samples(:sample1).name[-3..-1] + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### + ### actions and verify start ### + # toggle metadata on + find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click + # verify all 3 samples are still in table assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name + # verify metadata fields are now present + assert_selector '#samples-table table thead tr th', count: 8 + # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) + # verify table only has sample30 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 1 - assert_selector 'mark', text: filter_text - assert_no_text @sample2.name - assert_no_text @sample3.name - - # Refresh the page to ensure the search is still active - visit namespace_project_samples_url(@namespace, @project) + assert_no_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_selector 'mark', text: filter_text - assert_no_text @sample2.name - assert_no_text @sample3.name + # verify filter input persists + assert_selector %(input.t-search-component) do |input| + assert_equal filter_text, input['value'] + end + ### actions and verify end ### end - test 'can change pagination and then filter by name' do - visit namespace_project_samples_url(@namespace, @project) + test 'can change limit/pagination and then filter by id' do + # tests limit change and that it persists through other actions (filter) + ### setup start ### + sample3 = samples(:sample3) + visit namespace_project_samples_url(@namespace, @project2) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, + locale: @user.locale)) + ### setup end ### + ### actions and verify start ### within('div#limit-component') do + # set table limit to 10 find('button').click click_link '10' end + # verify limit is set to 10 assert_selector 'div#limit-component button div span', text: '10' - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 10, count: 20, locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name + # verify table consists of 10 samples per page + assert_selector '#samples-table table tbody tr', count: 10 - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: sample3.puid find('input.t-search-component').native.send_keys(:return) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector 'table tbody tr', count: 1 - assert_text @sample1.name - assert_no_text @sample2.name - assert_selector 'div#limit-component button div span', text: '10' + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) + assert_selector '#samples-table table tbody tr', count: 1 + assert_selector "tr[id='#{sample3.id}']" + ### actions and verify end ### end - test 'can change pagination and then toggle metadata' do + test 'filter highlighting for sample name' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + ### setup end ### - within('div#limit-component') do - find('button').click - click_link '10' - end + ### actions start ### + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' + find('input.t-search-component').native.send_keys(:return) + ### actions end ### - assert_selector 'div#limit-component button div span', text: '10' + ### verify start ### + # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - assert_selector '#samples-table table thead tr th', count: 6 - - assert_selector 'label', text: I18n.t('projects.samples.shared.metadata_toggle.label'), count: 1 - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click + # checks highlighting + assert_selector 'mark', text: 'Sample', count: 3 + end + test 'filter highlighting for sample puid' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - assert_selector '#samples-table table thead tr th', count: 8 - assert_selector 'div#limit-component button div span', text: '10' + ### setup end ### + + ### actions start ### + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid + find('input.t-search-component').native.send_keys(:return) + ### actions end ### + + ### verify start ### + # verify table only contains sample1 + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, + locale: @user.locale)) + # checks highlighting + assert_selector 'mark', text: @sample1.puid end - test 'can sort samples by column' do + test 'can sort samples' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 + ### setup end ### + + ### action and verify start ### within('tbody tr:first-child th') do assert_text @sample1.puid end - - click_on 'Sample ID' - - assert_selector 'table thead th:first-child svg.icon-arrow_up' - puids = retrieve_puids - (puids.length - 1).times do |n| - assert puids[n] < puids[n + 1] - end - - click_on 'Sample ID' - assert_selector 'table thead th:first-child svg.icon-arrow_down' - puids = retrieve_puids - (puids.length - 1).times do |n| - assert puids[n] > puids[n + 1] - end - - click_on 'Sample Name' + click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - assert_selector '#samples-table table tbody tr', count: 3 within('#samples-table table tbody') do assert_selector 'tr:first-child th', text: @sample1.puid assert_selector 'tr:first-child td:nth-child(2)', text: @sample1.name assert_selector 'tr:nth-child(2) th', text: @sample2.puid assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample3.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample3.name + assert_selector 'tr:last-child th', text: @sample30.puid + assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name end - click_on 'Sample Name' + click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - assert_selector '#samples-table table tbody tr', count: 3 within('#samples-table table tbody') do - assert_selector 'tr:first-child th', text: @sample3.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample3.name + assert_selector 'tr:first-child th', text: @sample30.puid + assert_selector 'tr:first-child td:nth-child(2)', text: @sample30.name assert_selector 'tr:nth-child(2) th', text: @sample2.puid assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end + ### action and verify end ### + end + + test 'sort samples attachments_updated_at_nulls_last' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) - click_on 'Created' + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + ### setup end ### - assert_selector 'table thead th:nth-child(3) svg.icon-arrow_up' - within('#samples-table table tbody') do - assert_selector 'tr:first-child th', text: @sample3.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample3.name - assert_selector 'tr:nth-child(2) th', text: @sample2.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample1.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name + ### action and verify start ### + within('tbody tr:first-child th') do + assert_text @sample1.puid end + click_on I18n.t('samples.table_component.attachments_updated_at') - click_on 'Created' - - assert_selector 'table thead th:nth-child(3) svg.icon-arrow_down' + assert_selector 'table thead th:nth-child(5) svg.icon-arrow_up' within('#samples-table table tbody') do assert_selector 'tr:first-child th', text: @sample1.puid assert_selector 'tr:first-child td:nth-child(2)', text: @sample1.name assert_selector 'tr:nth-child(2) th', text: @sample2.puid assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample3.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample3.name + assert_selector 'tr:last-child th', text: @sample30.puid + assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name end - click_on 'Last Updated' + click_on I18n.t('samples.table_component.attachments_updated_at') - assert_selector 'table thead th:nth-child(4) svg.icon-arrow_up' - within('#samples-table table tbody') do - assert_selector 'tr:first-child th', text: @sample3.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample3.name - assert_selector 'tr:nth-child(2) th', text: @sample2.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample1.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name - end - - click_on 'Last Updated' - - assert_selector 'table thead th:nth-child(4) svg.icon-arrow_down' + assert_selector 'table thead th:nth-child(5) svg.icon-arrow_down' within('#samples-table table tbody') do + # order does not change as sample1 is the only sample with attachments_updated_at assert_selector 'tr:first-child th', text: @sample1.puid assert_selector 'tr:first-child td:nth-child(2)', text: @sample1.name assert_selector 'tr:nth-child(2) th', text: @sample2.puid assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample3.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample3.name + assert_selector 'tr:last-child th', text: @sample30.puid + assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name end + ### action and verify end ### end test 'can filter and then sort the list of samples by name' do + # tests that filter persists through other actions (sort) + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child td:nth-child(2)') do - assert_text @sample1.name - end - - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: samples(:sample1).name - find('input.t-search-component').native.send_keys(:return) - - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_text @sample1.puid - assert_text @sample1.name - assert_no_text @sample2.name - assert_no_text @sample3.name - - click_on 'Sample Name' - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - - assert_selector '#samples-table table tbody tr', count: 1 - within('#samples-table table tbody tr td:nth-child(2)') do - assert_text @sample1.name - end - end - - test 'can filter and then sort the list of samples by puid' do - visit namespace_project_samples_url(@namespace, @project) - - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child th') do - assert_text @sample1.puid - end - - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid + ### actions start ### + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_text @sample1.puid - assert_text @sample1.name - assert_no_text @sample2.name - assert_no_text @sample3.name - - click_on 'Sample ID' - assert_selector 'table thead th:first-child svg.icon-arrow_up' - - assert_selector '#samples-table table tbody tr', count: 1 - within('#samples-table table tbody tr th') do - assert_text @sample1.puid - end - - visit namespace_project_samples_url(@namespace, @project) - - assert_selector '#samples-table table tbody tr', count: 1 - within('tbody tr th') do - assert_text @sample1.puid - end - end - - test 'can sort and then filter the list of samples by name' do - visit namespace_project_samples_url(@namespace, @project) + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child td:nth-child(2)') do - assert_text @sample1.name - end - - click_on 'Sample Name' + # apply sort + click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - click_on 'Sample Name' - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child td:nth-child(2)') do - assert_text @sample3.name - end + ### actions end ### - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: samples(:sample1).name - find('input.t-search-component').native.send_keys(:return) + ### verify start ### + # verify table still only contains sample1 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_text @sample1.puid - assert_text @sample1.name - assert_no_text @sample2.name - assert_no_text @sample3.name - - visit namespace_project_samples_url(@namespace, @project) - - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_text @sample1.puid - assert_text @sample1.name - assert_no_text @sample2.name - assert_no_text @sample3.name - end - - test 'can sort and then filter the list of samples by puid' do - visit namespace_project_samples_url(@namespace, @project) - - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child th') do - assert_text @sample1.puid + # verify filter text is still in filter input + assert_selector %(input.t-search-component) do |input| + assert_equal @sample1.name, input['value'] end + ### verify end ### + end - click_on 'Sample Name' + test 'can sort and then filter the list of samples by puid' do + # tests that sort persists through other actions (filter) + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### + + ### actions start ### + # apply sort + click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - click_on 'Sample Name' - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - - assert_selector '#samples-table table tbody tr', count: 3 - within('#samples-table table tbody tr:first-child th') do - assert_text @sample3.puid - end + # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid find('input.t-search-component').native.send_keys(:return) + ### actions end ### - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_text @sample1.puid - assert_text @sample1.name - assert_no_text @sample2.name - assert_no_text @sample3.name + ### verify start ### + # verify sort is still applied + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + # verify table only contains sample1 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + ### verify end ### end - test 'should be able to toggle metadata' do + test 'filter persists through page refresh' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + filter_text = @sample1.name + ### setup end ### - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table thead tr th', count: 6 + ### actions start ### + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text + find('input.t-search-component').native.send_keys(:return) + ### actions end ### - click_on 'Last Updated' - assert_selector 'table thead th:nth-child(4) svg.icon-arrow_up' + ### verify start ### + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" - assert_selector 'label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label'), count: 1 - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click + # refresh + visit namespace_project_samples_url(@namespace, @project) - assert_selector '#samples-table table thead tr th', count: 8 - within('#samples-table table tbody tr:first-child') do - assert_text @sample3.name - assert_selector 'td:nth-child(6)', text: 'value1' - assert_selector 'td:nth-child(7)', text: 'value2' + # verify filter is still in input field + assert_selector %(input.t-search-component) do |input| + assert_equal filter_text, input['value'] end - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click - assert_selector '#samples-table table thead tr th', count: 6 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + ### verify end ### end - test 'can sort samples by metadata column' do + test 'sort persists through page refresh' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - assert_selector 'label', text: I18n.t('projects.samples.shared.metadata_toggle.label'), count: 1 - assert_selector '#samples-table table thead tr th', count: 6 - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click - assert_selector '#samples-table table thead tr th', count: 8 - - within 'div.overflow-auto' do |div| - div.scroll_to div.find('table thead th:nth-child(7)') - end + ### setup end ### - click_on 'metadatafield1' - - assert_selector 'table thead th:nth-child(6) svg.icon-arrow_up' - assert_selector '#samples-table table tbody tr', count: 3 - within('tbody') do - assert_selector 'tr:first-child th', text: @sample3.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample3.name - assert_selector 'tr:nth-child(2) th', text: @sample1.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample1.name - assert_selector 'tr:last-child th', text: @sample2.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample2.name - end - - # toggling metadata again causes sort to be reset - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click - assert_selector '#samples-table table thead tr th', count: 6 + ### actions start ### + # apply sort + click_on I18n.t('samples.table_component.name') + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + assert_selector '#samples-table table tbody th:first-child', text: @sample1.puid + # change sort order from default sorting + click_on I18n.t('samples.table_component.name') + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' + assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid + ### actions end ### - assert_selector 'table thead th:nth-child(4) svg.icon-arrow_down' - assert_selector '#samples-table table tbody tr', count: 3 - within('tbody') do - assert_selector 'tr:first-child th', text: @sample1.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample1.name - assert_selector 'tr:nth-child(2) th', text: @sample2.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample3.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample3.name - end - end + ### verify start ### - test 'should not import metadata' do - login_as users(:ryan_doe) + # refresh visit namespace_project_samples_url(@namespace, @project) - assert_text I18n.t('projects.samples.index.import_metadata_button'), count: 0 + + # verify sort is still enabled + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' + # verify table ordering is still in changed/sorted state + assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid + ### verify end ### end test 'should import metadata via csv' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click + assert_selector '#samples-table table thead tr th', count: 8 + within('#samples-table table') do + within('thead') do + # metadatafield1 and 2 already exist, 3 does not and will be added by the import + assert_text 'METADATAFIELD1' + assert_text 'METADATAFIELD2' + assert_no_text 'METADATAFIELD3' + end + # sample 1 and 2 have no current value for metadatafield 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + end + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end + + # metadatafield3 added to header + assert_selector '#samples-table table thead tr th', count: 9 + within('#samples-table table') do + within('thead') do + assert_text 'METADATAFIELD3' + end + # sample 1 and 2 have no value current for metadatafield 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '10' + assert_selector 'td:nth-child(7)', text: '20' + assert_selector 'td:nth-child(8)', text: '30' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '15' + assert_selector 'td:nth-child(7)', text: '25' + assert_selector 'td:nth-child(8)', text: '35' + end + end + ### verify end ### end test 'should import metadata via xls' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click + assert_selector '#samples-table table thead tr th', count: 8 + within('#samples-table table') do + within('thead') do + # metadatafield 3 and 4 will be added by import + assert_no_text 'METADATAFIELD3' + assert_no_text 'METADATAFIELD4' + end + # sample 1 and 2 have no current value for metadatafield 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + end + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xls') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end + + # metadatafield3 and 4 added to header + assert_selector '#samples-table table thead tr th', count: 10 + within('#samples-table table') do + within('thead') do + assert_text 'METADATAFIELD3' + assert_text 'METADATAFIELD4' + end + # new metadata values for sample 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '10' + assert_selector 'td:nth-child(7)', text: '2024-01-04' + assert_selector 'td:nth-child(8)', text: 'true' + assert_selector 'td:nth-child(9)', text: 'A Test' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '15' + assert_selector 'td:nth-child(7)', text: '2024-12-31' + assert_selector 'td:nth-child(8)', text: 'false' + assert_selector 'td:nth-child(9)', text: 'Another Test' + end + end + ### verify end ### end test 'should import metadata via xlsx' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - + # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click assert_selector '#samples-table table thead tr th', count: 8 + within('#samples-table table') do + within('thead') do + # metadatafield 3 and 4 will be added by import + assert_no_text 'METADATAFIELD3' + assert_no_text 'METADATAFIELD4' + end + # sample 1 and 2 have no current value for metadatafield 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + end + ### setup end ### - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - - within('div[data-metadata--file-import-loaded-value="true"]') do + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xlsx') - find('#file_import_sample_id_column', wait: 2).find(:xpath, 'option[2]').select_option + find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end - assert_selector 'table thead tr th', count: 10 + # metadatafield3 and 4 added to header + assert_selector '#samples-table table thead tr th', count: 10 + within('#samples-table table') do + within('thead') do + assert_text 'METADATAFIELD3' + assert_text 'METADATAFIELD4' + end + # new metadata values for sample 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '10' + assert_selector 'td:nth-child(7)', text: '2024-01-04' + assert_selector 'td:nth-child(8)', text: 'true' + assert_selector 'td:nth-child(9)', text: 'A Test' + end + within("tr[id='#{@sample2.id}']") do + assert_selector 'td:nth-child(6)', text: '15' + assert_selector 'td:nth-child(7)', text: '2024-12-31' + assert_selector 'td:nth-child(8)', text: 'false' + assert_selector 'td:nth-child(9)', text: 'Another Test' + end + end + ### verify end ### end test 'should not import metadata via invalid file type' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/invalid.txt') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') end - within %(turbo-frame[id="import_metadata_dialog_alert"]) do + ### actions end ### + + ### verify start ### + within('#dialog') do assert_text I18n.t('services.samples.metadata.import_file.invalid_file_extension') end + ### verify end ### end test 'should import metadata with ignore empty values' do - namespace = groups(:subgroup_twelve_a) - project = projects(:project29) - sample = samples(:sample32) - visit namespace_project_samples_url(namespace, project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup start ### + visit namespace_project_samples_url(@subgroup12a, @project29) + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click + within("tr[id='#{@sample32.id}']") do + # value for metadatafield1, which is blank on the csv to import + assert_selector 'td:nth-child(6)', text: 'value1' + end + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option - check 'Ignore empty values' + find('input#file_import_ignore_empty_values').click click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end - visit namespace_project_sample_url(namespace, project, sample) - assert_text I18n.t('projects.samples.show.tabs.metadata') - click_on I18n.t('projects.samples.show.tabs.metadata') - within %(turbo-frame[id="table-listing"]) do - assert_text I18n.t('projects.samples.show.table_header.key').upcase - assert_selector 'table#metadata-table tbody tr', count: 3 - within('table#metadata-table tbody tr:first-child td:nth-child(2)') do - assert_text 'metadatafield1' - end - within('table#metadata-table tbody tr:first-child td:nth-child(3)') do - assert_text 'value1' - end + + within("tr[id='#{@sample32.id}']") do + # unchanged value + assert_selector 'td:nth-child(6)', text: 'value1' end + ### verify end ### end test 'should import metadata without ignore empty values' do - namespace = groups(:subgroup_twelve_a) - project = projects(:project29) - sample = samples(:sample32) - visit namespace_project_samples_url(namespace, project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup start ### + visit namespace_project_samples_url(@subgroup12a, @project29) + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click + within("tr[id='#{@sample32.id}']") do + # value for metadatafield1, which is blank on the csv to import + assert_selector 'td:nth-child(6)', text: 'value1' + end + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option - assert_not find_field('Ignore empty values').checked? + assert_not find('input#file_import_ignore_empty_values').checked? click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end - visit namespace_project_sample_url(namespace, project, sample) - assert_text I18n.t('projects.samples.show.tabs.metadata') - click_on I18n.t('projects.samples.show.tabs.metadata') - within %(turbo-frame[id="table-listing"]) do - assert_text I18n.t('projects.samples.show.table_header.key').upcase - assert_selector 'table#metadata-table tbody tr', count: 2 - assert_no_text 'metadatafield1' + within("tr[id='#{@sample32.id}']") do + # value is deleted for metadatafield1 + assert_selector 'td:nth-child(6)', text: '' end end test 'should not import metadata with duplicate header errors' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/duplicate_headers.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="import_metadata_dialog_alert"]) do + ### actions end ### + + ### verify start ### + # error msg assert_text I18n.t('services.samples.metadata.import_file.duplicate_column_names') + ### verify end ### end end test 'should not import metadata with missing metadata row errors' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_rows.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="import_metadata_dialog_alert"]) do + ### actions end ### + + ### verify start ### + # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_row') + ### verify end ### end end test 'should not import metadata with missing metadata column errors' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_columns.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="import_metadata_dialog_alert"]) do + ### actions end ### + + ### verify start ### + # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_column') + ### verify end ### end end test 'should partially import metadata with missing sample errors' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click assert_selector '#samples-table table thead tr th', count: 8 + within('#samples-table table') do + within('thead') do + # metadatafield1 and 2 already exist, 3 does not and will be added by the import + assert_text 'METADATAFIELD1' + assert_text 'METADATAFIELD2' + assert_no_text 'METADATAFIELD3' + end + # sample 1 has no current value for metadatafield 1 and 2 + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '' + assert_selector 'td:nth-child(7)', text: '' + end + end + ### setup end ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/mixed_project_samples.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do - assert_text I18n.t('shared.samples.metadata.file_imports.errors.description') + ### actions end ### + + ### verify start ### + assert_text I18n.t('services.samples.metadata.import_file.sample_not_found_within_project', + sample_puid: 'Project 2 Sample 3') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') end + + # metadata still imported assert_selector '#samples-table table thead tr th', count: 9 + within('#samples-table table') do + within('thead') do + assert_text 'METADATAFIELD3' + end + # sample 1 still imported even though sample3 (from import) does not exist + within("tr[id='#{@sample1.id}']") do + assert_selector 'td:nth-child(6)', text: '10' + assert_selector 'td:nth-child(7)', text: '20' + assert_selector 'td:nth-child(8)', text: '30' + end + end + ### verify end ### end test 'should not import metadata with analysis values' do + ### setup start ### subgroup12aa = groups(:subgroup_twelve_a_a) project31 = projects(:project31) - Project.reset_counters(project31.id, :samples_count) + sample34 = samples(:sample34) visit namespace_project_samples_url(subgroup12aa, project31) - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first - within('div[data-metadata--file-import-loaded-value="true"]') do + # toggle metadata on for samples table + find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click + # metadata not overwriting analysis values will still be added + assert_selector '#samples-table table thead tr th', count: 8 + within('#samples-table table thead') do + assert_no_text 'METADATAFIELD3' + end + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button') + within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_analysis_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do - assert_text I18n.t('shared.samples.metadata.file_imports.errors.description') + ### actions end ### + + ### verify start ### + assert_text I18n.t('services.samples.metadata.import_file.sample_metadata_fields_not_updated', + sample_name: sample34.name, metadata_fields: 'metadatafield1') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') end + # metadatafield3 still added + assert_selector '#samples-table table thead tr th', count: 9 + within('#samples-table table') do + within('thead') do + assert_text 'METADATAFIELD3' + end + # new metadata values for sample 1 and 2 + within("tr[id='#{sample34.id}']") do + assert_selector 'td:nth-child(8)', text: '20' + end + ### verify end ### + end end - test 'user with maintainer access should be able to see the clone samples button' do - user = users(:joan_doe) - login_as user - - visit namespace_project_samples_url(@namespace, @project) - - assert_selector 'a', text: I18n.t('projects.samples.index.clone_button'), count: 1 - end - - test 'user with guest access should not be able to see the clone samples button' do - user = users(:ryan_doe) - login_as user + test 'should clone samples' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project2) + # samples 1 and 2 do not exist in project2 + within('#samples-table table tbody') do + assert_no_text @sample1.name + assert_no_text @sample2.name + end visit namespace_project_samples_url(@namespace, @project) + ### setup end ### - assert_selector 'a', text: I18n.t('projects.samples.index.clone_button'), count: 0 - end - - test 'should clone multiple samples' do - project2 = projects(:project2) - visit namespace_project_samples_url(@namespace, @project) + ### actions start ### + # select samples 1 and 2 for cloning within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + find("input#sample_#{@sample1.id}").click + find("input#sample_#{@sample2.id}").click end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do + # plural dialog description since > 1 sample selected assert_text I18n.t( 'projects.samples.clones.dialog.description.plural' - ).gsub! 'COUNT_PLACEHOLDER', '3' - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end + ).gsub! 'COUNT_PLACEHOLDER', '2' + within('#list_selections') do + assert_text @sample1.puid + assert_text @sample1.name + assert_text @sample2.puid + assert_text @sample2.name end find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') end + ### actions end ### + + ### verify start ### + # flash msg assert_text I18n.t('projects.samples.clones.create.success') + # samples still exist within samples table of originating project + within('#samples-table table tbody') do + assert_text @sample1.name + assert_text @sample2.name + end + + # samples now exist in project2 samples table + visit namespace_project_samples_url(@namespace, @project2) + within('#samples-table table tbody') do + assert_text @sample1.name + assert_text @sample2.name + end + ### verify end ### end - test 'should clone single sample' do - project2 = projects(:project2) + test 'singular dialog description' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type="checkbox"]')[0].click end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.clone_button') + ### actions end ### + + ### verify start ### + within('#dialog') do assert_text I18n.t('projects.samples.clones.dialog.description.singular') - within %(turbo-frame[id="list_selections"]) do - assert_text @sample1.name - end - find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click - click_on I18n.t('projects.samples.clones.dialog.submit_button') end - assert_text I18n.t('projects.samples.clones.create.success') + ### verify end ### end test 'should not clone samples with session storage cleared' do - project2 = projects(:project2) + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end Capybara.execute_script 'sessionStorage.clear()' - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - end - within %(turbo-frame[id="samples_dialog"]) do + ### actions end ### + + ### verify start ### assert_no_selector "turbo-frame[id='list_selections']" assert_text I18n.t('projects.samples.clones.create.no_samples_cloned_error') - errors = project2.errors.full_messages_for(:base) - errors.each { |error| assert_text error } - click_on I18n.t('projects.samples.shared.errors.ok_button') + assert_text I18n.t('services.samples.clone.empty_sample_ids') + ### verify end ### end end test 'should not clone some samples' do + namespace = groups(:subgroup1) project25 = projects(:project25) + ### setup start ### + visit namespace_project_samples_url(namespace, project25) + # samples 1 and 2 do not exist in project25 samples table + within('#samples-table table tbody') do + assert_no_text @sample1.name + assert_no_text @sample2.name + end visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 + # check all samples. sample30 will error due to name collision in project25 all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') end + ### actions end ### + + ### verify start ### within %(turbo-frame[id="samples_dialog"]) do + # errors that a sample with the same name as sample30 already exists in project25 assert_text I18n.t('projects.samples.clones.create.error') - errors = @project.errors.full_messages_for(:samples) - errors.each { |error| assert_text error } + assert_text I18n.t('services.samples.clone.sample_exists', sample_puid: @sample30.puid, + sample_name: @sample30.name).gsub(':', '') click_on I18n.t('projects.samples.shared.errors.ok_button') end + + visit namespace_project_samples_url(namespace, project25) + # samples 1 and 2 still successfully clone + within('#samples-table table tbody') do + assert_text @sample1.name + assert_text @sample2.name + end + ### verify end ### end - test 'empty state of clone sample project selection' do + test 'empty state of destination project selection for sample cloning' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start #### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - within %(turbo-frame[id="list_selections"]) do - samples = @project.samples.pluck(:puid, :name) - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do find('input#select2-input').fill_in with: 'invalid project name or puid' + ### actions end ### + + ### verify start ### assert_text I18n.t('projects.samples.clones.dialog.empty_state') + ### verify end ### end end test 'no available destination projects to clone samples' do + ### setup start ### sign_in users(:jean_doe) - namespace = namespaces_user_namespaces(:john_doe_namespace) - project = projects(:john_doe_project2) - Project.reset_counters(project.id, :samples_count) - visit namespace_project_samples_url(namespace, project) + visit namespace_project_samples_url(namespaces_user_namespaces(:john_doe_namespace), projects(:john_doe_project2)) + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.clone_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + click_link I18n.t('projects.samples.index.clone_button') + ### actions end ### + + ### verify start ### + within('#dialog') do assert "input[placeholder='#{I18n.t('projects.samples.clones.dialog.no_available_projects')}']" end + ### verify end ### end test 'filtering samples by list of sample puids' do @@ -1379,35 +1678,13 @@ class SamplesTest < ApplicationSystemTestCase text: I18n.t('projects.samples.index.create_export_button.label') end - test 'action links are disabled when a group does not contain any projects with samples' do - login_as users(:empty_doe) - - visit group_samples_url(groups(:empty_group)) - - assert_no_button I18n.t(:'projects.samples.index.clone_button') - assert_no_button I18n.t(:'projects.samples.index.transfer_button') - assert_text I18n.t('projects.samples.index.create_export_button.label') - assert_selector 'button.pointer-events-none.cursor-not-allowed.bg-slate-100.text-slate-600', - text: I18n.t('projects.samples.index.create_export_button.label') - end - - def retrieve_puids - puids = [] - within('#samples-table table tbody') do - (1..3).each do |n| - puids << first("tr:nth-child(#{n}) th").text - end - end - puids - end - test 'delete multiple samples' do visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector 'tr', count: 3 assert_text @sample1.name assert_text @sample2.name - assert_text @sample3.name + assert_text @sample30.name all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end click_link I18n.t('projects.samples.index.delete_samples_button'), match: :first @@ -1420,8 +1697,8 @@ def retrieve_puids assert_text @sample1.puid assert_text @sample2.name assert_text @sample2.puid - assert_text @sample3.name - assert_text @sample3.puid + assert_text @sample30.name + assert_text @sample30.puid click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end @@ -1439,7 +1716,7 @@ def retrieve_puids assert_selector 'tr', count: 3 assert_text @sample1.name assert_text @sample2.name - assert_text @sample3.name + assert_text @sample30.name within 'tr:first-child' do all('input[type="checkbox"]')[0].click end @@ -1462,7 +1739,7 @@ def retrieve_puids assert_selector 'tr', count: 2 assert_no_text @sample1.name assert_text @sample2.name - assert_text @sample3.name + assert_text @sample30.name end end @@ -1472,7 +1749,7 @@ def retrieve_puids assert_selector 'tr', count: 3 assert_text @sample1.name assert_text @sample2.name - assert_text @sample3.name + assert_text @sample30.name all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end @@ -1482,7 +1759,7 @@ def retrieve_puids click_link I18n.t('projects.samples.index.remove_button') end - within 'dialog' do + within '#dialog' do click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end @@ -1502,7 +1779,7 @@ def retrieve_puids 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' ).gsub! 'COUNT_PLACEHOLDER', '2' assert_text @sample2.name - assert_text @sample3.name + assert_text @sample30.name assert_no_text @sample1.name click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end From d6e2370939cccee2e4059603927c4d08ed8d9e1a Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Thu, 12 Dec 2024 11:23:53 -0600 Subject: [PATCH 02/24] complete editing existing tests --- test/system/projects/samples_test.rb | 284 +++++++++++++++++---------- 1 file changed, 176 insertions(+), 108 deletions(-) diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index 320a0668f9..ff3f4d1487 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -1523,108 +1523,108 @@ class SamplesTest < ApplicationSystemTestCase ### verify end ### end - test 'filtering samples by list of sample puids' do - visit namespace_project_samples_url(@namespace, @project) - within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - assert_selector 'tr th', text: @sample1.puid - assert_selector 'tr th', text: @sample2.puid - end - click_button I18n.t(:'components.list_filter.title') - within '#list-filter-dialog' do - assert_selector 'h1', text: I18n.t(:'components.list_filter.title') - fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.puid}, #{@sample2.puid}" - assert_selector 'span.label', count: 1 - assert_selector 'span.label', text: @sample1.puid - find("input[name='q[name_or_puid_in][]']").text @sample2.puid - click_button I18n.t(:'components.list_filter.apply') - end - within '#samples-table table tbody' do - assert_selector 'tr', count: 2 - end - click_button I18n.t(:'components.list_filter.title') - within '#list-filter-dialog' do - assert_selector 'h1', text: I18n.t(:'components.list_filter.title') - click_button I18n.t(:'components.list_filter.clear') - click_button I18n.t(:'components.list_filter.apply') - end - within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - end - end - test 'selecting / deselecting all samples' do visit namespace_project_samples_url(@namespace, @project) + # no samples selected/checked within 'tbody' do assert_selector 'input[name="sample_ids[]"]', count: 3 assert_selector 'input[name="sample_ids[]"]:checked', count: 0 end within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" assert_selector 'strong[data-selection-target="selected"]', text: '0' end + # samples selected click_button I18n.t(:'projects.samples.index.select_all_button') within 'tbody' do assert_selector 'input[name="sample_ids[]"]:checked', count: 3 end within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" assert_selector 'strong[data-selection-target="selected"]', text: '3' end + # unselect single sample within 'tbody' do first('input[name="sample_ids[]"]').click end within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" assert_selector 'strong[data-selection-target="selected"]', text: '2' end + # select all again click_button I18n.t(:'projects.samples.index.select_all_button') within 'tbody' do assert_selector 'input[name="sample_ids[]"]', count: 3 assert_selector 'input[name="sample_ids[]"]:checked', count: 3 end + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '3' + end + # deselect all click_button I18n.t(:'projects.samples.index.deselect_all_button') within 'tbody' do assert_selector 'input[name="sample_ids[]"]', count: 3 assert_selector 'input[name="sample_ids[]"]:checked', count: 0 end + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end end test 'selecting / deselecting a page of samples' do - visit namespace_project_samples_url(@namespace, @project) + visit namespace_project_samples_url(@namespace, @project2) + within('div#limit-component') do + # set table limit to 10 to split samples table into two pages + find('button').click + click_link '10' + end within 'tbody' do - assert_selector 'input[name="sample_ids[]"]', count: 3 + assert_selector 'input[name="sample_ids[]"]', count: 10 assert_selector 'input[name="sample_ids[]"]:checked', count: 0 end within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" assert_selector 'strong[data-selection-target="selected"]', text: '0' end + # click select page find('input[name="select-page"]').click within 'tbody' do - assert_selector 'input[name="sample_ids[]"]:checked', count: 3 + assert_selector 'input[name="sample_ids[]"]:checked', count: 10 end within 'tfoot' do - assert_text 'Samples: 3' - assert_selector 'strong[data-selection-target="selected"]', text: '3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '10' end + # unselect 1 sample within 'tbody' do first('input[name="sample_ids[]"]').click end within 'tfoot' do - assert_text 'Samples: 3' - assert_selector 'strong[data-selection-target="selected"]', text: '2' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '9' end + # select whole page again find('input[name="select-page"]').click within 'tbody' do - assert_selector 'input[name="sample_ids[]"]', count: 3 - assert_selector 'input[name="sample_ids[]"]:checked', count: 3 + assert_selector 'input[name="sample_ids[]"]', count: 10 + assert_selector 'input[name="sample_ids[]"]:checked', count: 10 end + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '10' + end + # unselect whole page find('input[name="select-page"]').click within 'tbody' do - assert_selector 'input[name="sample_ids[]"]', count: 3 + assert_selector 'input[name="sample_ids[]"]', count: 10 assert_selector 'input[name="sample_ids[]"]:checked', count: 0 end + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end end test 'selecting samples while filtering' do @@ -1634,10 +1634,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'input[name="sample_ids[]"]:checked', count: 0 end within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" assert_selector 'strong[data-selection-target="selected"]', text: '0' end + # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: samples(:sample1).name find('input.t-search-component').native.send_keys(:return) @@ -1656,11 +1657,12 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'strong[data-selection-target="selected"]', text: '1' end + # remove filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: ' ' find('input.t-search-component').native.send_keys(:return) within 'tfoot' do - assert_text 'Samples: 3' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" assert_selector 'strong[data-selection-target="selected"]', text: '0' end end @@ -1679,16 +1681,19 @@ class SamplesTest < ApplicationSystemTestCase end test 'delete multiple samples' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name - assert_text @sample30.name + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - click_link I18n.t('projects.samples.index.delete_samples_button'), match: :first - within('span[data-controller-connected="true"] dialog') do + ### setup end ### + + ### actions start ### + click_link I18n.t('projects.samples.index.delete_samples_button') + within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') assert_text I18n.t( 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' @@ -1702,59 +1707,50 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end + ### actions end ### + + ### verify start ### + # flash msg assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') + # no remaining samples within 'div[role="alert"]' do assert_text I18n.t('projects.samples.index.no_samples') assert_text I18n.t('projects.samples.index.no_associated_samples') end end - test 'delete single sample with checkbox and delete samples button' do + test 'singular description within delete samples dialog' do visit namespace_project_samples_url(@namespace, @project) - within('tbody') do - assert_selector 'tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name - assert_text @sample30.name - within 'tr:first-child' do - all('input[type="checkbox"]')[0].click - end + within('tbody tr:first-child') do + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + all('input[type="checkbox"]')[0].click end - click_link I18n.t('projects.samples.index.delete_samples_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') + click_link I18n.t('projects.samples.index.delete_samples_button') + within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', sample_name: @sample1.name) - within %(turbo-frame[id="list_selections"]) do - assert_text @sample1.puid - end - - click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') - end - - assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') - - within 'tbody' do - assert_selector 'tr', count: 2 - assert_no_text @sample1.name - assert_text @sample2.name - assert_text @sample30.name end end test 'delete single sample with remove link while all samples selected followed by multiple deletion' do + # tests that localstorage does not contain a selected sample after it's destroyed + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### + + ### actions start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - assert_text @sample1.name - assert_text @sample2.name - assert_text @sample30.name + # select all samples all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - assert find('input#select-page').checked? - + # destroy sample1 with remove action link within '#samples-table table tbody tr:first-child' do click_link I18n.t('projects.samples.index.remove_button') end @@ -1763,18 +1759,18 @@ class SamplesTest < ApplicationSystemTestCase click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end + # sample 1 no longer exists and both remaining samples are still selected within '#samples-table table tbody' do - assert_selector 'tr', count: 2 - assert_no_text @sample1.name - assert all('input[type="checkbox"]')[0].checked? - assert all('input[type="checkbox"]')[1].checked? + assert_no_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + assert_selector 'input[name="sample_ids[]"]:checked', count: 2 end - assert find('input#select-page').checked? - - click_link I18n.t('projects.samples.index.delete_samples_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') + # click delete samples button + click_link I18n.t('projects.samples.index.delete_samples_button') + within('#dialog') do + # verify sample2 and 30 are still in localstorage, and sample1 is not assert_text I18n.t( 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' ).gsub! 'COUNT_PLACEHOLDER', '2' @@ -1783,46 +1779,118 @@ class SamplesTest < ApplicationSystemTestCase assert_no_text @sample1.name click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end + ### actions end ### + + ### verify start ### assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') within 'div[role="alert"]' do assert_text I18n.t('projects.samples.index.no_samples') assert_text I18n.t('projects.samples.index.no_associated_samples') end + ### verify end ### + end + + test 'filtering samples by list of sample puids' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + within '#samples-table table tbody' do + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + end + ### setup end ### - assert_selector 'a.cursor-not-allowed.pointer-events-none', count: 4 - assert_selector 'button.cursor-not-allowed.pointer-events-none', count: 1 + ### actions and verify start ### + click_button I18n.t(:'components.list_filter.title') + within '#list-filter-dialog' do + assert_selector 'h1', text: I18n.t(:'components.list_filter.title') + # add sample1 and 2 puids + fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.puid}, #{@sample2.puid}" + click_button I18n.t(:'components.list_filter.apply') + end + within '#samples-table table tbody' do + assert_selector 'tr', count: 2 + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + # sample30 filtered out + assert_no_selector "tr[id='#{@sample30.id}']" + end + click_button I18n.t(:'components.list_filter.title') + within '#list-filter-dialog' do + assert_selector 'h1', text: I18n.t(:'components.list_filter.title') + # clear filter + click_button I18n.t(:'components.list_filter.clear') + click_button I18n.t(:'components.list_filter.apply') + end + within '#samples-table table tbody' do + # sample30 no longer filtered + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + end + ### actions and verify end ### end - test 'can filter by large list of sample names or ids' do + test 'filtering samples by list of sample names' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do - assert_selector 'tr', count: 3 - assert_selector 'tr th', text: @sample1.puid - assert_selector 'tr th', text: @sample2.puid + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" end + ### setup end ### + + ### actions start ### click_button I18n.t(:'components.list_filter.title') - within '#list-filter-dialog' do |dialog| + within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') - fill_in I18n.t(:'components.list_filter.description'), with: long_filter_text - assert_selector 'span.label', count: 500 - dialog.scroll_to(dialog.find('button', text: I18n.t(:'components.list_filter.apply')), align: :bottom) + # add sample1 and 2 names + fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.name}, #{@sample2.name}" click_button I18n.t(:'components.list_filter.apply') end + ### actions end ### + + ### verify start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 1 + assert_selector 'tr', count: 2 + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + # sample30 filtered out + assert_no_selector "tr[id='#{@sample30.id}']" end + ### verify end ### + end + + test 'can filter by large list of sample names or ids' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + within '#samples-table table tbody' do + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + end + ### setup end ### + + ### actions start ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do |dialog| assert_selector 'h1', text: I18n.t(:'components.list_filter.title') - dialog.scroll_to dialog.find('button', text: I18n.t(:'components.list_filter.apply')) - - click_button I18n.t(:'components.list_filter.clear') + fill_in I18n.t(:'components.list_filter.description'), with: long_filter_text + assert_selector 'span.label', count: 500 + dialog.scroll_to(dialog.find('button', text: I18n.t(:'components.list_filter.apply')), align: :bottom) click_button I18n.t(:'components.list_filter.apply') end + ### actions end ### + + ### verify start ### within '#samples-table table tbody' do - assert_selector 'tr', count: 3 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" end + ### verify end ### end def long_filter_text From 9ec9d229db849bdcfadd7a01a2eb8f3b631f4fa6 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Thu, 12 Dec 2024 11:38:44 -0600 Subject: [PATCH 03/24] add additional tests for sort filter limit --- test/system/projects/samples_test.rb | 243 +++++++++++++++------------ 1 file changed, 132 insertions(+), 111 deletions(-) diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index ff3f4d1487..fa6bee79f9 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -608,50 +608,7 @@ class SamplesTest < ApplicationSystemTestCase ### verify end ### end - test 'can search the list of samples by metadata field and value presence when metadata is toggled' do - # also tests that metadata toggle persist through other actions (filter) and page refresh - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - filter_text = 'metadatafield1:value1' - - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - assert_selector "tr[id='#{@sample1.id}']" - assert_selector "tr[id='#{@sample2.id}']" - assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### - - ### actions and verify start ### - # toggle metadata on - find('label', text: I18n.t('projects.samples.shared.metadata_toggle.label')).click - # verify all 3 samples are still in table - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 3 - # verify metadata fields are now present - assert_selector '#samples-table table thead tr th', count: 8 - - # apply filter - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text - find('input.t-search-component').native.send_keys(:return) - - # verify table only has sample30 - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_no_selector "tr[id='#{@sample1.id}']" - assert_no_selector "tr[id='#{@sample2.id}']" - assert_selector "tr[id='#{@sample30.id}']" - - # verify filter input persists - assert_selector %(input.t-search-component) do |input| - assert_equal filter_text, input['value'] - end - ### actions and verify end ### - end - - test 'can change limit/pagination and then filter by id' do + test 'limit persists through filter and sort actions' do # tests limit change and that it persists through other actions (filter) ### setup start ### sample3 = samples(:sample3) @@ -678,50 +635,16 @@ class SamplesTest < ApplicationSystemTestCase fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: sample3.puid find('input.t-search-component').native.send_keys(:return) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) - assert_selector '#samples-table table tbody tr', count: 1 - assert_selector "tr[id='#{sample3.id}']" - ### actions and verify end ### - end - - test 'filter highlighting for sample name' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - ### setup end ### - - ### actions start ### - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' - find('input.t-search-component').native.send_keys(:return) - ### actions end ### - - ### verify start ### - # verify table only contains sample1 - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - # checks highlighting - assert_selector 'mark', text: 'Sample', count: 3 - end - - test 'filter highlighting for sample puid' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - ### setup end ### + # verify limit is still 10 + assert_selector 'div#limit-component button div span', text: '10' - ### actions start ### - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid - find('input.t-search-component').native.send_keys(:return) - ### actions end ### + # apply sort + click_on I18n.t('samples.table_component.name') + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - ### verify start ### - # verify table only contains sample1 - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, - locale: @user.locale)) - # checks highlighting - assert_selector 'mark', text: @sample1.puid + # verify limit is still 10 + assert_selector 'div#limit-component button div span', text: '10' + ### actions and verify end ### end test 'can sort samples' do @@ -801,8 +724,36 @@ class SamplesTest < ApplicationSystemTestCase ### action and verify end ### end - test 'can filter and then sort the list of samples by name' do - # tests that filter persists through other actions (sort) + test 'sort persists through limit and filter' do + # tests that sort persists through other actions (filter) + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions and verify start ### + # apply sort + click_on I18n.t('samples.table_component.name') + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + + # set limit + within('div#limit-component') do + find('button').click + click_link '10' + end + + # verify sort is still applied + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid + find('input.t-search-component').native.send_keys(:return) + + # verify sort is still applied + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + ### actions and verify end ### + end + + test 'filter by name' do ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" @@ -814,31 +765,17 @@ class SamplesTest < ApplicationSystemTestCase # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) - - assert_selector "tr[id='#{@sample1.id}']" - assert_no_selector "tr[id='#{@sample2.id}']" - assert_no_selector "tr[id='#{@sample30.id}']" - - # apply sort - click_on I18n.t('samples.table_component.name') - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' ### actions end ### ### verify start ### - # verify table still only contains sample1 + # only sample1 exists within table assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - - # verify filter text is still in filter input - assert_selector %(input.t-search-component) do |input| - assert_equal @sample1.name, input['value'] - end ### verify end ### end - test 'can sort and then filter the list of samples by puid' do - # tests that sort persists through other actions (filter) + test 'filter by puid' do ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" @@ -847,22 +784,106 @@ class SamplesTest < ApplicationSystemTestCase ### setup end ### ### actions start ### - # apply sort - click_on I18n.t('samples.table_component.name') - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample2.puid + find('input.t-search-component').native.send_keys(:return) + ### actions end ### + + ### verify start ### + # only sample2 exists within table + assert_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + ### verify end ### + end + + test 'filter highlighting for sample name' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + ### setup end ### + + ### actions start ### + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' + find('input.t-search-component').native.send_keys(:return) + ### actions end ### + + ### verify start ### + # verify table only contains sample1 + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + # checks highlighting + assert_selector 'mark', text: 'Sample', count: 3 + end + + test 'filter highlighting for sample puid' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + ### setup end ### + + ### actions start ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid find('input.t-search-component').native.send_keys(:return) ### actions end ### ### verify start ### - # verify sort is still applied - assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' # verify table only contains sample1 + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, + locale: @user.locale)) + # checks highlighting + assert_selector 'mark', text: @sample1.puid + end + + test 'filter persists through sort and limit actions' do + # tests that filter persists through other actions (sort) + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + assert_selector "tr[id='#{@sample1.id}']" + assert_selector "tr[id='#{@sample2.id}']" + assert_selector "tr[id='#{@sample30.id}']" + ### setup end ### + + ### actions and verify start ### + # apply filter + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name + find('input.t-search-component').native.send_keys(:return) + + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + + # apply sort + click_on I18n.t('samples.table_component.name') + assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' + + # verify table still only contains sample1 assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" + + # verify filter text is still in filter input + assert_selector %(input.t-search-component) do |input| + assert_equal @sample1.name, input['value'] + end + + # set limit + within('div#limit-component') do + find('button').click + click_link '10' + end + + # verify table still only contains sample1 + assert_selector "tr[id='#{@sample1.id}']" + assert_no_selector "tr[id='#{@sample2.id}']" + assert_no_selector "tr[id='#{@sample30.id}']" + + # verify filter text is still in filter input + assert_selector %(input.t-search-component) do |input| + assert_equal @sample1.name, input['value'] + end ### verify end ### end @@ -1395,7 +1416,7 @@ class SamplesTest < ApplicationSystemTestCase ### verify end ### end - test 'singular dialog description' do + test 'singular clone dialog description' do ### setup start ### visit namespace_project_samples_url(@namespace, @project) ### setup end ### From 6fe926b2ec9a93ce9224eee4b93a10b06874b825 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Thu, 12 Dec 2024 11:48:25 -0600 Subject: [PATCH 04/24] fix current tests --- test/system/projects/samples_test.rb | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index fa6bee79f9..6240a04e62 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -713,13 +713,12 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'table thead th:nth-child(5) svg.icon-arrow_down' within('#samples-table table tbody') do - # order does not change as sample1 is the only sample with attachments_updated_at - assert_selector 'tr:first-child th', text: @sample1.puid - assert_selector 'tr:first-child td:nth-child(2)', text: @sample1.name - assert_selector 'tr:nth-child(2) th', text: @sample2.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample2.name - assert_selector 'tr:last-child th', text: @sample30.puid - assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name + assert_selector 'tr:first-child th', text: @sample2.puid + assert_selector 'tr:first-child td:nth-child(2)', text: @sample2.name + assert_selector 'tr:nth-child(2) th', text: @sample3.puid + assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample3.name + assert_selector 'tr:last-child th', text: @sample1.puid + assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end ### action and verify end ### end @@ -1742,18 +1741,24 @@ class SamplesTest < ApplicationSystemTestCase end test 'singular description within delete samples dialog' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### within('tbody tr:first-child') do - assert_selector "tr[id='#{@sample1.id}']" - assert_selector "tr[id='#{@sample2.id}']" - assert_selector "tr[id='#{@sample30.id}']" + # select sample1 all('input[type="checkbox"]')[0].click end click_link I18n.t('projects.samples.index.delete_samples_button') + ### actions end ### + + ### verify start ### within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', sample_name: @sample1.name) end + ### verify end ### end test 'delete single sample with remove link while all samples selected followed by multiple deletion' do From 65f8e3f2731871fd627d2955eb6fba33c0c01f97 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Thu, 12 Dec 2024 11:57:26 -0600 Subject: [PATCH 05/24] further fix tests --- test/fixtures/samples.yml | 2 +- test/system/projects/samples_test.rb | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/fixtures/samples.yml b/test/fixtures/samples.yml index baf829bfec..a615e9026f 100644 --- a/test/fixtures/samples.yml +++ b/test/fixtures/samples.yml @@ -6,7 +6,7 @@ sample1: project_id: <%= ActiveRecord::FixtureSet.identify(:project1, :uuid) %> puid: INXT_SAM_AAAAAAAAAA created_at: <%= 1.week.ago %> - updated_at: <%= 1.day.ago %> + updated_at: <%= 3.hours.ago %> attachments_updated_at: <%= 2.hours.ago %> sample2: diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index 6240a04e62..fc9237d472 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -54,7 +54,7 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'th:first-child', text: @sample1.puid assert_selector 'td:nth-child(2)', text: @sample1.name assert_selector 'td:nth-child(3)', text: I18n.l(@sample1.created_at.localtime, format: :full_date) - # assert_selector 'td:nth-child(4)', text: "yesterday at #{Time.now.strftime('%-I:%M%P')}" + assert_selector 'td:nth-child(4)', text: '3 hours ago' assert_selector 'td:nth-child(5)', text: '2 hours ago' # actions tested by role in separate test end @@ -659,6 +659,7 @@ class SamplesTest < ApplicationSystemTestCase within('tbody tr:first-child th') do assert_text @sample1.puid end + # sort by name click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -671,6 +672,7 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name end + # change name sort direction click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' @@ -686,6 +688,7 @@ class SamplesTest < ApplicationSystemTestCase end test 'sort samples attachments_updated_at_nulls_last' do + # attachments_updated_at_nulls_last sorts null data together ### setup start ### visit namespace_project_samples_url(@namespace, @project) @@ -697,6 +700,7 @@ class SamplesTest < ApplicationSystemTestCase within('tbody tr:first-child th') do assert_text @sample1.puid end + # sort by attachments_updated_at click_on I18n.t('samples.table_component.attachments_updated_at') assert_selector 'table thead th:nth-child(5) svg.icon-arrow_up' @@ -709,14 +713,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child td:nth-child(2)', text: @sample30.name end + # change sort direction click_on I18n.t('samples.table_component.attachments_updated_at') assert_selector 'table thead th:nth-child(5) svg.icon-arrow_down' within('#samples-table table tbody') do assert_selector 'tr:first-child th', text: @sample2.puid assert_selector 'tr:first-child td:nth-child(2)', text: @sample2.name - assert_selector 'tr:nth-child(2) th', text: @sample3.puid - assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample3.name + assert_selector 'tr:nth-child(2) th', text: @sample30.puid + assert_selector 'tr:nth-child(2) td:nth-child(2)', text: @sample30.name assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end From 7aacd1010406256177ff817035a0add74e1cbd2d Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Fri, 13 Dec 2024 11:57:00 -0600 Subject: [PATCH 06/24] cleanup --- db/schema.rb | 34 +- test/system/projects/samples_test.rb | 1003 +++++++++++++++----------- 2 files changed, 588 insertions(+), 449 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 5dafb55105..a0083dcf21 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -714,34 +714,34 @@ SQL - create_trigger :logidze_on_attachments, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_attachments BEFORE INSERT OR UPDATE ON public.attachments FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') - SQL - create_trigger :logidze_on_automated_workflow_executions, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_automated_workflow_executions BEFORE INSERT OR UPDATE ON public.automated_workflow_executions FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_users, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_users BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_data_exports, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_data_exports BEFORE INSERT OR UPDATE ON public.data_exports FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_namespaces, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_namespaces BEFORE INSERT OR UPDATE ON public.namespaces FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_summary,updated_at,attachments_updated_at}') SQL create_trigger :logidze_on_members, sql_definition: <<-SQL CREATE TRIGGER logidze_on_members BEFORE INSERT OR UPDATE ON public.members FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_namespace_bots, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_namespace_bots BEFORE INSERT OR UPDATE ON public.namespace_bots FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_samples, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_samples BEFORE INSERT OR UPDATE ON public.samples FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_provenance,updated_at,attachments_updated_at}') + SQL + create_trigger :logidze_on_personal_access_tokens, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_personal_access_tokens BEFORE INSERT OR UPDATE ON public.personal_access_tokens FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{last_used_at}') SQL create_trigger :logidze_on_namespace_group_links, sql_definition: <<-SQL CREATE TRIGGER logidze_on_namespace_group_links BEFORE INSERT OR UPDATE ON public.namespace_group_links FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_namespaces, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_namespaces BEFORE INSERT OR UPDATE ON public.namespaces FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_summary,updated_at,attachments_updated_at}') + create_trigger :logidze_on_attachments, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_attachments BEFORE INSERT OR UPDATE ON public.attachments FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_personal_access_tokens, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_personal_access_tokens BEFORE INSERT OR UPDATE ON public.personal_access_tokens FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{last_used_at}') + create_trigger :logidze_on_data_exports, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_data_exports BEFORE INSERT OR UPDATE ON public.data_exports FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_samples, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_samples BEFORE INSERT OR UPDATE ON public.samples FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_provenance,updated_at,attachments_updated_at}') + create_trigger :logidze_on_namespace_bots, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_namespace_bots BEFORE INSERT OR UPDATE ON public.namespace_bots FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_users, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_users BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_automated_workflow_executions, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_automated_workflow_executions BEFORE INSERT OR UPDATE ON public.automated_workflow_executions FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL end diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index fc9237d472..54abb347ae 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -60,13 +60,9 @@ class SamplesTest < ApplicationSystemTestCase end end end - - # pagy - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) end - test 'edit and delete row actions render for user with role == Owner in samples table' do + test 'edit and delete row actions render for user with Owner role' do visit namespace_project_samples_url(@namespace, @project) within("tr[id='#{@sample1.id}'] td:last-child") do @@ -75,7 +71,7 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'edit row action render for user with role == Maintainer in samples table' do + test 'edit row action render for user with Maintainer role' do login_as users(:joan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -85,11 +81,11 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'no row actions for user with role < Maintainer in samples table' do + test 'no row actions for user with role < Maintainer' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) within('#samples-table table thead tr:first-child') do - # attachments updated at is the last column, action column does not exist + # attachments_updated_at is the last column, action column does not exist assert_selector 'th:last-child', text: I18n.t('samples.table_component.attachments_updated_at').upcase assert_no_selector 'th:last-child', text: I18n.t('samples.table_component.action').upcase end @@ -129,67 +125,67 @@ class SamplesTest < ApplicationSystemTestCase assert_no_selector "input#sample_#{@sample1.id}" end - test 'User with role >= Analyst sees workflow execution link in samples index' do + test 'User with role >= Analyst sees workflow execution link' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role < Analyst does not see workflow execution link in samples index' do + test 'User with role < Analyst does not see workflow execution link' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role >= Analyst sees create export button in samples index' do + test 'User with role >= Analyst sees create export button' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role < Analyst does not see create export button in samples index' do + test 'User with role < Analyst does not see create export button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role >= Maintainer sees import metadata link in samples index' do + test 'User with role >= Maintainer sees import metadata button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role < Maintainer does not see import metadata link in samples index' do + test 'User with role < Maintainer does not see import metadata button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role >= Maintainer sees new sample button in samples index' do + test 'User with role >= Maintainer sees new sample button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role < Maintainer does not see new sample button in samples index' do + test 'User with role < Maintainer does not see new sample button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role >= Maintainer sees delete samples button in samples index' do + test 'User with role >= Maintainer sees delete samples button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.delete_samples_button') end - test 'User with role < Maintainer does not see delete samples button in samples index' do + test 'User with role < Maintainer does not see delete samples button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -204,12 +200,16 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t(:'action_policy.policy.project.sample_listing?', name: @project.name) end - test 'should create sample' do - ### setup start ### + test 'create sample' do + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + within('#samples-table table tbody') do + # sample does not currently exist + assert_no_text 'New Name' + end + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # launch dialog click_on I18n.t('projects.samples.index.new_button') @@ -217,7 +217,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t('activerecord.attributes.sample.description'), with: 'A sample description' fill_in I18n.t('activerecord.attributes.sample.name'), with: 'New Name' click_on I18n.t('projects.samples.new.submit_button') - ### actions end ### + ### ACTIONS END ### ### results start ### # flash msg @@ -232,12 +232,12 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'should update Sample' do - ### setup start ### + test 'edit sample' do + ### SETUP START ### visit namespace_project_sample_url(@namespace, @project, @sample1) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # nav to edit sample page click_on I18n.t('projects.samples.show.edit_button') @@ -245,7 +245,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in 'Description', with: 'A new description' fill_in 'Name', with: 'New Sample Name' click_on I18n.t('projects.samples.edit.submit_button') - ### actions end ### + ### ACTIONS END ### ### results start ### # flash msg @@ -257,8 +257,8 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'should destroy Sample from sample show page' do - ### setup start ### + test 'destroy sample from sample show page' do + ### SETUP START ### # nav to samples index and verify sample exists within table visit namespace_project_samples_url(@namespace, @project) assert_selector "#samples-table table tbody tr[id='#{@sample1.id}']" @@ -266,37 +266,40 @@ class SamplesTest < ApplicationSystemTestCase # nav to sample show visit namespace_project_sample_url(@namespace, @project, @sample1) - ### setup end ### + ### SETUP END ### - ### actions start ## + ### ACTIONS START ## click_link I18n.t(:'projects.samples.index.remove_button') within('#turbo-confirm[open]') do click_button I18n.t(:'components.confirmation.confirm') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) - # deleted sample row no longer exists - assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" # redirected to samples index assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 + # deleted sample row no longer exists + assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" # remaining samples still appear on table assert_selector '#samples-table table tbody tr', count: 2 - ### verify end ### + ### VERIFY END ### end - test 'should destroy Sample from sample listing page' do - ### setup start ### + test 'should destroy Sample from samples table' do + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### + + ### ACTIONS START ### within("tr[id='#{@sample1.id}']") do + # click remove action click_link I18n.t('projects.samples.index.remove_button') end @@ -304,9 +307,9 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t('projects.samples.deletions.new_deletion_dialog.description', sample_name: @sample1.name) click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end - ### setup end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) @@ -316,11 +319,69 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 # remaining samples still in table assert_selector '#samples-table table tbody tr', count: 2 - ### verify end ### + ### VERIFY END ### end - test 'should transfer samples' do - ### setup start ### + test 'transfer dialog sample listing' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + ### VERIFY END ### + end + + test 'transfer dialog with plural description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', + '3') + end + ### VERIFY END ### + end + + test 'transfer dialog with singular description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.singular') + end + ### VERIFY END ### + end + + test 'transfer samples' do + ### SETUP START ### # show destination project has 20 samples prior to transfer visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, @@ -331,38 +392,28 @@ class SamplesTest < ApplicationSystemTestCase ) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### samples = @project.samples.pluck(:puid, :name) - within('#samples-table table tbody') do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + # select all 3 samples + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do - # verify 'plural' form of description renders - assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', - '3') - # verify sample puid and name are listed in dialog list - within %(turbo-frame[id="list_selections"]) do - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end # select destination project find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.transfers.create.success') # originating project no longer has samples assert_text I18n.t('projects.samples.index.no_samples') + # destination project received transferred samples visit namespace_project_samples_url(@namespace, @project2) within '#samples-table table tbody' do samples.each do |sample| @@ -370,60 +421,42 @@ class SamplesTest < ApplicationSystemTestCase assert_text sample[1] end end - ### verify end ### - end - - test 'transfer dialog with single sample' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.transfer_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.singular') - end - ### verify end ### + ### VERIFY END ### end test 'should not transfer samples with session storage cleared' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + # select samples + click_button I18n.t(:'projects.samples.index.select_all_button') + # clear localstorage Capybara.execute_script 'sessionStorage.clear()' + # launch transfer dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # samples listing should no longer appear in dialog assert_no_selector '#list_selections' # error msg displayed in dialog assert_text I18n.t('projects.samples.transfers.create.no_samples_transferred_error') end - ### verify end ### + ### VERIFY END ### end test 'transfer samples with and without same name in destination project' do - # only samples without a matching name will transfer + # only samples without a matching name to samples in destination project will transfer - ### setup start ### + ### SETUP START ### namespace = groups(:subgroup1) project25 = projects(:project25) @@ -431,26 +464,23 @@ class SamplesTest < ApplicationSystemTestCase visit namespace_project_samples_url(namespace, project25) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 2, count: 2, locale: @user.locale)) + # 3 samples in originating project visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each do |checkbox| - checkbox.click unless checkbox.checked? - end - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do # error messages in dialog assert_text I18n.t('projects.samples.transfers.create.error') @@ -472,117 +502,114 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'sample transfer project listing should be empty for maintainer if no other projects in hierarchy' do - ### setup start ### + ### SETUP START ### login_as users(:user28) namespace = groups(:group_hotel) project = projects(:projectHotel) visit namespace_project_samples_url(namespace, project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do # no available destination projects assert_selector "input[placeholder='#{I18n.t('projects.samples.transfers.dialog.no_available_projects')}']" end - ### verify end ### + ### VERIFY END ### end - test 'should update pagination & selection during transfer samples' do - namespace1 = groups(:group_one) - namespace17 = groups(:group_seventeen) - project38 = projects(:project38) - project2 = projects(:project2) - samples = [samples(:bulk_sample1), samples(:bulk_sample2)] - - Project.reset_counters(project38.id, :samples_count) - visit namespace_project_samples_url(namespace17, project38) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 200, - locale: @user.locale)) + test 'updating sample selection during transfer samples' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project2) - click_button I18n.t(:'projects.samples.index.select_all_button') + # verify no samples currently selected in destination project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### - within 'tbody' do - assert_selector 'input[name="sample_ids[]"]:checked', count: 20 + ### ACTIONS START ### + # select 1 sample to transfer + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click end + + # verify 1 sample selected in originating project within 'tfoot' do - assert_text 'Samples: 200' - assert_selector 'strong[data-selection-target="selected"]', text: '200' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '1' end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', '200') - within %(turbo-frame[id="list_selections"]) do - samples.pluck(:puid, :name).each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - + # transfer sample + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end + ### ACTIONS END ### - # Check samples selected are [] and has the proper number of samples - assert_text I18n.t(:'projects.samples.index.no_samples') + ### VERIFY START ### + # verify no samples selected anymore + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 2" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end - Project.reset_counters(project2.id, :samples_count) - visit namespace_project_samples_url(namespace1, project2) + # verify destination project still has no selected samples and one additional sample + visit namespace_project_samples_url(@namespace, @project2) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 220, - locale: @user.locale)) + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end click_button I18n.t(:'projects.samples.index.select_all_button') within 'tfoot' do - sample_counts = all('strong') - total_samples = sample_counts[0].text.to_i - selected_samples = sample_counts[1].text.to_i - assert selected_samples <= total_samples + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '21' end + ### VERIFY END end test 'empty state of transfer sample project selection' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # check samples - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + # select samples + click_button I18n.t(:'projects.samples.index.select_all_button') # launch dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do # fill destination input find('input#select2-input').fill_in with: 'invalid project name or puid' - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.transfers.dialog.empty_state') - ### verify end ### + ### VERIFY END ### end end test 'can search the list of samples by name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # partial name search - filter_text = @sample1.name[-3..-1] + filter_text = @sample1.name[-3..] assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) @@ -590,34 +617,34 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 1 assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'limit persists through filter and sort actions' do # tests limit change and that it persists through other actions (filter) - ### setup start ### + ### SETUP START ### sample3 = samples(:sample3) visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### within('div#limit-component') do # set table limit to 10 find('button').click @@ -644,18 +671,15 @@ class SamplesTest < ApplicationSystemTestCase # verify limit is still 10 assert_selector 'div#limit-component button div span', text: '10' - ### actions and verify end ### + ### actions and VERIFY END ### end test 'can sort samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - ### setup end ### - - ### action and verify start ### + ### ACTION and VERIFY START ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -684,19 +708,19 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### action and verify end ### + ### ACTION and VERIFY END ### end test 'sort samples attachments_updated_at_nulls_last' do # attachments_updated_at_nulls_last sorts null data together - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### action and verify start ### + ### action and VERIFY START ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -725,16 +749,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### action and verify end ### + ### action and VERIFY END ### end test 'sort persists through limit and filter' do - # tests that sort persists through other actions (filter) - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -754,105 +777,107 @@ class SamplesTest < ApplicationSystemTestCase # verify sort is still applied assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - ### actions and verify end ### + ### actions and VERIFY END ### end test 'filter by name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # only sample1 exists within table assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'filter by puid' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample2.puid find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # only sample2 exists within table assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'filter highlighting for sample name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### - # verify table only contains sample1 + ### VERIFY START ### + # verify table still contains all samples assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: 'Sample', count: 3 + ### VERIFY END ### end test 'filter highlighting for sample puid' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: @sample1.puid + ### VERIFY END ### end test 'filter persists through sort and limit actions' do - # tests that filter persists through other actions (sort) - ### setup start ### + ### SETUP START ### + filter_text = @sample1.name visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### ACTIONS and VERIFY START ### # apply filter - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) assert_selector "tr[id='#{@sample1.id}']" @@ -870,7 +895,7 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal @sample1.name, input['value'] + assert_equal filter_text, input['value'] end # set limit @@ -886,24 +911,24 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal @sample1.name, input['value'] + assert_equal filter_text, input['value'] end - ### verify end ### + ### VERIFY END ### end test 'filter persists through page refresh' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) filter_text = @sample1.name - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" @@ -918,15 +943,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'sort persists through page refresh' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -935,22 +960,21 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### actions end ### - - ### verify start ### + ### ACTIONS END ### + ### VERIFY START ### # refresh visit namespace_project_samples_url(@namespace, @project) # verify sort is still enabled assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - # verify table ordering is still in changed/sorted state + # verify table ordering is still in sorted state assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### verify end ### + ### VERIFY END ### end test 'should import metadata via csv' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -972,17 +996,19 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + # start import click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### + # success msg assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -993,7 +1019,7 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # sample 1 and 2 have no value current for metadatafield 1 and 2 + # sample 1 and 2 metadata is updated within("tr[id='#{@sample1.id}']") do assert_selector 'td:nth-child(6)', text: '10' assert_selector 'td:nth-child(7)', text: '20' @@ -1005,11 +1031,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '35' end end - ### verify end ### + ### VERIFY END ### end test 'should import metadata via xls' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1030,17 +1056,18 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + # start import click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xls') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1066,11 +1093,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### verify end ### + ### VERIFY END ### end test 'should import metadata via xlsx' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1091,17 +1118,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xlsx') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1127,51 +1154,54 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### verify end ### + ### VERIFY END ### end test 'should not import metadata via invalid file type' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/invalid.txt') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do + # error msg assert_text I18n.t('services.samples.metadata.import_file.invalid_file_extension') end - ### verify end ### + ### VERIFY END ### end test 'should import metadata with ignore empty values' do - ### setup start ### + # enabled ignore empty values will leave sample metadata values unchanged + ### SETUP START ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import + # value for metadatafield1, which is blank on the csv to import and will be left unchanged after import assert_selector 'td:nth-child(6)', text: 'value1' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option + # enable ignore empty values find('input#file_import_ignore_empty_values').click click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1180,30 +1210,32 @@ class SamplesTest < ApplicationSystemTestCase # unchanged value assert_selector 'td:nth-child(6)', text: 'value1' end - ### verify end ### + ### VERIFY END ### end test 'should import metadata without ignore empty values' do - ### setup start ### + # disabled ignore empty values will delete any metadata values that are empty on the import + ### SETUP START ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import + # value for metadatafield1, which is blank on the csv to import and will be deleted by the import assert_selector 'td:nth-child(6)', text: 'value1' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option + # leave ignore empty values disabled assert_not find('input#file_import_ignore_empty_values').checked? click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1211,70 +1243,71 @@ class SamplesTest < ApplicationSystemTestCase # value is deleted for metadatafield1 assert_selector 'td:nth-child(6)', text: '' end + ### VERIFY END ### end test 'should not import metadata with duplicate header errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/duplicate_headers.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.duplicate_column_names') - ### verify end ### + ### VERIFY END ### end end test 'should not import metadata with missing metadata row errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_rows.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_row') - ### verify end ### + ### VERIFY END ### end end test 'should not import metadata with missing metadata column errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_columns.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_column') - ### verify end ### + ### VERIFY END ### end end test 'should partially import metadata with missing sample errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1292,17 +1325,18 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first + ### ACTIONS START ### + click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/mixed_project_samples.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### + # sample 3 does not exist in current project assert_text I18n.t('services.samples.metadata.import_file.sample_not_found_within_project', sample_puid: 'Project 2 Sample 3') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1321,33 +1355,33 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '30' end end - ### verify end ### + ### VERIFY END ### end test 'should not import metadata with analysis values' do - ### setup start ### + ### SETUP START ### subgroup12aa = groups(:subgroup_twelve_a_a) project31 = projects(:project31) sample34 = samples(:sample34) visit namespace_project_samples_url(subgroup12aa, project31) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click - # metadata not overwriting analysis values will still be added + # metadata that does not overwriting analysis values will still be added assert_selector '#samples-table table thead tr th', count: 8 within('#samples-table table thead') do assert_no_text 'METADATAFIELD3' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_analysis_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('services.samples.metadata.import_file.sample_metadata_fields_not_updated', sample_name: sample34.name, metadata_fields: 'metadatafield1') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1358,27 +1392,86 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # new metadata values for sample 1 and 2 + # new metadata value within("tr[id='#{sample34.id}']") do assert_selector 'td:nth-child(8)', text: '20' end - ### verify end ### + ### VERIFY END ### + end + end + + test 'clone dialog sample listing' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end end + ### VERIFY END ### + end + + test 'singular clone dialog description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.clones.dialog.description.singular') + end + ### VERIFY END ### + end + + test 'plural clone dialog description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t( + 'projects.samples.clones.dialog.description.plural' + ).gsub! 'COUNT_PLACEHOLDER', '2' + end + ### VERIFY END ### end test 'should clone samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project2) - # samples 1 and 2 do not exist in project2 + # verify samples 1 and 2 do not exist in project2 within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name end visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # select samples 1 and 2 for cloning within '#samples-table table tbody' do find("input#sample_#{@sample1.id}").click @@ -1386,23 +1479,13 @@ class SamplesTest < ApplicationSystemTestCase end click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do - # plural dialog description since > 1 sample selected - assert_text I18n.t( - 'projects.samples.clones.dialog.description.plural' - ).gsub! 'COUNT_PLACEHOLDER', '2' - within('#list_selections') do - assert_text @sample1.puid - assert_text @sample1.name - assert_text @sample2.puid - assert_text @sample2.name - end find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.clones.create.success') # samples still exist within samples table of originating project @@ -1417,81 +1500,60 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### verify end ### - end - - test 'singular clone dialog description' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.clone_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.clones.dialog.description.singular') - end - ### verify end ### + ### VERIFY END ### end test 'should not clone samples with session storage cleared' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + # clear localstorage Capybara.execute_script 'sessionStorage.clear()' click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### - assert_no_selector "turbo-frame[id='list_selections']" + ### VERIFY START ### + # sample listing should not be in error dialog + assert_no_selector '#list_selections' + # error msg assert_text I18n.t('projects.samples.clones.create.no_samples_cloned_error') assert_text I18n.t('services.samples.clone.empty_sample_ids') - ### verify end ### + ### VERIFY END ### end end test 'should not clone some samples' do namespace = groups(:subgroup1) project25 = projects(:project25) - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(namespace, project25) - # samples 1 and 2 do not exist in project25 samples table + # sample30's name already exists in project25 samples table, samples1 and 2 do not within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name + assert_text @sample30.name end visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # check all samples. sample30 will error due to name collision in project25 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - end - ### actions end ### - ### verify start ### - within %(turbo-frame[id="samples_dialog"]) do + ### ACTIONS END ### + + ### VERIFY START ### # errors that a sample with the same name as sample30 already exists in project25 assert_text I18n.t('projects.samples.clones.create.error') assert_text I18n.t('services.samples.clone.sample_exists', sample_puid: @sample30.puid, @@ -1505,47 +1567,100 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### verify end ### + ### VERIFY END ### end test 'empty state of destination project selection for sample cloning' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start #### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START #### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').fill_in with: 'invalid project name or puid' - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.clones.dialog.empty_state') - ### verify end ### + ### VERIFY END ### end end test 'no available destination projects to clone samples' do - ### setup start ### + ### SETUP START ### sign_in users(:jean_doe) visit namespace_project_samples_url(namespaces_user_namespaces(:john_doe_namespace), projects(:john_doe_project2)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do assert "input[placeholder='#{I18n.t('projects.samples.clones.dialog.no_available_projects')}']" end - ### verify end ### + ### VERIFY END ### + end + + test 'updating sample selection during sample cloning' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project2) + # verify no samples currently selected in destination project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + # select 1 sample to clone + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + + # verify 1 sample selected in originating project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '1' + end + + # clone sample + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do + fill_in placeholder: I18n.t('projects.samples.clones.dialog.select_project'), with: @project2.full_path + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click + click_on I18n.t('projects.samples.clones.dialog.submit_button') + end + ### ACTIONS END ### + + ### VERIFY START ### + # verify no samples selected anymore + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + + # verify destination project still has no selected samples and one additional sample + Project.reset_counters(@project2.id, :samples_count) + visit namespace_project_samples_url(@namespace, @project2) + + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + + click_button I18n.t(:'projects.samples.index.select_all_button') + + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '21' + end + ### VERIFY END end test 'selecting / deselecting all samples' do @@ -1705,18 +1820,66 @@ class SamplesTest < ApplicationSystemTestCase text: I18n.t('projects.samples.index.create_export_button.label') end + test 'singular description within delete samples dialog' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within('tbody tr:first-child') do + # select sample1 + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.delete_samples_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', + sample_name: @sample1.name) + end + ### VERIFY END ### + end + + test 'plural description within delete samples dialog' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.delete_samples_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t( + 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' + ).gsub! 'COUNT_PLACEHOLDER', '3' + + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + end + ### VERIFY END ### + end + test 'delete multiple samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.delete_samples_button') within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') @@ -1732,9 +1895,9 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') @@ -1745,41 +1908,17 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'singular description within delete samples dialog' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within('tbody tr:first-child') do - # select sample1 - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.delete_samples_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', - sample_name: @sample1.name) - end - ### verify end ### - end - test 'delete single sample with remove link while all samples selected followed by multiple deletion' do # tests that localstorage does not contain a selected sample after it's destroyed - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # select all samples - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') # destroy sample1 with remove action link within '#samples-table table tbody tr:first-child' do @@ -1810,29 +1949,29 @@ class SamplesTest < ApplicationSystemTestCase assert_no_text @sample1.name click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') within 'div[role="alert"]' do assert_text I18n.t('projects.samples.index.no_samples') assert_text I18n.t('projects.samples.index.no_associated_samples') end - ### verify end ### + ### VERIFY END ### end test 'filtering samples by list of sample puids' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1860,20 +1999,20 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### actions and verify end ### + ### actions and VERIFY END ### end test 'filtering samples by list of sample names' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1881,9 +2020,9 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.name}, #{@sample2.name}" click_button I18n.t(:'components.list_filter.apply') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within '#samples-table table tbody' do assert_selector 'tr', count: 2 assert_selector "tr[id='#{@sample1.id}']" @@ -1891,20 +2030,20 @@ class SamplesTest < ApplicationSystemTestCase # sample30 filtered out assert_no_selector "tr[id='#{@sample30.id}']" end - ### verify end ### + ### VERIFY END ### end test 'can filter by large list of sample names or ids' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do |dialog| assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1913,15 +2052,15 @@ class SamplesTest < ApplicationSystemTestCase dialog.scroll_to(dialog.find('button', text: I18n.t(:'components.list_filter.apply')), align: :bottom) click_button I18n.t(:'components.list_filter.apply') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" end - ### verify end ### + ### VERIFY END ### end def long_filter_text From 2042c7c6615b2b187b60a969c2b7bf47c0eca581 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Fri, 13 Dec 2024 11:59:40 -0600 Subject: [PATCH 07/24] Revert "cleanup" This reverts commit 83a159a8c4f9f2db545aa5962c61a97c22b9baaa. --- db/schema.rb | 34 +- test/system/projects/samples_test.rb | 1003 +++++++++++--------------- 2 files changed, 449 insertions(+), 588 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index a0083dcf21..5dafb55105 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -714,34 +714,34 @@ SQL - create_trigger :logidze_on_users, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_users BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_attachments, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_attachments BEFORE INSERT OR UPDATE ON public.attachments FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_namespaces, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_namespaces BEFORE INSERT OR UPDATE ON public.namespaces FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_summary,updated_at,attachments_updated_at}') + create_trigger :logidze_on_automated_workflow_executions, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_automated_workflow_executions BEFORE INSERT OR UPDATE ON public.automated_workflow_executions FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + SQL + create_trigger :logidze_on_data_exports, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_data_exports BEFORE INSERT OR UPDATE ON public.data_exports FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL create_trigger :logidze_on_members, sql_definition: <<-SQL CREATE TRIGGER logidze_on_members BEFORE INSERT OR UPDATE ON public.members FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_samples, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_samples BEFORE INSERT OR UPDATE ON public.samples FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_provenance,updated_at,attachments_updated_at}') - SQL - create_trigger :logidze_on_personal_access_tokens, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_personal_access_tokens BEFORE INSERT OR UPDATE ON public.personal_access_tokens FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{last_used_at}') + create_trigger :logidze_on_namespace_bots, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_namespace_bots BEFORE INSERT OR UPDATE ON public.namespace_bots FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL create_trigger :logidze_on_namespace_group_links, sql_definition: <<-SQL CREATE TRIGGER logidze_on_namespace_group_links BEFORE INSERT OR UPDATE ON public.namespace_group_links FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL - create_trigger :logidze_on_attachments, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_attachments BEFORE INSERT OR UPDATE ON public.attachments FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_namespaces, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_namespaces BEFORE INSERT OR UPDATE ON public.namespaces FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_summary,updated_at,attachments_updated_at}') SQL - create_trigger :logidze_on_data_exports, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_data_exports BEFORE INSERT OR UPDATE ON public.data_exports FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_personal_access_tokens, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_personal_access_tokens BEFORE INSERT OR UPDATE ON public.personal_access_tokens FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{last_used_at}') SQL - create_trigger :logidze_on_namespace_bots, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_namespace_bots BEFORE INSERT OR UPDATE ON public.namespace_bots FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_samples, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_samples BEFORE INSERT OR UPDATE ON public.samples FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at', '{created_at,metadata_provenance,updated_at,attachments_updated_at}') SQL - create_trigger :logidze_on_automated_workflow_executions, sql_definition: <<-SQL - CREATE TRIGGER logidze_on_automated_workflow_executions BEFORE INSERT OR UPDATE ON public.automated_workflow_executions FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') + create_trigger :logidze_on_users, sql_definition: <<-SQL + CREATE TRIGGER logidze_on_users BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW WHEN ((COALESCE(current_setting('logidze.disabled'::text, true), ''::text) <> 'on'::text)) EXECUTE FUNCTION logidze_logger('null', 'updated_at') SQL end diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index 54abb347ae..fc9237d472 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -60,9 +60,13 @@ class SamplesTest < ApplicationSystemTestCase end end end + + # pagy + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) end - test 'edit and delete row actions render for user with Owner role' do + test 'edit and delete row actions render for user with role == Owner in samples table' do visit namespace_project_samples_url(@namespace, @project) within("tr[id='#{@sample1.id}'] td:last-child") do @@ -71,7 +75,7 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'edit row action render for user with Maintainer role' do + test 'edit row action render for user with role == Maintainer in samples table' do login_as users(:joan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -81,11 +85,11 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'no row actions for user with role < Maintainer' do + test 'no row actions for user with role < Maintainer in samples table' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) within('#samples-table table thead tr:first-child') do - # attachments_updated_at is the last column, action column does not exist + # attachments updated at is the last column, action column does not exist assert_selector 'th:last-child', text: I18n.t('samples.table_component.attachments_updated_at').upcase assert_no_selector 'th:last-child', text: I18n.t('samples.table_component.action').upcase end @@ -125,67 +129,67 @@ class SamplesTest < ApplicationSystemTestCase assert_no_selector "input#sample_#{@sample1.id}" end - test 'User with role >= Analyst sees workflow execution link' do + test 'User with role >= Analyst sees workflow execution link in samples index' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role < Analyst does not see workflow execution link' do + test 'User with role < Analyst does not see workflow execution link in samples index' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role >= Analyst sees create export button' do + test 'User with role >= Analyst sees create export button in samples index' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role < Analyst does not see create export button' do + test 'User with role < Analyst does not see create export button in samples index' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role >= Maintainer sees import metadata button' do + test 'User with role >= Maintainer sees import metadata link in samples index' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role < Maintainer does not see import metadata button' do + test 'User with role < Maintainer does not see import metadata link in samples index' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role >= Maintainer sees new sample button' do + test 'User with role >= Maintainer sees new sample button in samples index' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role < Maintainer does not see new sample button' do + test 'User with role < Maintainer does not see new sample button in samples index' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role >= Maintainer sees delete samples button' do + test 'User with role >= Maintainer sees delete samples button in samples index' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.delete_samples_button') end - test 'User with role < Maintainer does not see delete samples button' do + test 'User with role < Maintainer does not see delete samples button in samples index' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -200,16 +204,12 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t(:'action_policy.policy.project.sample_listing?', name: @project.name) end - test 'create sample' do - ### SETUP START ### + test 'should create sample' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - within('#samples-table table tbody') do - # sample does not currently exist - assert_no_text 'New Name' - end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # launch dialog click_on I18n.t('projects.samples.index.new_button') @@ -217,7 +217,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t('activerecord.attributes.sample.description'), with: 'A sample description' fill_in I18n.t('activerecord.attributes.sample.name'), with: 'New Name' click_on I18n.t('projects.samples.new.submit_button') - ### ACTIONS END ### + ### actions end ### ### results start ### # flash msg @@ -232,12 +232,12 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'edit sample' do - ### SETUP START ### + test 'should update Sample' do + ### setup start ### visit namespace_project_sample_url(@namespace, @project, @sample1) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # nav to edit sample page click_on I18n.t('projects.samples.show.edit_button') @@ -245,7 +245,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in 'Description', with: 'A new description' fill_in 'Name', with: 'New Sample Name' click_on I18n.t('projects.samples.edit.submit_button') - ### ACTIONS END ### + ### actions end ### ### results start ### # flash msg @@ -257,8 +257,8 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'destroy sample from sample show page' do - ### SETUP START ### + test 'should destroy Sample from sample show page' do + ### setup start ### # nav to samples index and verify sample exists within table visit namespace_project_samples_url(@namespace, @project) assert_selector "#samples-table table tbody tr[id='#{@sample1.id}']" @@ -266,40 +266,37 @@ class SamplesTest < ApplicationSystemTestCase # nav to sample show visit namespace_project_sample_url(@namespace, @project, @sample1) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ## + ### actions start ## click_link I18n.t(:'projects.samples.index.remove_button') within('#turbo-confirm[open]') do click_button I18n.t(:'components.confirmation.confirm') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) - # redirected to samples index - assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 # deleted sample row no longer exists assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" + # redirected to samples index + assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 # remaining samples still appear on table assert_selector '#samples-table table tbody tr', count: 2 - ### VERIFY END ### + ### verify end ### end - test 'should destroy Sample from samples table' do - ### SETUP START ### + test 'should destroy Sample from sample listing page' do + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### - - ### ACTIONS START ### + ### setup end ### within("tr[id='#{@sample1.id}']") do - # click remove action click_link I18n.t('projects.samples.index.remove_button') end @@ -307,9 +304,9 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t('projects.samples.deletions.new_deletion_dialog.description', sample_name: @sample1.name) click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end - ### ACTIONS END ### + ### setup end ### - ### VERIFY START ### + ### verify start ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) @@ -319,69 +316,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 # remaining samples still in table assert_selector '#samples-table table tbody tr', count: 2 - ### VERIFY END ### + ### verify end ### end - test 'transfer dialog sample listing' do - ### SETUP START ### - samples = @project.samples.pluck(:puid, :name) - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.transfer_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#list_selections') do - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - ### VERIFY END ### - end - - test 'transfer dialog with plural description' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.transfer_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', - '3') - end - ### VERIFY END ### - end - - test 'transfer dialog with singular description' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.transfer_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.singular') - end - ### VERIFY END ### - end - - test 'transfer samples' do - ### SETUP START ### + test 'should transfer samples' do + ### setup start ### # show destination project has 20 samples prior to transfer visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, @@ -392,28 +331,38 @@ class SamplesTest < ApplicationSystemTestCase ) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### samples = @project.samples.pluck(:puid, :name) - # select all 3 samples - click_button I18n.t(:'projects.samples.index.select_all_button') + within('#samples-table table tbody') do + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do + # verify 'plural' form of description renders + assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', + '3') + # verify sample puid and name are listed in dialog list + within %(turbo-frame[id="list_selections"]) do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end # select destination project find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # flash msg assert_text I18n.t('projects.samples.transfers.create.success') # originating project no longer has samples assert_text I18n.t('projects.samples.index.no_samples') - # destination project received transferred samples visit namespace_project_samples_url(@namespace, @project2) within '#samples-table table tbody' do samples.each do |sample| @@ -421,42 +370,60 @@ class SamplesTest < ApplicationSystemTestCase assert_text sample[1] end end - ### VERIFY END ### + ### verify end ### + end + + test 'transfer dialog with single sample' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.transfer_button') + ### actions end ### + + ### verify start ### + within('#dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.singular') + end + ### verify end ### end test 'should not transfer samples with session storage cleared' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - # select samples - click_button I18n.t(:'projects.samples.index.select_all_button') - # clear localstorage + ### actions start ### + within '#samples-table table tbody' do + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end Capybara.execute_script 'sessionStorage.clear()' - # launch transfer dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # samples listing should no longer appear in dialog assert_no_selector '#list_selections' # error msg displayed in dialog assert_text I18n.t('projects.samples.transfers.create.no_samples_transferred_error') end - ### VERIFY END ### + ### verify end ### end test 'transfer samples with and without same name in destination project' do - # only samples without a matching name to samples in destination project will transfer + # only samples without a matching name will transfer - ### SETUP START ### + ### setup start ### namespace = groups(:subgroup1) project25 = projects(:project25) @@ -464,23 +431,26 @@ class SamplesTest < ApplicationSystemTestCase visit namespace_project_samples_url(namespace, project25) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 2, count: 2, locale: @user.locale)) - # 3 samples in originating project visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### + within '#samples-table table tbody' do + all('input[type=checkbox]').each do |checkbox| + checkbox.click unless checkbox.checked? + end + end click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### within('#dialog') do # error messages in dialog assert_text I18n.t('projects.samples.transfers.create.error') @@ -502,114 +472,117 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### VERIFY END ### + ### verify end ### end test 'sample transfer project listing should be empty for maintainer if no other projects in hierarchy' do - ### SETUP START ### + ### setup start ### login_as users(:user28) namespace = groups(:group_hotel) project = projects(:projectHotel) visit namespace_project_samples_url(namespace, project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### + within '#samples-table table tbody' do + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end click_link I18n.t('projects.samples.index.transfer_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### within('#dialog') do # no available destination projects assert_selector "input[placeholder='#{I18n.t('projects.samples.transfers.dialog.no_available_projects')}']" end - ### VERIFY END ### + ### verify end ### end - test 'updating sample selection during transfer samples' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project2) + test 'should update pagination & selection during transfer samples' do + namespace1 = groups(:group_one) + namespace17 = groups(:group_seventeen) + project38 = projects(:project38) + project2 = projects(:project2) + samples = [samples(:bulk_sample1), samples(:bulk_sample2)] - # verify no samples currently selected in destination project - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + Project.reset_counters(project38.id, :samples_count) + visit namespace_project_samples_url(namespace17, project38) + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 200, + locale: @user.locale)) - ### ACTIONS START ### - # select 1 sample to transfer - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end + click_button I18n.t(:'projects.samples.index.select_all_button') - # verify 1 sample selected in originating project + within 'tbody' do + assert_selector 'input[name="sample_ids[]"]:checked', count: 20 + end within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" - assert_selector 'strong[data-selection-target="selected"]', text: '1' + assert_text 'Samples: 200' + assert_selector 'strong[data-selection-target="selected"]', text: '200' end - # transfer sample - click_link I18n.t('projects.samples.index.transfer_button') - within('#dialog') do + click_link I18n.t('projects.samples.index.transfer_button'), match: :first + within('span[data-controller-connected="true"] dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', '200') + within %(turbo-frame[id="list_selections"]) do + samples.pluck(:puid, :name).each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### ACTIONS END ### - ### VERIFY START ### - # verify no samples selected anymore - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 2" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end + # Check samples selected are [] and has the proper number of samples + assert_text I18n.t(:'projects.samples.index.no_samples') - # verify destination project still has no selected samples and one additional sample - visit namespace_project_samples_url(@namespace, @project2) + Project.reset_counters(project2.id, :samples_count) + visit namespace_project_samples_url(namespace1, project2) - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 220, + locale: @user.locale)) click_button I18n.t(:'projects.samples.index.select_all_button') within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" - assert_selector 'strong[data-selection-target="selected"]', text: '21' + sample_counts = all('strong') + total_samples = sample_counts[0].text.to_i + selected_samples = sample_counts[1].text.to_i + assert selected_samples <= total_samples end - ### VERIFY END end test 'empty state of transfer sample project selection' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - # select samples - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### + within '#samples-table table tbody' do + # check samples + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end # launch dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do # fill destination input find('input#select2-input').fill_in with: 'invalid project name or puid' - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('projects.samples.transfers.dialog.empty_state') - ### VERIFY END ### + ### verify end ### end end test 'can search the list of samples by name' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) # partial name search - filter_text = @sample1.name[-3..] + filter_text = @sample1.name[-3..-1] assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) @@ -617,34 +590,34 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 1 assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### VERIFY END ### + ### verify end ### end test 'limit persists through filter and sort actions' do # tests limit change and that it persists through other actions (filter) - ### SETUP START ### + ### setup start ### sample3 = samples(:sample3) visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### actions and VERIFY START ### + ### actions and verify start ### within('div#limit-component') do # set table limit to 10 find('button').click @@ -671,15 +644,18 @@ class SamplesTest < ApplicationSystemTestCase # verify limit is still 10 assert_selector 'div#limit-component button div span', text: '10' - ### actions and VERIFY END ### + ### actions and verify end ### end test 'can sort samples' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - ### ACTION and VERIFY START ### + assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, + locale: @user.locale)) + ### setup end ### + + ### action and verify start ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -708,19 +684,19 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### ACTION and VERIFY END ### + ### action and verify end ### end test 'sort samples attachments_updated_at_nulls_last' do # attachments_updated_at_nulls_last sorts null data together - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### action and VERIFY START ### + ### action and verify start ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -749,15 +725,16 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### action and VERIFY END ### + ### action and verify end ### end test 'sort persists through limit and filter' do - ### SETUP START ### + # tests that sort persists through other actions (filter) + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### actions and VERIFY START ### + ### actions and verify start ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -777,107 +754,105 @@ class SamplesTest < ApplicationSystemTestCase # verify sort is still applied assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - ### actions and VERIFY END ### + ### actions and verify end ### end test 'filter by name' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # only sample1 exists within table assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### VERIFY END ### + ### verify end ### end test 'filter by puid' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample2.puid find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # only sample2 exists within table assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### VERIFY END ### + ### verify end ### end test 'filter highlighting for sample name' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### - # verify table still contains all samples + ### verify start ### + # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: 'Sample', count: 3 - ### VERIFY END ### end test 'filter highlighting for sample puid' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: @sample1.puid - ### VERIFY END ### end test 'filter persists through sort and limit actions' do - ### SETUP START ### - filter_text = @sample1.name + # tests that filter persists through other actions (sort) + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### SETUP END ### + ### setup end ### - ### ACTIONS and VERIFY START ### + ### actions and verify start ### # apply filter - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) assert_selector "tr[id='#{@sample1.id}']" @@ -895,7 +870,7 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal filter_text, input['value'] + assert_equal @sample1.name, input['value'] end # set limit @@ -911,24 +886,24 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal filter_text, input['value'] + assert_equal @sample1.name, input['value'] end - ### VERIFY END ### + ### verify end ### end test 'filter persists through page refresh' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) filter_text = @sample1.name - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" @@ -943,15 +918,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### VERIFY END ### + ### verify end ### end test 'sort persists through page refresh' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -960,21 +935,22 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### ACTIONS END ### + ### actions end ### + + ### verify start ### - ### VERIFY START ### # refresh visit namespace_project_samples_url(@namespace, @project) # verify sort is still enabled assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - # verify table ordering is still in sorted state + # verify table ordering is still in changed/sorted state assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### VERIFY END ### + ### verify end ### end test 'should import metadata via csv' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -996,19 +972,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - # start import + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### - # success msg + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1019,7 +993,7 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # sample 1 and 2 metadata is updated + # sample 1 and 2 have no value current for metadatafield 1 and 2 within("tr[id='#{@sample1.id}']") do assert_selector 'td:nth-child(6)', text: '10' assert_selector 'td:nth-child(7)', text: '20' @@ -1031,11 +1005,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '35' end end - ### VERIFY END ### + ### verify end ### end test 'should import metadata via xls' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1056,18 +1030,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - # start import + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xls') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1093,11 +1066,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### VERIFY END ### + ### verify end ### end test 'should import metadata via xlsx' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1118,17 +1091,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xlsx') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1154,54 +1127,51 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### VERIFY END ### + ### verify end ### end test 'should not import metadata via invalid file type' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/invalid.txt') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### within('#dialog') do - # error msg assert_text I18n.t('services.samples.metadata.import_file.invalid_file_extension') end - ### VERIFY END ### + ### verify end ### end test 'should import metadata with ignore empty values' do - # enabled ignore empty values will leave sample metadata values unchanged - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import and will be left unchanged after import + # value for metadatafield1, which is blank on the csv to import assert_selector 'td:nth-child(6)', text: 'value1' end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option - # enable ignore empty values find('input#file_import_ignore_empty_values').click click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1210,32 +1180,30 @@ class SamplesTest < ApplicationSystemTestCase # unchanged value assert_selector 'td:nth-child(6)', text: 'value1' end - ### VERIFY END ### + ### verify end ### end test 'should import metadata without ignore empty values' do - # disabled ignore empty values will delete any metadata values that are empty on the import - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import and will be deleted by the import + # value for metadatafield1, which is blank on the csv to import assert_selector 'td:nth-child(6)', text: 'value1' end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option - # leave ignore empty values disabled assert_not find('input#file_import_ignore_empty_values').checked? click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1243,71 +1211,70 @@ class SamplesTest < ApplicationSystemTestCase # value is deleted for metadatafield1 assert_selector 'td:nth-child(6)', text: '' end - ### VERIFY END ### end test 'should not import metadata with duplicate header errors' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/duplicate_headers.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # error msg assert_text I18n.t('services.samples.metadata.import_file.duplicate_column_names') - ### VERIFY END ### + ### verify end ### end end test 'should not import metadata with missing metadata row errors' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_rows.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_row') - ### VERIFY END ### + ### verify end ### end end test 'should not import metadata with missing metadata column errors' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_columns.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_column') - ### VERIFY END ### + ### verify end ### end end test 'should partially import metadata with missing sample errors' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1325,18 +1292,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_link I18n.t('projects.samples.index.import_metadata_button') + ### actions start ### + click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/mixed_project_samples.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### - # sample 3 does not exist in current project + ### verify start ### assert_text I18n.t('services.samples.metadata.import_file.sample_not_found_within_project', sample_puid: 'Project 2 Sample 3') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1355,33 +1321,33 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '30' end end - ### VERIFY END ### + ### verify end ### end test 'should not import metadata with analysis values' do - ### SETUP START ### + ### setup start ### subgroup12aa = groups(:subgroup_twelve_a_a) project31 = projects(:project31) sample34 = samples(:sample34) visit namespace_project_samples_url(subgroup12aa, project31) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click - # metadata that does not overwriting analysis values will still be added + # metadata not overwriting analysis values will still be added assert_selector '#samples-table table thead tr th', count: 8 within('#samples-table table thead') do assert_no_text 'METADATAFIELD3' end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_analysis_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('services.samples.metadata.import_file.sample_metadata_fields_not_updated', sample_name: sample34.name, metadata_fields: 'metadatafield1') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1392,86 +1358,27 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # new metadata value + # new metadata values for sample 1 and 2 within("tr[id='#{sample34.id}']") do assert_selector 'td:nth-child(8)', text: '20' end - ### VERIFY END ### - end - end - - test 'clone dialog sample listing' do - ### SETUP START ### - samples = @project.samples.pluck(:puid, :name) - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.clone_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#list_selections') do - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end + ### verify end ### end - ### VERIFY END ### - end - - test 'singular clone dialog description' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.clone_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t('projects.samples.clones.dialog.description.singular') - end - ### VERIFY END ### - end - - test 'plural clone dialog description' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.clone_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t( - 'projects.samples.clones.dialog.description.plural' - ).gsub! 'COUNT_PLACEHOLDER', '2' - end - ### VERIFY END ### end test 'should clone samples' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project2) - # verify samples 1 and 2 do not exist in project2 + # samples 1 and 2 do not exist in project2 within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name end visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### # select samples 1 and 2 for cloning within '#samples-table table tbody' do find("input#sample_#{@sample1.id}").click @@ -1479,13 +1386,23 @@ class SamplesTest < ApplicationSystemTestCase end click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do + # plural dialog description since > 1 sample selected + assert_text I18n.t( + 'projects.samples.clones.dialog.description.plural' + ).gsub! 'COUNT_PLACEHOLDER', '2' + within('#list_selections') do + assert_text @sample1.puid + assert_text @sample1.name + assert_text @sample2.puid + assert_text @sample2.name + end find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # flash msg assert_text I18n.t('projects.samples.clones.create.success') # samples still exist within samples table of originating project @@ -1500,60 +1417,81 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### VERIFY END ### + ### verify end ### + end + + test 'singular clone dialog description' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.clone_button') + ### actions end ### + + ### verify start ### + within('#dialog') do + assert_text I18n.t('projects.samples.clones.dialog.description.singular') + end + ### verify end ### end test 'should not clone samples with session storage cleared' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - # clear localstorage + ### actions start ### + within '#samples-table table tbody' do + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end Capybara.execute_script 'sessionStorage.clear()' click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### - # sample listing should not be in error dialog - assert_no_selector '#list_selections' - # error msg + ### verify start ### + assert_no_selector "turbo-frame[id='list_selections']" assert_text I18n.t('projects.samples.clones.create.no_samples_cloned_error') assert_text I18n.t('services.samples.clone.empty_sample_ids') - ### VERIFY END ### + ### verify end ### end end test 'should not clone some samples' do namespace = groups(:subgroup1) project25 = projects(:project25) - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(namespace, project25) - # sample30's name already exists in project25 samples table, samples1 and 2 do not + # samples 1 and 2 do not exist in project25 samples table within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name - assert_text @sample30.name end visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### + within '#samples-table table tbody' do + # check all samples. sample30 will error due to name collision in project25 + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') + end + ### actions end ### - ### ACTIONS END ### - - ### VERIFY START ### + ### verify start ### + within %(turbo-frame[id="samples_dialog"]) do # errors that a sample with the same name as sample30 already exists in project25 assert_text I18n.t('projects.samples.clones.create.error') assert_text I18n.t('services.samples.clone.sample_exists', sample_puid: @sample30.puid, @@ -1567,100 +1505,47 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### VERIFY END ### + ### verify end ### end test 'empty state of destination project selection for sample cloning' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START #### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start #### + within '#samples-table table tbody' do + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').fill_in with: 'invalid project name or puid' - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('projects.samples.clones.dialog.empty_state') - ### VERIFY END ### + ### verify end ### end end test 'no available destination projects to clone samples' do - ### SETUP START ### + ### setup start ### sign_in users(:jean_doe) visit namespace_project_samples_url(namespaces_user_namespaces(:john_doe_namespace), projects(:john_doe_project2)) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.clone_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert "input[placeholder='#{I18n.t('projects.samples.clones.dialog.no_available_projects')}']" - end - ### VERIFY END ### - end - - test 'updating sample selection during sample cloning' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project2) - # verify no samples currently selected in destination project - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - # select 1 sample to clone + ### actions start ### within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - - # verify 1 sample selected in originating project - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" - assert_selector 'strong[data-selection-target="selected"]', text: '1' - end - - # clone sample click_link I18n.t('projects.samples.index.clone_button') - within('#dialog') do - fill_in placeholder: I18n.t('projects.samples.clones.dialog.select_project'), with: @project2.full_path - find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click - click_on I18n.t('projects.samples.clones.dialog.submit_button') - end - ### ACTIONS END ### - - ### VERIFY START ### - # verify no samples selected anymore - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end - - # verify destination project still has no selected samples and one additional sample - Project.reset_counters(@project2.id, :samples_count) - visit namespace_project_samples_url(@namespace, @project2) + ### actions end ### - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" - assert_selector 'strong[data-selection-target="selected"]', text: '0' - end - - click_button I18n.t(:'projects.samples.index.select_all_button') - - within 'tfoot' do - assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" - assert_selector 'strong[data-selection-target="selected"]', text: '21' + ### verify start ### + within('#dialog') do + assert "input[placeholder='#{I18n.t('projects.samples.clones.dialog.no_available_projects')}']" end - ### VERIFY END + ### verify end ### end test 'selecting / deselecting all samples' do @@ -1820,66 +1705,18 @@ class SamplesTest < ApplicationSystemTestCase text: I18n.t('projects.samples.index.create_export_button.label') end - test 'singular description within delete samples dialog' do - ### SETUP START ### - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - within('tbody tr:first-child') do - # select sample1 - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.delete_samples_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', - sample_name: @sample1.name) - end - ### VERIFY END ### - end - - test 'plural description within delete samples dialog' do - ### SETUP START ### - samples = @project.samples.pluck(:puid, :name) - visit namespace_project_samples_url(@namespace, @project) - ### SETUP END ### - - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') - click_link I18n.t('projects.samples.index.delete_samples_button') - ### ACTIONS END ### - - ### VERIFY START ### - within('#dialog') do - assert_text I18n.t( - 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' - ).gsub! 'COUNT_PLACEHOLDER', '3' - - within('#list_selections') do - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - end - ### VERIFY END ### - end - test 'delete multiple samples' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### click_link I18n.t('projects.samples.index.delete_samples_button') within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') @@ -1895,9 +1732,9 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') @@ -1908,17 +1745,41 @@ class SamplesTest < ApplicationSystemTestCase end end + test 'singular description within delete samples dialog' do + ### setup start ### + visit namespace_project_samples_url(@namespace, @project) + ### setup end ### + + ### actions start ### + within('tbody tr:first-child') do + # select sample1 + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.delete_samples_button') + ### actions end ### + + ### verify start ### + within('#dialog') do + assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', + sample_name: @sample1.name) + end + ### verify end ### + end + test 'delete single sample with remove link while all samples selected followed by multiple deletion' do # tests that localstorage does not contain a selected sample after it's destroyed - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### - click_button I18n.t(:'projects.samples.index.select_all_button') + ### actions start ### + within '#samples-table table tbody' do + # select all samples + all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } + end # destroy sample1 with remove action link within '#samples-table table tbody tr:first-child' do @@ -1949,29 +1810,29 @@ class SamplesTest < ApplicationSystemTestCase assert_no_text @sample1.name click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') within 'div[role="alert"]' do assert_text I18n.t('projects.samples.index.no_samples') assert_text I18n.t('projects.samples.index.no_associated_samples') end - ### VERIFY END ### + ### verify end ### end test 'filtering samples by list of sample puids' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### SETUP END ### + ### setup end ### - ### actions and VERIFY START ### + ### actions and verify start ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1999,20 +1860,20 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### actions and VERIFY END ### + ### actions and verify end ### end test 'filtering samples by list of sample names' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -2020,9 +1881,9 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.name}, #{@sample2.name}" click_button I18n.t(:'components.list_filter.apply') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### within '#samples-table table tbody' do assert_selector 'tr', count: 2 assert_selector "tr[id='#{@sample1.id}']" @@ -2030,20 +1891,20 @@ class SamplesTest < ApplicationSystemTestCase # sample30 filtered out assert_no_selector "tr[id='#{@sample30.id}']" end - ### VERIFY END ### + ### verify end ### end test 'can filter by large list of sample names or ids' do - ### SETUP START ### + ### setup start ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### SETUP END ### + ### setup end ### - ### ACTIONS START ### + ### actions start ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do |dialog| assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -2052,15 +1913,15 @@ class SamplesTest < ApplicationSystemTestCase dialog.scroll_to(dialog.find('button', text: I18n.t(:'components.list_filter.apply')), align: :bottom) click_button I18n.t(:'components.list_filter.apply') end - ### ACTIONS END ### + ### actions end ### - ### VERIFY START ### + ### verify start ### within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" end - ### VERIFY END ### + ### verify end ### end def long_filter_text From 1d8167f71df80be93f0cbcfb145d0fd188998900 Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Fri, 13 Dec 2024 12:00:27 -0600 Subject: [PATCH 08/24] cleanup --- test/system/projects/samples_test.rb | 1003 +++++++++++++++----------- 1 file changed, 571 insertions(+), 432 deletions(-) diff --git a/test/system/projects/samples_test.rb b/test/system/projects/samples_test.rb index fc9237d472..54abb347ae 100644 --- a/test/system/projects/samples_test.rb +++ b/test/system/projects/samples_test.rb @@ -60,13 +60,9 @@ class SamplesTest < ApplicationSystemTestCase end end end - - # pagy - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) end - test 'edit and delete row actions render for user with role == Owner in samples table' do + test 'edit and delete row actions render for user with Owner role' do visit namespace_project_samples_url(@namespace, @project) within("tr[id='#{@sample1.id}'] td:last-child") do @@ -75,7 +71,7 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'edit row action render for user with role == Maintainer in samples table' do + test 'edit row action render for user with Maintainer role' do login_as users(:joan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -85,11 +81,11 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'no row actions for user with role < Maintainer in samples table' do + test 'no row actions for user with role < Maintainer' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) within('#samples-table table thead tr:first-child') do - # attachments updated at is the last column, action column does not exist + # attachments_updated_at is the last column, action column does not exist assert_selector 'th:last-child', text: I18n.t('samples.table_component.attachments_updated_at').upcase assert_no_selector 'th:last-child', text: I18n.t('samples.table_component.action').upcase end @@ -129,67 +125,67 @@ class SamplesTest < ApplicationSystemTestCase assert_no_selector "input#sample_#{@sample1.id}" end - test 'User with role >= Analyst sees workflow execution link in samples index' do + test 'User with role >= Analyst sees workflow execution link' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role < Analyst does not see workflow execution link in samples index' do + test 'User with role < Analyst does not see workflow execution link' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'span[class="sr-only"]', text: I18n.t('projects.samples.index.workflows.button_sr') end - test 'User with role >= Analyst sees create export button in samples index' do + test 'User with role >= Analyst sees create export button' do login_as users(:james_doe) visit namespace_project_samples_url(@namespace, @project) assert_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role < Analyst does not see create export button in samples index' do + test 'User with role < Analyst does not see create export button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'button', text: I18n.t('projects.samples.index.create_export_button.label') end - test 'User with role >= Maintainer sees import metadata link in samples index' do + test 'User with role >= Maintainer sees import metadata button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role < Maintainer does not see import metadata link in samples index' do + test 'User with role < Maintainer does not see import metadata button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.import_metadata_button') end - test 'User with role >= Maintainer sees new sample button in samples index' do + test 'User with role >= Maintainer sees new sample button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role < Maintainer does not see new sample button in samples index' do + test 'User with role < Maintainer does not see new sample button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) assert_no_selector 'a', text: I18n.t('projects.samples.index.new_button') end - test 'User with role >= Maintainer sees delete samples button in samples index' do + test 'User with role >= Maintainer sees delete samples button' do visit namespace_project_samples_url(@namespace, @project) assert_selector 'a', text: I18n.t('projects.samples.index.delete_samples_button') end - test 'User with role < Maintainer does not see delete samples button in samples index' do + test 'User with role < Maintainer does not see delete samples button' do login_as users(:ryan_doe) visit namespace_project_samples_url(@namespace, @project) @@ -204,12 +200,16 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t(:'action_policy.policy.project.sample_listing?', name: @project.name) end - test 'should create sample' do - ### setup start ### + test 'create sample' do + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + within('#samples-table table tbody') do + # sample does not currently exist + assert_no_text 'New Name' + end + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # launch dialog click_on I18n.t('projects.samples.index.new_button') @@ -217,7 +217,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t('activerecord.attributes.sample.description'), with: 'A sample description' fill_in I18n.t('activerecord.attributes.sample.name'), with: 'New Name' click_on I18n.t('projects.samples.new.submit_button') - ### actions end ### + ### ACTIONS END ### ### results start ### # flash msg @@ -232,12 +232,12 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'should update Sample' do - ### setup start ### + test 'edit sample' do + ### SETUP START ### visit namespace_project_sample_url(@namespace, @project, @sample1) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # nav to edit sample page click_on I18n.t('projects.samples.show.edit_button') @@ -245,7 +245,7 @@ class SamplesTest < ApplicationSystemTestCase fill_in 'Description', with: 'A new description' fill_in 'Name', with: 'New Sample Name' click_on I18n.t('projects.samples.edit.submit_button') - ### actions end ### + ### ACTIONS END ### ### results start ### # flash msg @@ -257,8 +257,8 @@ class SamplesTest < ApplicationSystemTestCase ### results end ### end - test 'should destroy Sample from sample show page' do - ### setup start ### + test 'destroy sample from sample show page' do + ### SETUP START ### # nav to samples index and verify sample exists within table visit namespace_project_samples_url(@namespace, @project) assert_selector "#samples-table table tbody tr[id='#{@sample1.id}']" @@ -266,37 +266,40 @@ class SamplesTest < ApplicationSystemTestCase # nav to sample show visit namespace_project_sample_url(@namespace, @project, @sample1) - ### setup end ### + ### SETUP END ### - ### actions start ## + ### ACTIONS START ## click_link I18n.t(:'projects.samples.index.remove_button') within('#turbo-confirm[open]') do click_button I18n.t(:'components.confirmation.confirm') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) - # deleted sample row no longer exists - assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" # redirected to samples index assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 + # deleted sample row no longer exists + assert_no_selector "#samples-table table tbody tr[id='#{@sample1.id}']" # remaining samples still appear on table assert_selector '#samples-table table tbody tr', count: 2 - ### verify end ### + ### VERIFY END ### end - test 'should destroy Sample from sample listing page' do - ### setup start ### + test 'should destroy Sample from samples table' do + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### + + ### ACTIONS START ### within("tr[id='#{@sample1.id}']") do + # click remove action click_link I18n.t('projects.samples.index.remove_button') end @@ -304,9 +307,9 @@ class SamplesTest < ApplicationSystemTestCase assert_text I18n.t('projects.samples.deletions.new_deletion_dialog.description', sample_name: @sample1.name) click_button I18n.t('projects.samples.deletions.new_deletion_dialog.submit_button') end - ### setup end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy.success', sample_name: @sample1.name, project_name: @project.namespace.human_name) @@ -316,11 +319,69 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'h1', text: I18n.t(:'projects.samples.index.title'), count: 1 # remaining samples still in table assert_selector '#samples-table table tbody tr', count: 2 - ### verify end ### + ### VERIFY END ### end - test 'should transfer samples' do - ### setup start ### + test 'transfer dialog sample listing' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + ### VERIFY END ### + end + + test 'transfer dialog with plural description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', + '3') + end + ### VERIFY END ### + end + + test 'transfer dialog with singular description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.transfer_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.transfers.dialog.description.singular') + end + ### VERIFY END ### + end + + test 'transfer samples' do + ### SETUP START ### # show destination project has 20 samples prior to transfer visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, @@ -331,38 +392,28 @@ class SamplesTest < ApplicationSystemTestCase ) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### samples = @project.samples.pluck(:puid, :name) - within('#samples-table table tbody') do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + # select all 3 samples + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do - # verify 'plural' form of description renders - assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', - '3') - # verify sample puid and name are listed in dialog list - within %(turbo-frame[id="list_selections"]) do - samples.each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end # select destination project find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.transfers.create.success') # originating project no longer has samples assert_text I18n.t('projects.samples.index.no_samples') + # destination project received transferred samples visit namespace_project_samples_url(@namespace, @project2) within '#samples-table table tbody' do samples.each do |sample| @@ -370,60 +421,42 @@ class SamplesTest < ApplicationSystemTestCase assert_text sample[1] end end - ### verify end ### - end - - test 'transfer dialog with single sample' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.transfer_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.singular') - end - ### verify end ### + ### VERIFY END ### end test 'should not transfer samples with session storage cleared' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + # select samples + click_button I18n.t(:'projects.samples.index.select_all_button') + # clear localstorage Capybara.execute_script 'sessionStorage.clear()' + # launch transfer dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # samples listing should no longer appear in dialog assert_no_selector '#list_selections' # error msg displayed in dialog assert_text I18n.t('projects.samples.transfers.create.no_samples_transferred_error') end - ### verify end ### + ### VERIFY END ### end test 'transfer samples with and without same name in destination project' do - # only samples without a matching name will transfer + # only samples without a matching name to samples in destination project will transfer - ### setup start ### + ### SETUP START ### namespace = groups(:subgroup1) project25 = projects(:project25) @@ -431,26 +464,23 @@ class SamplesTest < ApplicationSystemTestCase visit namespace_project_samples_url(namespace, project25) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 2, count: 2, locale: @user.locale)) + # 3 samples in originating project visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each do |checkbox| - checkbox.click unless checkbox.checked? - end - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do # error messages in dialog assert_text I18n.t('projects.samples.transfers.create.error') @@ -472,117 +502,114 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'sample transfer project listing should be empty for maintainer if no other projects in hierarchy' do - ### setup start ### + ### SETUP START ### login_as users(:user28) namespace = groups(:group_hotel) project = projects(:projectHotel) visit namespace_project_samples_url(namespace, project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.transfer_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do # no available destination projects assert_selector "input[placeholder='#{I18n.t('projects.samples.transfers.dialog.no_available_projects')}']" end - ### verify end ### + ### VERIFY END ### end - test 'should update pagination & selection during transfer samples' do - namespace1 = groups(:group_one) - namespace17 = groups(:group_seventeen) - project38 = projects(:project38) - project2 = projects(:project2) - samples = [samples(:bulk_sample1), samples(:bulk_sample2)] - - Project.reset_counters(project38.id, :samples_count) - visit namespace_project_samples_url(namespace17, project38) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 200, - locale: @user.locale)) + test 'updating sample selection during transfer samples' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project2) - click_button I18n.t(:'projects.samples.index.select_all_button') + # verify no samples currently selected in destination project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### - within 'tbody' do - assert_selector 'input[name="sample_ids[]"]:checked', count: 20 + ### ACTIONS START ### + # select 1 sample to transfer + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click end + + # verify 1 sample selected in originating project within 'tfoot' do - assert_text 'Samples: 200' - assert_selector 'strong[data-selection-target="selected"]', text: '200' + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '1' end - click_link I18n.t('projects.samples.index.transfer_button'), match: :first - within('span[data-controller-connected="true"] dialog') do - assert_text I18n.t('projects.samples.transfers.dialog.description.plural').gsub!('COUNT_PLACEHOLDER', '200') - within %(turbo-frame[id="list_selections"]) do - samples.pluck(:puid, :name).each do |sample| - assert_text sample[0] - assert_text sample[1] - end - end - + # transfer sample + click_link I18n.t('projects.samples.index.transfer_button') + within('#dialog') do find('input#select2-input').click - find("button[data-viral--select2-primary-param='#{project2.full_path}']").click + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.transfers.dialog.submit_button') end + ### ACTIONS END ### - # Check samples selected are [] and has the proper number of samples - assert_text I18n.t(:'projects.samples.index.no_samples') + ### VERIFY START ### + # verify no samples selected anymore + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 2" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end - Project.reset_counters(project2.id, :samples_count) - visit namespace_project_samples_url(namespace1, project2) + # verify destination project still has no selected samples and one additional sample + visit namespace_project_samples_url(@namespace, @project2) - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 220, - locale: @user.locale)) + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end click_button I18n.t(:'projects.samples.index.select_all_button') within 'tfoot' do - sample_counts = all('strong') - total_samples = sample_counts[0].text.to_i - selected_samples = sample_counts[1].text.to_i - assert selected_samples <= total_samples + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '21' end + ### VERIFY END end test 'empty state of transfer sample project selection' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # check samples - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + # select samples + click_button I18n.t(:'projects.samples.index.select_all_button') # launch dialog click_link I18n.t('projects.samples.index.transfer_button') within('#dialog') do # fill destination input find('input#select2-input').fill_in with: 'invalid project name or puid' - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.transfers.dialog.empty_state') - ### verify end ### + ### VERIFY END ### end end test 'can search the list of samples by name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # partial name search - filter_text = @sample1.name[-3..-1] + filter_text = @sample1.name[-3..] assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) @@ -590,34 +617,34 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary.one', count: 1, locale: @user.locale)) assert_selector '#samples-table table tbody tr', count: 1 assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'limit persists through filter and sort actions' do # tests limit change and that it persists through other actions (filter) - ### setup start ### + ### SETUP START ### sample3 = samples(:sample3) visit namespace_project_samples_url(@namespace, @project2) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 20, count: 20, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### within('div#limit-component') do # set table limit to 10 find('button').click @@ -644,18 +671,15 @@ class SamplesTest < ApplicationSystemTestCase # verify limit is still 10 assert_selector 'div#limit-component button div span', text: '10' - ### actions and verify end ### + ### actions and VERIFY END ### end test 'can sort samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### - assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, - locale: @user.locale)) - ### setup end ### - - ### action and verify start ### + ### ACTION and VERIFY START ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -684,19 +708,19 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### action and verify end ### + ### ACTION and VERIFY END ### end test 'sort samples attachments_updated_at_nulls_last' do # attachments_updated_at_nulls_last sorts null data together - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### action and verify start ### + ### action and VERIFY START ### within('tbody tr:first-child th') do assert_text @sample1.puid end @@ -725,16 +749,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'tr:last-child th', text: @sample1.puid assert_selector 'tr:last-child td:nth-child(2)', text: @sample1.name end - ### action and verify end ### + ### action and VERIFY END ### end test 'sort persists through limit and filter' do - # tests that sort persists through other actions (filter) - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -754,105 +777,107 @@ class SamplesTest < ApplicationSystemTestCase # verify sort is still applied assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' - ### actions and verify end ### + ### actions and VERIFY END ### end test 'filter by name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # only sample1 exists within table assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'filter by puid' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample2.puid find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # only sample2 exists within table assert_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'filter highlighting for sample name' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: 'sample' find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### - # verify table only contains sample1 + ### VERIFY START ### + # verify table still contains all samples assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: 'Sample', count: 3 + ### VERIFY END ### end test 'filter highlighting for sample puid' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 3, count: 3, locale: @user.locale)) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.puid find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # verify table only contains sample1 assert_text strip_tags(I18n.t(:'viral.pagy.limit_component.summary', from: 1, to: 1, count: 1, locale: @user.locale)) # checks highlighting assert_selector 'mark', text: @sample1.puid + ### VERIFY END ### end test 'filter persists through sort and limit actions' do - # tests that filter persists through other actions (sort) - ### setup start ### + ### SETUP START ### + filter_text = @sample1.name visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### ACTIONS and VERIFY START ### # apply filter - fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: @sample1.name + fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) assert_selector "tr[id='#{@sample1.id}']" @@ -870,7 +895,7 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal @sample1.name, input['value'] + assert_equal filter_text, input['value'] end # set limit @@ -886,24 +911,24 @@ class SamplesTest < ApplicationSystemTestCase # verify filter text is still in filter input assert_selector %(input.t-search-component) do |input| - assert_equal @sample1.name, input['value'] + assert_equal filter_text, input['value'] end - ### verify end ### + ### VERIFY END ### end test 'filter persists through page refresh' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) filter_text = @sample1.name - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply filter fill_in placeholder: I18n.t(:'projects.samples.index.search.placeholder'), with: filter_text find('input.t-search-component').native.send_keys(:return) - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" @@ -918,15 +943,15 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" - ### verify end ### + ### VERIFY END ### end test 'sort persists through page refresh' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # apply sort click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_up' @@ -935,22 +960,21 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('samples.table_component.name') assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### actions end ### - - ### verify start ### + ### ACTIONS END ### + ### VERIFY START ### # refresh visit namespace_project_samples_url(@namespace, @project) # verify sort is still enabled assert_selector 'table thead th:nth-child(2) svg.icon-arrow_down' - # verify table ordering is still in changed/sorted state + # verify table ordering is still in sorted state assert_selector '#samples-table table tbody th:first-child', text: @sample30.puid - ### verify end ### + ### VERIFY END ### end test 'should import metadata via csv' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -972,17 +996,19 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + # start import click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### + # success msg assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -993,7 +1019,7 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # sample 1 and 2 have no value current for metadatafield 1 and 2 + # sample 1 and 2 metadata is updated within("tr[id='#{@sample1.id}']") do assert_selector 'td:nth-child(6)', text: '10' assert_selector 'td:nth-child(7)', text: '20' @@ -1005,11 +1031,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '35' end end - ### verify end ### + ### VERIFY END ### end test 'should import metadata via xls' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1030,17 +1056,18 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + # start import click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xls') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1066,11 +1093,11 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### verify end ### + ### VERIFY END ### end test 'should import metadata via xlsx' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1091,17 +1118,17 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/valid.xlsx') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1127,51 +1154,54 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(9)', text: 'Another Test' end end - ### verify end ### + ### VERIFY END ### end test 'should not import metadata via invalid file type' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/invalid.txt') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do + # error msg assert_text I18n.t('services.samples.metadata.import_file.invalid_file_extension') end - ### verify end ### + ### VERIFY END ### end test 'should import metadata with ignore empty values' do - ### setup start ### + # enabled ignore empty values will leave sample metadata values unchanged + ### SETUP START ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import + # value for metadatafield1, which is blank on the csv to import and will be left unchanged after import assert_selector 'td:nth-child(6)', text: 'value1' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option + # enable ignore empty values find('input#file_import_ignore_empty_values').click click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1180,30 +1210,32 @@ class SamplesTest < ApplicationSystemTestCase # unchanged value assert_selector 'td:nth-child(6)', text: 'value1' end - ### verify end ### + ### VERIFY END ### end test 'should import metadata without ignore empty values' do - ### setup start ### + # disabled ignore empty values will delete any metadata values that are empty on the import + ### SETUP START ### visit namespace_project_samples_url(@subgroup12a, @project29) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click within("tr[id='#{@sample32.id}']") do - # value for metadatafield1, which is blank on the csv to import + # value for metadatafield1, which is blank on the csv to import and will be deleted by the import assert_selector 'td:nth-child(6)', text: 'value1' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_empty_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option + # leave ignore empty values disabled assert_not find('input#file_import_ignore_empty_values').checked? click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('shared.samples.metadata.file_imports.success.description') click_on I18n.t('shared.samples.metadata.file_imports.success.ok_button') end @@ -1211,70 +1243,71 @@ class SamplesTest < ApplicationSystemTestCase # value is deleted for metadatafield1 assert_selector 'td:nth-child(6)', text: '' end + ### VERIFY END ### end test 'should not import metadata with duplicate header errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/duplicate_headers.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.duplicate_column_names') - ### verify end ### + ### VERIFY END ### end end test 'should not import metadata with missing metadata row errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_rows.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_row') - ### verify end ### + ### VERIFY END ### end end test 'should not import metadata with missing metadata column errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/missing_metadata_columns.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # error msg assert_text I18n.t('services.samples.metadata.import_file.missing_metadata_column') - ### verify end ### + ### VERIFY END ### end end test 'should partially import metadata with missing sample errors' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click @@ -1292,17 +1325,18 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(7)', text: '' end end - ### setup end ### + ### SETUP END ### - ### actions start ### - click_link I18n.t('projects.samples.index.import_metadata_button'), match: :first + ### ACTIONS START ### + click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/mixed_project_samples.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### + # sample 3 does not exist in current project assert_text I18n.t('services.samples.metadata.import_file.sample_not_found_within_project', sample_puid: 'Project 2 Sample 3') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1321,33 +1355,33 @@ class SamplesTest < ApplicationSystemTestCase assert_selector 'td:nth-child(8)', text: '30' end end - ### verify end ### + ### VERIFY END ### end test 'should not import metadata with analysis values' do - ### setup start ### + ### SETUP START ### subgroup12aa = groups(:subgroup_twelve_a_a) project31 = projects(:project31) sample34 = samples(:sample34) visit namespace_project_samples_url(subgroup12aa, project31) # toggle metadata on for samples table find('label', text: I18n.t(:'projects.samples.shared.metadata_toggle.label')).click - # metadata not overwriting analysis values will still be added + # metadata that does not overwriting analysis values will still be added assert_selector '#samples-table table thead tr th', count: 8 within('#samples-table table thead') do assert_no_text 'METADATAFIELD3' end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_link I18n.t('projects.samples.index.import_metadata_button') within('#dialog') do attach_file 'file_import[file]', Rails.root.join('test/fixtures/files/metadata/contains_analysis_values.csv') find('#file_import_sample_id_column', wait: 1).find(:xpath, 'option[2]').select_option click_on I18n.t('shared.samples.metadata.file_imports.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('services.samples.metadata.import_file.sample_metadata_fields_not_updated', sample_name: sample34.name, metadata_fields: 'metadatafield1') click_on I18n.t('shared.samples.metadata.file_imports.errors.ok_button') @@ -1358,27 +1392,86 @@ class SamplesTest < ApplicationSystemTestCase within('thead') do assert_text 'METADATAFIELD3' end - # new metadata values for sample 1 and 2 + # new metadata value within("tr[id='#{sample34.id}']") do assert_selector 'td:nth-child(8)', text: '20' end - ### verify end ### + ### VERIFY END ### + end + end + + test 'clone dialog sample listing' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end end + ### VERIFY END ### + end + + test 'singular clone dialog description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.clones.dialog.description.singular') + end + ### VERIFY END ### + end + + test 'plural clone dialog description' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.clone_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t( + 'projects.samples.clones.dialog.description.plural' + ).gsub! 'COUNT_PLACEHOLDER', '2' + end + ### VERIFY END ### end test 'should clone samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project2) - # samples 1 and 2 do not exist in project2 + # verify samples 1 and 2 do not exist in project2 within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name end visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### # select samples 1 and 2 for cloning within '#samples-table table tbody' do find("input#sample_#{@sample1.id}").click @@ -1386,23 +1479,13 @@ class SamplesTest < ApplicationSystemTestCase end click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do - # plural dialog description since > 1 sample selected - assert_text I18n.t( - 'projects.samples.clones.dialog.description.plural' - ).gsub! 'COUNT_PLACEHOLDER', '2' - within('#list_selections') do - assert_text @sample1.puid - assert_text @sample1.name - assert_text @sample2.puid - assert_text @sample2.name - end find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.clones.create.success') # samples still exist within samples table of originating project @@ -1417,81 +1500,60 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### verify end ### - end - - test 'singular clone dialog description' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within '#samples-table table tbody' do - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.clone_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.clones.dialog.description.singular') - end - ### verify end ### + ### VERIFY END ### end test 'should not clone samples with session storage cleared' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + # clear localstorage Capybara.execute_script 'sessionStorage.clear()' click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### - assert_no_selector "turbo-frame[id='list_selections']" + ### VERIFY START ### + # sample listing should not be in error dialog + assert_no_selector '#list_selections' + # error msg assert_text I18n.t('projects.samples.clones.create.no_samples_cloned_error') assert_text I18n.t('services.samples.clone.empty_sample_ids') - ### verify end ### + ### VERIFY END ### end end test 'should not clone some samples' do namespace = groups(:subgroup1) project25 = projects(:project25) - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(namespace, project25) - # samples 1 and 2 do not exist in project25 samples table + # sample30's name already exists in project25 samples table, samples1 and 2 do not within('#samples-table table tbody') do assert_no_text @sample1.name assert_no_text @sample2.name + assert_text @sample30.name end visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # check all samples. sample30 will error due to name collision in project25 - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').click find("button[data-viral--select2-primary-param='#{project25.full_path}']").click click_on I18n.t('projects.samples.clones.dialog.submit_button') - end - ### actions end ### - ### verify start ### - within %(turbo-frame[id="samples_dialog"]) do + ### ACTIONS END ### + + ### VERIFY START ### # errors that a sample with the same name as sample30 already exists in project25 assert_text I18n.t('projects.samples.clones.create.error') assert_text I18n.t('services.samples.clone.sample_exists', sample_puid: @sample30.puid, @@ -1505,47 +1567,100 @@ class SamplesTest < ApplicationSystemTestCase assert_text @sample1.name assert_text @sample2.name end - ### verify end ### + ### VERIFY END ### end test 'empty state of destination project selection for sample cloning' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) - ### setup end ### + ### SETUP END ### - ### actions start #### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START #### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') within('#dialog') do find('input#select2-input').fill_in with: 'invalid project name or puid' - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.clones.dialog.empty_state') - ### verify end ### + ### VERIFY END ### end end test 'no available destination projects to clone samples' do - ### setup start ### + ### SETUP START ### sign_in users(:jean_doe) visit namespace_project_samples_url(namespaces_user_namespaces(:john_doe_namespace), projects(:john_doe_project2)) - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.clone_button') - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within('#dialog') do assert "input[placeholder='#{I18n.t('projects.samples.clones.dialog.no_available_projects')}']" end - ### verify end ### + ### VERIFY END ### + end + + test 'updating sample selection during sample cloning' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project2) + # verify no samples currently selected in destination project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 20" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + # select 1 sample to clone + within '#samples-table table tbody' do + all('input[type="checkbox"]')[0].click + end + + # verify 1 sample selected in originating project + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '1' + end + + # clone sample + click_link I18n.t('projects.samples.index.clone_button') + within('#dialog') do + fill_in placeholder: I18n.t('projects.samples.clones.dialog.select_project'), with: @project2.full_path + find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click + click_on I18n.t('projects.samples.clones.dialog.submit_button') + end + ### ACTIONS END ### + + ### VERIFY START ### + # verify no samples selected anymore + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 3" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + + # verify destination project still has no selected samples and one additional sample + Project.reset_counters(@project2.id, :samples_count) + visit namespace_project_samples_url(@namespace, @project2) + + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '0' + end + + click_button I18n.t(:'projects.samples.index.select_all_button') + + within 'tfoot' do + assert_text "#{I18n.t('samples.table_component.counts.samples')}: 21" + assert_selector 'strong[data-selection-target="selected"]', text: '21' + end + ### VERIFY END end test 'selecting / deselecting all samples' do @@ -1705,18 +1820,66 @@ class SamplesTest < ApplicationSystemTestCase text: I18n.t('projects.samples.index.create_export_button.label') end + test 'singular description within delete samples dialog' do + ### SETUP START ### + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + within('tbody tr:first-child') do + # select sample1 + all('input[type="checkbox"]')[0].click + end + click_link I18n.t('projects.samples.index.delete_samples_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', + sample_name: @sample1.name) + end + ### VERIFY END ### + end + + test 'plural description within delete samples dialog' do + ### SETUP START ### + samples = @project.samples.pluck(:puid, :name) + visit namespace_project_samples_url(@namespace, @project) + ### SETUP END ### + + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') + click_link I18n.t('projects.samples.index.delete_samples_button') + ### ACTIONS END ### + + ### VERIFY START ### + within('#dialog') do + assert_text I18n.t( + 'projects.samples.deletions.new_multiple_deletions_dialog.description.plural' + ).gsub! 'COUNT_PLACEHOLDER', '3' + + within('#list_selections') do + samples.each do |sample| + assert_text sample[0] + assert_text sample[1] + end + end + end + ### VERIFY END ### + end + test 'delete multiple samples' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') click_link I18n.t('projects.samples.index.delete_samples_button') within('#dialog') do assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.title') @@ -1732,9 +1895,9 @@ class SamplesTest < ApplicationSystemTestCase click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### # flash msg assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') @@ -1745,41 +1908,17 @@ class SamplesTest < ApplicationSystemTestCase end end - test 'singular description within delete samples dialog' do - ### setup start ### - visit namespace_project_samples_url(@namespace, @project) - ### setup end ### - - ### actions start ### - within('tbody tr:first-child') do - # select sample1 - all('input[type="checkbox"]')[0].click - end - click_link I18n.t('projects.samples.index.delete_samples_button') - ### actions end ### - - ### verify start ### - within('#dialog') do - assert_text I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.description.singular', - sample_name: @sample1.name) - end - ### verify end ### - end - test 'delete single sample with remove link while all samples selected followed by multiple deletion' do # tests that localstorage does not contain a selected sample after it's destroyed - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" - ### setup end ### + ### SETUP END ### - ### actions start ### - within '#samples-table table tbody' do - # select all samples - all('input[type=checkbox]').each { |checkbox| checkbox.click unless checkbox.checked? } - end + ### ACTIONS START ### + click_button I18n.t(:'projects.samples.index.select_all_button') # destroy sample1 with remove action link within '#samples-table table tbody tr:first-child' do @@ -1810,29 +1949,29 @@ class SamplesTest < ApplicationSystemTestCase assert_no_text @sample1.name click_on I18n.t('projects.samples.deletions.new_multiple_deletions_dialog.submit_button') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### assert_text I18n.t('projects.samples.deletions.destroy_multiple.success') within 'div[role="alert"]' do assert_text I18n.t('projects.samples.index.no_samples') assert_text I18n.t('projects.samples.index.no_associated_samples') end - ### verify end ### + ### VERIFY END ### end test 'filtering samples by list of sample puids' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions and verify start ### + ### actions and VERIFY START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1860,20 +1999,20 @@ class SamplesTest < ApplicationSystemTestCase assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### actions and verify end ### + ### actions and VERIFY END ### end test 'filtering samples by list of sample names' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1881,9 +2020,9 @@ class SamplesTest < ApplicationSystemTestCase fill_in I18n.t(:'components.list_filter.description'), with: "#{@sample1.name}, #{@sample2.name}" click_button I18n.t(:'components.list_filter.apply') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within '#samples-table table tbody' do assert_selector 'tr', count: 2 assert_selector "tr[id='#{@sample1.id}']" @@ -1891,20 +2030,20 @@ class SamplesTest < ApplicationSystemTestCase # sample30 filtered out assert_no_selector "tr[id='#{@sample30.id}']" end - ### verify end ### + ### VERIFY END ### end test 'can filter by large list of sample names or ids' do - ### setup start ### + ### SETUP START ### visit namespace_project_samples_url(@namespace, @project) within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_selector "tr[id='#{@sample2.id}']" assert_selector "tr[id='#{@sample30.id}']" end - ### setup end ### + ### SETUP END ### - ### actions start ### + ### ACTIONS START ### click_button I18n.t(:'components.list_filter.title') within '#list-filter-dialog' do |dialog| assert_selector 'h1', text: I18n.t(:'components.list_filter.title') @@ -1913,15 +2052,15 @@ class SamplesTest < ApplicationSystemTestCase dialog.scroll_to(dialog.find('button', text: I18n.t(:'components.list_filter.apply')), align: :bottom) click_button I18n.t(:'components.list_filter.apply') end - ### actions end ### + ### ACTIONS END ### - ### verify start ### + ### VERIFY START ### within '#samples-table table tbody' do assert_selector "tr[id='#{@sample1.id}']" assert_no_selector "tr[id='#{@sample2.id}']" assert_no_selector "tr[id='#{@sample30.id}']" end - ### verify end ### + ### VERIFY END ### end def long_filter_text From 00a72f2a14c70cea8d5a7c8c1cf215af6f7f598f Mon Sep 17 00:00:00 2001 From: Chris Huynh Date: Fri, 13 Dec 2024 14:08:22 -0600 Subject: [PATCH 09/24] fix tests, try to reduce flakiness --- .../viral/select2_option_component.rb | 1 + test/system/projects/samples_test.rb | 70 ++++++------------- 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/app/components/viral/select2_option_component.rb b/app/components/viral/select2_option_component.rb index 89971b6ad2..4b19e03b11 100644 --- a/app/components/viral/select2_option_component.rb +++ b/app/components/viral/select2_option_component.rb @@ -7,6 +7,7 @@ class Select2OptionComponent < Viral::Component