diff --git a/app/views/admin/products_v3/_variant_row.html.haml b/app/views/admin/products_v3/_variant_row.html.haml index 534c39b8e3..7bc193f1e4 100644 --- a/app/views/admin/products_v3/_variant_row.html.haml +++ b/app/views/admin/products_v3/_variant_row.html.haml @@ -79,6 +79,7 @@ options: variant.tax_category_id ? [[variant.tax_category.name, variant.tax_category_id]] : [], selected_option: variant.tax_category_id, aria_label: t('.tax_category_field_name'), + include_blank: t('.none_tax_category'), remote_url: admin_products_search_tax_categories_url, placeholder_value: t('.search_for_tax_categories'))) = error_message_on variant, :tax_category diff --git a/spec/support/tom_select_helper.rb b/spec/support/tom_select_helper.rb index 34a0179d98..957f65f7f2 100644 --- a/spec/support/tom_select_helper.rb +++ b/spec/support/tom_select_helper.rb @@ -19,12 +19,25 @@ module TomSelectHelper tomselect_wrapper.find(:css, '.ts-dropdown div.create').click end + # Searches for and selects an option in a TomSelect dropdown with search functionality. + # @param value [String] The text to search for and select from the dropdown + # @param options [Hash] Configuration options + # @option options [String] :from The name/id of the select field + # @option options [Boolean] :remote_search If true, waits for search loading after interactions + # + # @example + # tomselect_search_and_select("Apple", from: "fruit_selector") + # tomselect_search_and_select("California", from: "state", remote_search: true) def tomselect_search_and_select(value, options) tomselect_wrapper = page.find_field(options[:from]).sibling(".ts-wrapper") tomselect_wrapper.find(".ts-control").click + expect_tomselect_loading_completion(tomselect_wrapper, options) + # Use send_keys as setting the value directly doesn't trigger the search tomselect_wrapper.find(".ts-dropdown input.dropdown-input").send_keys(value) - tomselect_wrapper.find(".ts-dropdown .ts-dropdown-content .option.active", text: value).click + expect_tomselect_loading_completion(tomselect_wrapper, options) + + tomselect_wrapper.find(".ts-dropdown .ts-dropdown-content .option", text: value).click end def tomselect_select(value, options) @@ -64,4 +77,52 @@ module TomSelectHelper end end end + + # Validates both available options and selected options in a TomSelect dropdown. + # @param from [String] The name/id of the select field + # @param existing_options [Array] List of options that should be available in the dropdown + # @param selected_options [Array] List of options that should currently be selected + # + # @example + # expect_tomselect_existing_with_selected_options( + # from: "category_selector", + # existing_options: ["Fruit", "Vegetables", "Dairy"], + # selected_options: ["Fruit"] + # ) + def expect_tomselect_existing_with_selected_options(from:, existing_options:, selected_options:) + tomselect_wrapper = page.find_field(from).sibling(".ts-wrapper") + tomselect_control = tomselect_wrapper.find('.ts-control') + + tomselect_control.click # open the dropdown (would work for remote vs non-remote dropdowns) + + # validate existing options are present in the dropdown + within(tomselect_wrapper) do + existing_options.each do |option| + expect(page).to have_css( + ".ts-dropdown .ts-dropdown-content .option", + text: option + ) + end + end + + # validate selected options are selected in the dropdown + within(tomselect_wrapper) do + selected_options.each do |option| + expect(page).to have_css( + "div[data-ts-item]", + text: option + ) + end + end + + # close the dropdown by clicking on the already selected option + tomselect_wrapper.find(".ts-dropdown .ts-dropdown-content .option.active").click + end + + def expect_tomselect_loading_completion(tomselect_wrapper, options) + return unless options[:remote_search] + + expect(tomselect_wrapper).to have_css(".spinner") + expect(tomselect_wrapper).not_to have_css(".spinner") + end end diff --git a/spec/system/admin/products_v3/actions_spec.rb b/spec/system/admin/products_v3/actions_spec.rb index 16650bd588..897775990a 100644 --- a/spec/system/admin/products_v3/actions_spec.rb +++ b/spec/system/admin/products_v3/actions_spec.rb @@ -15,10 +15,6 @@ RSpec.describe 'As an enterprise user, I can perform actions on the products scr login_as user end - let(:producer_search_selector) { 'input[placeholder="Select producer"]' } - let(:categories_search_selector) { 'input[placeholder="Select category"]' } - let(:tax_categories_search_selector) { 'input[placeholder="Search for tax categories"]' } - describe "column selector" do let!(:product) { create(:simple_product) } @@ -102,54 +98,7 @@ RSpec.describe 'As an enterprise user, I can perform actions on the products scr } let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } - context "when they are under 11" do - before do - create_list(:supplier_enterprise, 9, users: [user]) - create_list(:tax_category, 9) - create_list(:taxon, 2) - - visit admin_products_url - end - - it "should not display search input, change the producers, category and tax category" do - producer_to_select = random_producer(variant_a1) - category_to_select = random_category(variant_a1) - tax_category_to_select = random_tax_category - - within row_containing_name(variant_a1.display_name) do - validate_tomselect_without_search!( - page, "Producer", - producer_search_selector - ) - tomselect_select(producer_to_select, from: "Producer") - end - - within row_containing_name(variant_a1.display_name) do - validate_tomselect_without_search!( - page, "Category", - categories_search_selector - ) - tomselect_select(category_to_select, from: "Category") - - validate_tomselect_without_search!( - page, "Tax Category", - tax_categories_search_selector - ) - tomselect_select(tax_category_to_select, from: "Tax Category") - end - - click_button "Save changes" - - expect(page).to have_content "Changes saved" - - variant_a1.reload - expect(variant_a1.supplier.name).to eq(producer_to_select) - expect(variant_a1.primary_taxon.name).to eq(category_to_select) - expect(variant_a1.tax_category.name).to eq(tax_category_to_select) - end - end - - context "when they are over 11" do + context "when there are products" do before do create_list(:supplier_enterprise, 11, users: [user]) create_list(:tax_category, 11) @@ -167,9 +116,13 @@ RSpec.describe 'As an enterprise user, I can perform actions on the products scr tax_category_to_select = random_tax_category within row_containing_name(variant_a1.display_name) do - tomselect_search_and_select(producer_to_select, from: "Producer") - tomselect_search_and_select(category_to_select, from: "Category") - tomselect_search_and_select(tax_category_to_select, from: "Tax Category") + tomselect_search_and_select(producer_to_select, from: "Producer", remote_search: true) + tomselect_search_and_select(category_to_select, from: "Category", remote_search: true) + tomselect_search_and_select( + tax_category_to_select, + from: "Tax Category", + remote_search: true + ) end click_button "Save changes" diff --git a/spec/system/admin/products_v3/create_spec.rb b/spec/system/admin/products_v3/create_spec.rb index 965d9f9e99..04f90abcaf 100644 --- a/spec/system/admin/products_v3/create_spec.rb +++ b/spec/system/admin/products_v3/create_spec.rb @@ -86,14 +86,14 @@ RSpec.describe 'As an enterprise user, I can manage my products' do find('button[aria-label="On Hand"]').click find('input[id$="_price"]').fill_in with: "11.1" - select supplier.name, from: 'Producer' - select taxon.name, from: 'Category' - if stock == "on_hand" find('input[id$="_on_hand_desired"]').fill_in with: "66" elsif stock == "on_demand" find('input[id$="_on_demand_desired"]').check end + + tomselect_select supplier.name, from: 'Producer' + tomselect_select taxon.name, from: 'Category' end expect(page).to have_content "1 product modified." diff --git a/spec/system/admin/products_v3/index_spec.rb b/spec/system/admin/products_v3/index_spec.rb index d943e5a1d3..d53a391e0c 100644 --- a/spec/system/admin/products_v3/index_spec.rb +++ b/spec/system/admin/products_v3/index_spec.rb @@ -106,13 +106,19 @@ RSpec.describe 'As an enterprise user, I can browse my products' do visit spree.admin_products_path within row_containing_name "Variant1" do - expect(page).to have_select "Producer", with_options: ["Producer A", "Producer B"], - selected: "Producer A" + expect_tomselect_existing_with_selected_options( + from: 'Producer', + existing_options: ["Producer A", "Producer B"], + selected_options: ["Producer A"] + ) end within row_containing_name "Variant2a" do - expect(page).to have_select "Producer", with_options: ["Producer A", "Producer B"], - selected: "Producer B" + expect_tomselect_existing_with_selected_options( + from: 'Producer', + existing_options: ["Producer A", "Producer B"], + selected_options: ["Producer B"] + ) end end end @@ -543,24 +549,21 @@ RSpec.describe 'As an enterprise user, I can browse my products' do it "shows only suppliers that I manage or have permission to" do visit spree.admin_products_path + existing_options = [supplier_managed1.name, supplier_managed2.name, supplier_permitted.name] within row_containing_placeholder(product_supplied.name) do - expect(page).to have_select( - '_products_0_variants_attributes_0_supplier_id', - options: [ - 'Select producer', - supplier_managed1.name, supplier_managed2.name, supplier_permitted.name - ], selected: supplier_managed1.name + expect_tomselect_existing_with_selected_options( + existing_options:, + from: '_products_0_variants_attributes_0_supplier_id', + selected_options: [supplier_managed1.name] ) end within row_containing_placeholder(product_supplied_permitted.name) do - expect(page).to have_select( - '_products_1_variants_attributes_0_supplier_id', - options: [ - 'Select producer', - supplier_managed1.name, supplier_managed2.name, supplier_permitted.name - ], selected: supplier_permitted.name + expect_tomselect_existing_with_selected_options( + existing_options:, + from: '_products_1_variants_attributes_0_supplier_id', + selected_options: [supplier_permitted.name] ) end end diff --git a/spec/system/admin/products_v3/update_spec.rb b/spec/system/admin/products_v3/update_spec.rb index 0da94594f6..4ddeff1578 100644 --- a/spec/system/admin/products_v3/update_spec.rb +++ b/spec/system/admin/products_v3/update_spec.rb @@ -350,8 +350,8 @@ RSpec.describe 'As an enterprise user, I can update my products' do click_on "On Hand" # activate popout fill_in "On Hand", with: "3" - select producer.name, from: 'Producer' - select taxon.name, from: 'Category' + tomselect_select producer.name, from: 'Producer' + tomselect_select taxon.name, from: 'Category' end expect { @@ -586,8 +586,8 @@ RSpec.describe 'As an enterprise user, I can update my products' do fill_in "Name", with: "Nice box" fill_in "SKU", with: "APL-02" - select producer.name, from: 'Producer' - select taxon.name, from: 'Category' + tomselect_select producer.name, from: 'Producer' + tomselect_select taxon.name, from: 'Category' end expect { diff --git a/spec/views/admin/products_v3/_filters.html.haml_spec.rb b/spec/views/admin/products_v3/_filters.html.haml_spec.rb index a6bcbfbca3..1b2ed5b697 100644 --- a/spec/views/admin/products_v3/_filters.html.haml_spec.rb +++ b/spec/views/admin/products_v3/_filters.html.haml_spec.rb @@ -17,7 +17,7 @@ RSpec.describe "admin/products_v3/_filters.html.haml" do end let(:spree_current_user) { build(:enterprise_user) } - it "shows the producer filter when there are options" do + it "shows the producer filter with the default option initially" do allow(view).to receive_messages locals.merge( producer_options: [ ["Ada's Apples", 1], @@ -27,9 +27,7 @@ RSpec.describe "admin/products_v3/_filters.html.haml" do is_expected.to have_content "Producers" is_expected.to have_select "producer_id", options: [ - "All producers", - "Ada's Apples", - "Ben's Bananas", + "All producers" ], selected: nil end