diff --git a/Gemfile b/Gemfile index 12dd15b556..3f59333669 100644 --- a/Gemfile +++ b/Gemfile @@ -117,7 +117,8 @@ group :test, :development do gem 'awesome_print' gem 'letter_opener', '>= 1.4.1' gem 'timecop' - gem 'poltergeist', '>= 1.16.0' + gem 'selenium-webdriver' + gem 'chromedriver-helper' gem 'rspec-retry' gem 'json_spec', '~> 1.1.4' gem 'unicorn-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 4bcd2be6a2..f6f333df16 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,6 +188,8 @@ GEM tilt angularjs-file-upload-rails (2.4.1) angularjs-rails (1.5.5) + archive-zip (0.7.0) + io-like (~> 0.3.0) arel (3.0.3) ast (2.4.0) atomic (1.1.101) @@ -213,10 +215,14 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (>= 2.0, < 4.0) + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) + chromedriver-helper (1.1.0) + archive-zip (~> 0.7.0) + nokogiri (~> 1.6) chronic (0.10.2) chunky_png (1.3.10) climate_control (0.2.0) - cliver (0.3.2) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.1.2) @@ -488,6 +494,7 @@ GEM i18n (>= 0.6.6, < 2) immigrant (0.3.6) activerecord (>= 3.0) + io-like (0.3.0) ipaddress (0.8.3) jaro_winkler (1.5.1) journey (1.0.4) @@ -561,10 +568,6 @@ GEM paypal-sdk-merchant (1.106.1) paypal-sdk-core (~> 0.2.3) pg (0.21.0) - poltergeist (1.18.1) - capybara (>= 2.1, < 4) - cliver (~> 0.3.1) - websocket-driver (>= 0.2.0) polyamorous (0.5.0) activerecord (~> 3.0) polyglot (0.3.5) @@ -681,6 +684,9 @@ GEM tilt (~> 1.3) select2-rails (3.5.10) thor (~> 0.14) + selenium-webdriver (3.12.0) + childprocess (~> 0.5) + rubyzip (~> 1.2) shellany (0.0.1) shoulda-matchers (2.8.0) activesupport (>= 3.0.0) @@ -771,6 +777,7 @@ DEPENDENCIES bugsnag byebug (~> 9.0.0) capybara (>= 2.15.4) + chromedriver-helper coffee-rails (~> 3.2.1) compass-rails custom_error_message! @@ -815,7 +822,6 @@ DEPENDENCIES paper_trail (~> 3.0.8) paperclip pg - poltergeist (>= 1.16.0) pry-byebug (>= 3.4.3) rabl rack-mini-profiler (< 1.0.0) @@ -832,6 +838,7 @@ DEPENDENCIES rubocop (>= 0.49.1) sass (~> 3.3) sass-rails (~> 3.2.3) + selenium-webdriver shoulda-matchers simple_form! simplecov diff --git a/app/views/admin/enterprises/form/_primary_details.html.haml b/app/views/admin/enterprises/form/_primary_details.html.haml index aad869288e..dd83c4d2c2 100644 --- a/app/views/admin/enterprises/form/_primary_details.html.haml +++ b/app/views/admin/enterprises/form/_primary_details.html.haml @@ -59,7 +59,7 @@ .six.columns = f.text_field :permalink, { 'ng-model' => "Enterprise.permalink", placeholder: "eg. your-shop-name", 'ng-model-options' => "{ updateOn: 'default blur', debounce: {'default': 300, 'blur': 0} }" } .two.columns.omega - %img.spinner{ src: "/assets/loading.gif", width: "30px", ng: { show: "checking" } } + %img.spinner{ src: "/assets/spinning-circles.svg", width: "30px", ng: { show: "checking" } } %span{ ng: { class: 'availability.toLowerCase()', hide: "checking" } } {{ availability }} %i{ ng: { class: "{'icon-ok-sign': availability == 'Available', 'icon-remove-sign': availability == 'Unavailable'}" } } diff --git a/config/ng-test.conf.js b/config/ng-test.conf.js index 20ec36622c..13dc997ebd 100644 --- a/config/ng-test.conf.js +++ b/config/ng-test.conf.js @@ -43,7 +43,7 @@ module.exports = function(config) { autoWatch: true, - browsers: ['PhantomJS'], + browsers: ['ChromeHeadless'], junitReporter: { outputFile: 'log/testacular-unit.xml', diff --git a/package.json b/package.json index bb174e883d..53c751067d 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,10 @@ "url": "https://github.com/openfoodfoundation/openfoodnetwork" }, "devDependencies": { - "phantomjs-prebuilt": "~2.1.7", "karma": "~0.13.22", + "karma-chrome-launcher": "~2.2.0", "karma-jasmine": "~0.3.8", "jasmine-core": "~2.4.1", - "karma-phantomjs-launcher": "~1.0.0", "karma-coffee-preprocessor": "~0.3.0" }, "license": "AGPL-1.0" diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index d6410daef7..d261405a4d 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -474,13 +474,17 @@ feature %q{ end it "displays only line items whose orders meet the date restriction criteria, when changed" do - fill_in "start_date_filter", :with => (Time.zone.today - 8.days).strftime("%F") + find('#start_date_filter').click + select_date(Time.zone.today - 8.days) + expect(page).to have_selector "tr#li_#{li1.id}" expect(page).to have_selector "tr#li_#{li2.id}" expect(page).to have_selector "tr#li_#{li3.id}" expect(page).to have_no_selector "tr#li_#{li4.id}" - fill_in "end_date_filter", :with => (Time.zone.today + 1.day).strftime("%F") + find('#end_date_filter').click + select_date(Time.zone.today + 1.day) + expect(page).to have_selector "tr#li_#{li1.id}" expect(page).to have_selector "tr#li_#{li2.id}" expect(page).to have_selector "tr#li_#{li3.id}" @@ -629,7 +633,9 @@ feature %q{ it "removes a line item when the relevant delete button is clicked" do expect(page).to have_selector "a.delete-line-item", :count => 2 - find("tr#li_#{li1.id} a.delete-line-item").click + accept_alert do + find("tr#li_#{li1.id} a.delete-line-item").click + end expect(page).to have_no_selector "a.delete-line-item", :count => 2 expect(page).to have_selector "a.delete-line-item", :count => 1 visit '/admin/orders/bulk_management' @@ -732,4 +738,12 @@ feature %q{ expect(page).to have_no_selector "tr#li_#{line_item_not_distributed.id}", :visible => true end end + + def select_date(date) + current_month = Time.zone.today.strftime("%B") + target_month = date.strftime("%B") + + find('#ui-datepicker-div .ui-datepicker-header .ui-datepicker-prev').click if current_month != target_month + find('#ui-datepicker-div .ui-datepicker-calendar .ui-state-default', text: date.strftime("%e").to_s.strip, exact_text: true).click + end end diff --git a/spec/features/admin/bulk_product_update_spec.rb b/spec/features/admin/bulk_product_update_spec.rb index 96259bfe55..eb2e4434f3 100644 --- a/spec/features/admin/bulk_product_update_spec.rb +++ b/spec/features/admin/bulk_product_update_spec.rb @@ -74,7 +74,7 @@ feature %q{ visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - find("a.view-variants").trigger('click') + find("a.view-variants").click expect(page).to have_no_selector "span[name='on_hand']", text: "On demand", visible: true expect(page).to have_field "variant_on_hand", with: "4" @@ -111,7 +111,7 @@ feature %q{ visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 2 - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_field "product_name", with: v1.product.name expect(page).to have_field "product_name", with: v2.product.name @@ -126,7 +126,7 @@ feature %q{ visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_selector "span[name='on_hand']", text: p1.variants.sum{ |v| v.on_hand }.to_s expect(page).to have_field "variant_on_hand", with: "15" @@ -141,7 +141,7 @@ feature %q{ visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_field "price", with: "2.0", visible: false expect(page).to have_field "variant_price", with: "12.75" @@ -155,7 +155,7 @@ feature %q{ visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_field "variant_unit_value_with_description", with: "1.2 (small bag)" expect(page).to have_field "variant_unit_value_with_description", with: "4.8 (large bag)" @@ -197,18 +197,20 @@ feature %q{ visit spree.admin_products_path # I should see an add variant button - page.find('a.view-variants').trigger('click') + page.find('a.view-variants').click # When I add three variants - page.find('a.add-variant', visible: true).trigger('click') - page.find('a.add-variant', visible: true).trigger('click') + page.find('a.add-variant', visible: true).click + page.find('a.add-variant', visible: true).click # They should be added, and should not see edit buttons for new variants expect(page).to have_selector "tr.variant", count: 3 expect(page).to have_selector "a.edit-variant", count: 1 # When I remove two, they should be removed - page.all('a.delete-variant', visible: true).first.click + accept_alert do + page.all('a.delete-variant', visible: true).first.click + end expect(page).to have_selector "tr.variant", count: 2 page.all('a.delete-variant', visible: true).first.click expect(page).to have_selector "tr.variant", count: 1 @@ -310,7 +312,7 @@ feature %q{ quick_login_as_admin visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - find("a.view-variants").trigger('click') + find("a.view-variants").click toggle_columns "SKU" @@ -346,7 +348,7 @@ feature %q{ quick_login_as_admin visit spree.admin_products_path expect(page).to have_selector "a.view-variants", count: 1 - find("a.view-variants").trigger('click') + find("a.view-variants").click expect(page).to have_field "variant_price", with: "3.0" @@ -458,7 +460,9 @@ feature %q{ expect(page).to have_selector "a.delete-product", :count => 2 within "tr#p_#{p1.id}" do - find("a.delete-product").click + accept_alert do + find("a.delete-product").click + end end expect(page).to have_selector "a.delete-product", :count => 1 @@ -470,19 +474,21 @@ feature %q{ it "shows a delete button for variants, which deletes the appropriate variant when clicked" do expect(page).to have_selector "a.view-variants" - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_selector "a.delete-variant", :count => 3 within "tr#v_#{v3.id}" do - find("a.delete-variant").click + accept_alert do + find("a.delete-variant").click + end end expect(page).to have_selector "a.delete-variant", :count => 2 visit spree.admin_products_path expect(page).to have_selector "a.view-variants" - all("a.view-variants").select { |e| e.visible? }.each { |e| e.trigger('click') } + all("a.view-variants").select { |e| e.visible? }.each { |e| e.click } expect(page).to have_selector "a.delete-variant", :count => 2 end @@ -511,7 +517,7 @@ feature %q{ it "shows an edit button for variants, which takes the user to the standard edit page for that variant" do expect(page).to have_selector "a.view-variants" - all("a.view-variants").each { |e| e.trigger('click') } + all("a.view-variants").each { |e| e.click } expect(page).to have_selector "a.edit-variant", :count => 2 @@ -701,7 +707,7 @@ feature %q{ fill_in "available_on", with: (3.days.ago.beginning_of_day).strftime("%F %T") select "Weight (kg)", from: "variant_unit_with_scale" - find("a.view-variants").trigger('click') + find("a.view-variants").click end within "#v_#{v.id}" do @@ -741,7 +747,7 @@ feature %q{ expect(page).to have_css "img[src='/assets/noimage/mini.png']" # Click image - page.find("a.image-modal").trigger('click') + page.find("a.image-modal").click end # Shows upload modal @@ -766,7 +772,7 @@ feature %q{ @new_thumb_src = page.find("a.image-modal img")['src'] expect(@old_thumb_src) != @new_thumb_src - page.find("a.image-modal").trigger('click') + page.find("a.image-modal").click end expect(page).to have_selector "div.reveal-modal.product-image-upload" diff --git a/spec/features/admin/customers_spec.rb b/spec/features/admin/customers_spec.rb index 65a27d6ef8..7a2650d93f 100644 --- a/spec/features/admin/customers_spec.rb +++ b/spec/features/admin/customers_spec.rb @@ -75,7 +75,9 @@ feature 'Customers' do create(:order, customer: customer1) expect{ within "tr#c_#{customer1.id}" do - find("a.delete-customer").trigger('click') + accept_alert do + find("a.delete-customer").click + end end expect(page).to have_selector "#info-dialog .text", text: I18n.t('admin.customers.destroy.has_associated_orders') click_button "OK" @@ -83,7 +85,9 @@ feature 'Customers' do expect{ within "tr#c_#{customer2.id}" do - find("a.delete-customer").click + accept_alert do + find("a.delete-customer").click + end end expect(page).to have_no_selector "tr#c_#{customer2.id}" }.to change{Customer.count}.by(-1) @@ -125,7 +129,7 @@ feature 'Customers' do fill_in "name", with: "" expect(page).to have_css "input[name=name].update-pending" - find("tags-input li.tag-item a.remove-button").trigger('click') + find("tags-input li.tag-item a.remove-button").click expect(page).to have_css ".tag_watcher.update-pending" end click_button "Save Changes" diff --git a/spec/features/admin/enterprise_fees_spec.rb b/spec/features/admin/enterprise_fees_spec.rb index c3526e1b20..ea23afc938 100644 --- a/spec/features/admin/enterprise_fees_spec.rb +++ b/spec/features/admin/enterprise_fees_spec.rb @@ -97,7 +97,9 @@ feature %q{ visit admin_enterprise_fees_path # And I click delete - find("a.delete-resource").click + accept_alert do + find("a.delete-resource").click + end # Then my enterprise fee should have been deleted visit admin_enterprise_fees_path @@ -116,7 +118,9 @@ feature %q{ visit admin_enterprise_fees_path # And I click delete - find("a.delete-resource").click + accept_alert do + find("a.delete-resource").click + end # Then I should see an error expect(page).to have_content "That enterprise fee cannot be deleted as it is referenced by a product distribution: #{p.id} - #{p.name}." diff --git a/spec/features/admin/enterprise_groups_spec.rb b/spec/features/admin/enterprise_groups_spec.rb index 2a118eb9b5..0d3bb60b61 100644 --- a/spec/features/admin/enterprise_groups_spec.rb +++ b/spec/features/admin/enterprise_groups_spec.rb @@ -97,7 +97,9 @@ feature %q{ eg = create(:enterprise_group, name: 'EGEGEG') click_link 'Groups' - first("a.delete-resource").click + accept_alert do + first("a.delete-resource").click + end page.should have_no_content 'EGEGEG' diff --git a/spec/features/admin/enterprise_relationships_spec.rb b/spec/features/admin/enterprise_relationships_spec.rb index 45d26a9e87..de77f79dd2 100644 --- a/spec/features/admin/enterprise_relationships_spec.rb +++ b/spec/features/admin/enterprise_relationships_spec.rb @@ -48,6 +48,8 @@ feature %q{ select2_select 'Two', from: 'enterprise_relationship_child_id' click_button 'Create' + # Wait for row to appear since have_relationship doesn't wait + page.should have_selector 'tr', count: 2 page.should have_relationship e1, e2, ['to add to order cycle', 'to add products to inventory', 'to edit profile'] er = EnterpriseRelationship.where(parent_id: e1, child_id: e2).first er.should be_present @@ -80,7 +82,9 @@ feature %q{ visit admin_enterprise_relationships_path page.should have_relationship e1, e2, ['to add to order cycle'] - first("a.delete-enterprise-relationship").click + accept_alert do + first("a.delete-enterprise-relationship").click + end page.should_not have_relationship e1, e2 EnterpriseRelationship.where(id: er.id).should be_empty diff --git a/spec/features/admin/enterprise_roles_spec.rb b/spec/features/admin/enterprise_roles_spec.rb index 8d001c52a2..d86a320f75 100644 --- a/spec/features/admin/enterprise_roles_spec.rb +++ b/spec/features/admin/enterprise_roles_spec.rb @@ -43,6 +43,8 @@ feature %q{ select 'One', from: 'enterprise_role_enterprise_id' click_button 'Create' + # Wait for row to appear since have_relationship doesn't wait + page.should have_selector 'tr', count: 3 page.should have_relationship u, e EnterpriseRole.where(user_id: u, enterprise_id: e).should be_present end @@ -73,9 +75,13 @@ feature %q{ page.should have_relationship u, e within("#enterprise_role_#{er.id}") do - find("a.delete-enterprise-role").click + accept_alert do + find("a.delete-enterprise-role").click + end end + # Wait for row to disappear, otherwise have_relationship waits 30 seconds. + page.should_not have_selector "#enterprise_role_#{er.id}" page.should_not have_relationship u, e EnterpriseRole.where(id: er.id).should be_empty end @@ -122,7 +128,7 @@ feature %q{ end it "shows changes to enterprise contact or owner" do - select user2.email, from: 'receives_notifications_dropdown', visible: false + select2_select user2.email, from: 'receives_notifications_dropdown' within('#save-bar') { click_button 'Update' } within('.side_menu') { click_link 'Users' } diff --git a/spec/features/admin/enterprises/images_spec.rb b/spec/features/admin/enterprises/images_spec.rb index 92c4bbafaf..b2f1cb0787 100644 --- a/spec/features/admin/enterprises/images_spec.rb +++ b/spec/features/admin/enterprises/images_spec.rb @@ -54,6 +54,7 @@ feature "Managing enterprise images" do # Removing image within ".page-admin-enterprises-form__logo-field-group" do click_on "Remove Image" + accept_js_alert end expect(page).to have_content("Logo removed successfully") @@ -91,6 +92,7 @@ feature "Managing enterprise images" do # Removing image within ".page-admin-enterprises-form__promo-image-field-group" do click_on "Remove Image" + accept_js_alert end expect(page).to have_content("Promo image removed successfully") diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index f594536127..ffc2d010b6 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -61,9 +61,6 @@ feature %q{ end scenario "editing an existing enterprise", js: true do - # Make the page long enough to avoid the save bar overlaying the form - page.driver.resize(1280, 1000) - @enterprise = create(:enterprise) e2 = create(:enterprise) eg1 = create(:enterprise_group, name: 'eg1') @@ -77,7 +74,7 @@ feature %q{ visit '/admin/enterprises' within "tr.enterprise-#{@enterprise.id}" do - first("a", text: 'Settings').trigger 'click' + first("a", text: 'Settings').click end fill_in 'enterprise_name', :with => 'Eaterprises' @@ -86,30 +83,33 @@ feature %q{ choose 'Own' # Require login to view shopfront or for checkout - within(".side_menu") { click_link "Shop Preferences" } + accept_alert do + within(".side_menu") { click_link "Shop Preferences" } + end expect(page).to have_checked_field "enterprise_require_login_false" expect(page).to have_checked_field "enterprise_allow_guest_orders_true" choose "Visible to registered customers only" expect(page).to have_no_checked_field "enterprise_require_login_false" # expect(page).to have_checked_field "enterprise_enable_subscriptions_false" - within(".side_menu") { click_link "Users" } + accept_alert do + within(".side_menu") { click_link "Users" } + end select2_search user.email, from: 'Owner' expect(page).to have_no_selector '.select2-drop-mask' # Ensure select2 has finished - click_link "About" + accept_alert do + click_link "About" + end fill_in 'enterprise_description', :with => 'Connecting farmers and eaters' - # TODO: Directly altering the text in the contenteditable div like this started breaking with the upgrade - # of Poltergeist from 1.5 to 1.7. Probably requires an upgrade of AngularJS and/or TextAngular - # long_description = find :css, "text-angular#enterprise_long_description div.ta-scroll-window div.ta-bind" - # long_description.set 'This is an interesting long description' - # long_description.native.send_keys(:Enter) # Sets the value - - page.first("input[name='enterprise\[long_description\]']", visible: false).set('This is an interesting long description') + description_input = page.find("text-angular#enterprise_long_description div[id^='taTextElement']") + description_input.native.send_keys('This is an interesting long description') # Check Angularjs switching of sidebar elements - click_link "Primary Details" + accept_alert do + click_link "Primary Details" + end uncheck 'enterprise_is_primary_producer' choose 'None' page.should_not have_selector "#enterprise_fees" @@ -131,40 +131,52 @@ feature %q{ select2_search eg1.name, from: 'Groups' - click_link "Payment Methods" + accept_alert do + click_link "Payment Methods" + end page.should_not have_checked_field "enterprise_payment_method_ids_#{payment_method.id}" check "enterprise_payment_method_ids_#{payment_method.id}" - click_link "Shipping Methods" + accept_alert do + click_link "Shipping Methods" + end page.should_not have_checked_field "enterprise_shipping_method_ids_#{shipping_method.id}" check "enterprise_shipping_method_ids_#{shipping_method.id}" - click_link "Contact" + accept_alert do + click_link "Contact" + end fill_in 'enterprise_contact_name', :with => 'Kirsten or Ren' fill_in 'enterprise_phone', :with => '0413 897 321' fill_in 'enterprise_email_address', :with => 'info@eaterprises.com.au' fill_in 'enterprise_website', :with => 'http://eaterprises.com.au' - click_link "Social" + accept_alert do + click_link "Social" + end fill_in 'enterprise_twitter', :with => '@eaterprises' - click_link "Business Details" + accept_alert do + click_link "Business Details" + end fill_in 'enterprise_abn', :with => '09812309823' fill_in 'enterprise_acn', :with => '' choose 'Yes' # enterprise_charges_sales_tax - click_link "Address" + accept_alert do + click_link "Address" + end fill_in 'enterprise_address_attributes_address1', :with => '35 Ballantyne St' fill_in 'enterprise_address_attributes_city', :with => 'Thornbury' fill_in 'enterprise_address_attributes_zipcode', :with => '3072' select2_search 'Australia', :from => 'Country' select2_search 'Victoria', :from => 'State' - click_link "Shop Preferences" - # TODO: Same as above - # shopfront_message = find :css, "text-angular#enterprise_preferred_shopfront_message div.ta-scroll-window div.ta-bind" - # shopfront_message.set 'This is my shopfront message.' - page.first("input[name='enterprise\[preferred_shopfront_message\]']", visible: false).set('This is my shopfront message.') + accept_alert do + click_link "Shop Preferences" + end + shop_message_input = page.find("text-angular#enterprise_preferred_shopfront_message div[id^='taTextElement']") + shop_message_input.native.send_keys('This is my shopfront message.') page.should have_checked_field "enterprise_preferred_shopfront_order_cycle_order_orders_close_at" choose "enterprise_preferred_shopfront_order_cycle_order_orders_open_at" choose "enterprise_enable_subscriptions_true" @@ -443,7 +455,12 @@ feature %q{ click_link "Properties" end - within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click } + # Bug: https://github.com/openfoodfoundation/openfoodnetwork/issues/2453 + accept_alert do + accept_alert do + within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click } + end + end click_button 'Update' diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index fb1c8731ad..5f9b887b82 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -154,8 +154,6 @@ feature %q{ let(:order_cycle_closing_time) { Time.zone.local(2040, 11, 13, 17, 00, 00).strftime("%F %T %z") } scenario "creating an order cycle", js: true do - page.driver.resize(1280, 2000) - # Given coordinating, supplying and distributing enterprises with some products with variants coordinator = create(:distributor_enterprise, name: 'My coordinator') supplier = create(:supplier_enterprise, name: 'My supplier') @@ -610,7 +608,7 @@ feature %q{ quick_login_as_admin visit edit_admin_order_cycle_path(oc) within("table.exchanges tbody tr.supplier") { page.find('td.products').click } - page.find("#order_cycle_incoming_exchange_0_variants_#{p.master.id}", visible: true).trigger('click') # uncheck + page.find("#order_cycle_incoming_exchange_0_variants_#{p.master.id}").click # uncheck click_button "Update" # Then the master variant should have been removed from all exchanges @@ -708,9 +706,6 @@ feature %q{ scenario "creating a new order cycle" do distributor_managed.update_attribute(:enable_subscriptions, true) - # Make the page long enough to avoid the save bar overlaying the form - page.driver.resize(1280, 2000) - visit admin_order_cycles_path click_link 'New Order Cycle' @@ -997,9 +992,6 @@ feature %q{ end it "creates order cycles", js: true do - # Make the page long enough to avoid the save bar overlaying the form - page.driver.resize(1280, 2000) - # When I go to the new order cycle page visit admin_order_cycles_path click_link 'New Order Cycle' @@ -1150,7 +1142,9 @@ feature %q{ quick_login_as_admin visit admin_order_cycles_path expect(page).to have_selector "tr.order-cycle-#{order_cycle.id}" - first('a.delete-order-cycle').click + accept_alert do + first('a.delete-order-cycle').click + end expect(page).to_not have_selector "tr.order-cycle-#{order_cycle.id}" end diff --git a/spec/features/admin/orders_spec.rb b/spec/features/admin/orders_spec.rb index 032ed3443a..797b945925 100644 --- a/spec/features/admin/orders_spec.rb +++ b/spec/features/admin/orders_spec.rb @@ -287,32 +287,34 @@ feature %q{ end within_window ticket_window do - print_data = page.evaluate_script('printData'); - elements_in_print_data = - [ - @order.distributor.name, - @order.distributor.address.address_part1, - @order.distributor.address.address_part2, - @order.distributor.contact.email, - @order.number, - @order.line_items.map { |line_item| - [line_item.quantity.to_s, - line_item.product.name, - line_item.single_display_amount_with_adjustments.format(symbol: false, with_currency: false), - line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)] - }, - checkout_adjustments_for(@order, exclude: [:line_item]).reject { |a| a.amount == 0 }.map { |adjustment| - [raw(adjustment.label), - display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)] - }, - @order.display_total.format(with_currency: false), - display_checkout_taxes_hash(@order).map { |tax_rate, tax_value| - [tax_rate, - tax_value.format(with_currency: false)] - }, - display_checkout_total_less_tax(@order).format(with_currency: false) - ] - expect(print_data.join).to include(*elements_in_print_data.flatten) + accept_alert do + print_data = page.evaluate_script('printData'); + elements_in_print_data = + [ + @order.distributor.name, + @order.distributor.address.address_part1, + @order.distributor.address.address_part2, + @order.distributor.contact.email, + @order.number, + @order.line_items.map { |line_item| + [line_item.quantity.to_s, + line_item.product.name, + line_item.single_display_amount_with_adjustments.format(symbol: false, with_currency: false), + line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)] + }, + checkout_adjustments_for(@order, exclude: [:line_item]).reject { |a| a.amount == 0 }.map { |adjustment| + [raw(adjustment.label), + display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)] + }, + @order.display_total.format(with_currency: false), + display_checkout_taxes_hash(@order).map { |tax_rate, tax_value| + [tax_rate, + tax_value.format(with_currency: false)] + }, + display_checkout_total_less_tax(@order).format(with_currency: false) + ] + expect(print_data.join).to include(*elements_in_print_data.flatten) + end end end end diff --git a/spec/features/admin/product_import_spec.rb b/spec/features/admin/product_import_spec.rb index c1b87b1f33..d196a686e0 100644 --- a/spec/features/admin/product_import_spec.rb +++ b/spec/features/admin/product_import_spec.rb @@ -165,7 +165,7 @@ feature "Product Import", js: true do expect(page).to have_selector 'div#s2id_import_date_filter' import_time = carrots.import_date.to_date.to_formatted_s(:long).gsub(' ', ' ') - select import_time, from: "import_date_filter", visible: false + select2_select import_time, from: "import_date_filter" expect(page).to have_field "product_name", with: carrots.name expect(page).to have_field "product_name", with: potatoes.name diff --git a/spec/features/admin/products_spec.rb b/spec/features/admin/products_spec.rb index 3894e46e93..1e3f9a8f15 100644 --- a/spec/features/admin/products_spec.rb +++ b/spec/features/admin/products_spec.rb @@ -35,7 +35,7 @@ feature %q{ fill_in 'product_on_hand', with: 5 select 'Test Tax Category', from: 'product_tax_category_id' select 'Test Shipping Category', from: 'product_shipping_category_id' - page.find("input[name='product\[description\]']", visible: false).set('A description...') + page.find("div[id^='taTextElement']").native.send_keys('A description...') click_button 'Create' @@ -53,7 +53,7 @@ feature %q{ product.on_hand.should == 5 product.tax_category_id.should == tax_category.id product.shipping_category.should == shipping_category - product.description.should == "A description..." + product.description.should == "
A description...
" product.group_buy.should be_falsey product.master.option_values.map(&:name).should == ['5kg'] product.master.options_text.should == "5kg" @@ -75,8 +75,7 @@ feature %q{ check 'product_on_demand' select 'Test Tax Category', from: 'product_tax_category_id' select 'Test Shipping Category', from: 'product_shipping_category_id' - #fill_in 'product_description', with: "In demand, and on_demand! The hottest cakes in town." - page.first("input[name='product\[description\]']", visible: false).set('In demand, and on_demand! The hottest cakes in town.') + page.find("div[id^='taTextElement']").native.send_keys('In demand, and on_demand! The hottest cakes in town.') click_button 'Create' @@ -225,12 +224,14 @@ feature %q{ visit spree.admin_product_images_path(product) page.should have_selector "table[data-hook='images_table'] td img" - product.reload.images.count.should == 1 + expect(product.reload.images.count).to eq 1 - page.find('a.delete-resource').click - wait_until { product.reload.images.count == 0 } + accept_alert do + page.find('a.delete-resource').click + end - page.should_not have_selector "table[data-hook='images_table'] td img" + expect(page).to_not have_selector "table[data-hook='images_table'] td img" + expect(product.reload.images.count).to eq 0 end end end diff --git a/spec/features/admin/schedules_spec.rb b/spec/features/admin/schedules_spec.rb index 33eace602d..6cc3ae4200 100644 --- a/spec/features/admin/schedules_spec.rb +++ b/spec/features/admin/schedules_spec.rb @@ -108,7 +108,9 @@ feature 'Schedules', js: true do end within "#schedule-dialog" do - click_button "Delete Schedule" + accept_alert do + click_button "Delete Schedule" + end end save_bar = find("#save-bar") diff --git a/spec/features/admin/shipping_methods_spec.rb b/spec/features/admin/shipping_methods_spec.rb index 4a06ea139a..f6d4935a55 100644 --- a/spec/features/admin/shipping_methods_spec.rb +++ b/spec/features/admin/shipping_methods_spec.rb @@ -94,6 +94,9 @@ feature 'shipping methods' do check "shipping_method_distributor_ids_#{distributor1.id}" find(:css, "tags-input .tags input").set "local\n" + within(".tags .tag-list") do + expect(page).to have_css '.tag-item' + end click_button 'Create' diff --git a/spec/features/admin/subscriptions_spec.rb b/spec/features/admin/subscriptions_spec.rb index 37b496919d..27bfaa1bfc 100644 --- a/spec/features/admin/subscriptions_spec.rb +++ b/spec/features/admin/subscriptions_spec.rb @@ -70,7 +70,7 @@ feature 'Subscriptions' do # Viewing Products within "tr#so_#{subscription.id}" do expect(page).to have_selector "td.items.panel-toggle", text: 3 - page.find("td.items.panel-toggle").trigger('click') + page.find("td.items.panel-toggle").click end within "#subscription-line-items" do @@ -82,7 +82,7 @@ feature 'Subscriptions' do # Viewing Orders within "tr#so_#{subscription.id}" do expect(page).to have_selector "td.orders.panel-toggle", text: 1 - page.find("td.orders.panel-toggle").trigger('click') + page.find("td.orders.panel-toggle").click end within ".subscription-orders" do @@ -93,14 +93,14 @@ feature 'Subscriptions' do within "tr#po_#{proxy_order.id}" do expect(page).to have_no_content 'CANCELLED' accept_alert 'Are you sure?' do - find("a.cancel-order").trigger('click') + find("a.cancel-order").click end expect(page).to have_content 'CANCELLED' expect(proxy_order.reload.canceled_at).to be_within(5.seconds).of Time.zone.now # Resuming an order accept_alert 'Are you sure?' do - find("a.resume-order").trigger('click') + find("a.resume-order").click end # Note: the order itself was not complete when 'cancelled', so state remained as cart expect(page).to have_content 'PENDING' @@ -215,7 +215,7 @@ feature 'Subscriptions' do expect(page).to have_content 'Please add at least one product' # Adding a product and getting a price estimate - select2_search product1.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' + select2_search_async product1.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' fill_in 'add_quantity', with: 2 click_link 'Add' within 'table#subscription-line-items tr.item', match: :first do @@ -241,7 +241,7 @@ feature 'Subscriptions' do click_button('edit-products') # Adding a new product - select2_search product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' + select2_search_async product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' fill_in 'add_quantity', with: 3 click_link 'Add' within 'table#subscription-line-items tr.item', match: :first do @@ -255,14 +255,18 @@ feature 'Subscriptions' do expect{ click_button('Create Subscription') - expect(page).to have_content 'Saved' + expect(page).to have_current_path admin_subscriptions_path }.to change(Subscription, :count).by(1) - # Prices are shown + select2_select shop.name, from: "shop_id" + expect(page).to have_selector "td.items.panel-toggle" + first("td.items.panel-toggle").click + + # Prices are shown in the index within 'table#subscription-line-items tr.item', match: :first do expect(page).to have_selector 'td.description', text: "#{product2.name} - #{variant2.full_name}" expect(page).to have_selector 'td.price', text: "$7.75" - expect(page).to have_selector 'td.quantity', text: "3" + expect(page).to have_input 'quantity', with: "3" expect(page).to have_selector 'td.total', text: "$23.25" end @@ -343,7 +347,7 @@ feature 'Subscriptions' do expect(page).to have_content 'Please add at least one product' # Add variant2 to the subscription - select2_search product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' + select2_search_async product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' fill_in 'add_quantity', with: 1 click_link 'Add' within "#sli_0" do @@ -357,7 +361,7 @@ feature 'Subscriptions' do expect(page).to have_selector '#order_form_total', text: "$7.75" # Add variant3 to the subscription (even though it is not available) - select2_search product3.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' + select2_search_async product3.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop' fill_in 'add_quantity', with: 1 click_link 'Add' within "#sli_1" do @@ -379,7 +383,11 @@ feature 'Subscriptions' do end click_button 'Save Changes' - expect(page).to have_content 'Saved' + expect(page).to have_current_path admin_subscriptions_path + + select2_select shop.name, from: "shop_id" + expect(page).to have_selector "td.items.panel-toggle" + first("td.items.panel-toggle").click # Total should be $7.75 expect(page).to have_selector '#order_form_total', text: "$7.75" diff --git a/spec/features/admin/tag_rules_spec.rb b/spec/features/admin/tag_rules_spec.rb index 188fb86cc1..591d8cde26 100644 --- a/spec/features/admin/tag_rules_spec.rb +++ b/spec/features/admin/tag_rules_spec.rb @@ -13,9 +13,6 @@ feature 'Tag Rules', js: true do end it "allows creation of rules of each type" do - # Make the whole page visible - page.driver.resize(1280, 2000) - click_link "Tag Rules" # Creating a new tag @@ -123,9 +120,6 @@ feature 'Tag Rules', js: true do end it "saves changes to rules of each type" do - # Make the whole page visible - page.driver.resize(1280, 2000) - click_link "Tag Rules" # Tag groups exist @@ -135,20 +129,20 @@ feature 'Tag Rules', js: true do expect(page).to have_selector '.customer_tag .header tags-input .tag-list ti-tag-item', text: "wholesale", count: 1 expect(page).to have_selector '.customer_tag .header tags-input .tag-list ti-tag-item', text: "trusted", count: 1 all(:css, ".customer_tag .header tags-input").each do |node| - node.find("li.tag-item a.remove-button").trigger('click') + node.find("li.tag-item a.remove-button").click node.find(".tags input").set "volunteer\n" end # DEFAULT FilterShippingMethods rule within ".default_rules #tr_0" do - within "li.tag-item", text: "local ✖" do find("a.remove-button").trigger('click') end + within "li.tag-item", text: "local ✖" do find("a.remove-button").click end find(:css, "tags-input .tags input").set "volunteers-only\n" expect(page).to have_content "not visible" end # FilterProducts rule within ".customer_tag #tr_1" do - within "li.tag-item", text: "member ✖" do find("a.remove-button").trigger('click') end + within "li.tag-item", text: "member ✖" do find("a.remove-button").click end find(:css, "tags-input .tags input").set "volunteers-only1\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_1_preferred_matched_variants_visibility", selected: 'VISIBLE' select2_select 'NOT VISIBLE', from: "enterprise_tag_rules_attributes_1_preferred_matched_variants_visibility" @@ -156,7 +150,7 @@ feature 'Tag Rules', js: true do # FilterPaymentMethods rule within ".customer_tag #tr_2" do - within "li.tag-item", text: "trusted ✖" do find("a.remove-button").trigger('click') end + within "li.tag-item", text: "trusted ✖" do find("a.remove-button").click end find(:css, "tags-input .tags input").set "volunteers-only2\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_2_preferred_matched_payment_methods_visibility", selected: 'NOT VISIBLE' select2_select 'VISIBLE', from: "enterprise_tag_rules_attributes_2_preferred_matched_payment_methods_visibility" @@ -164,7 +158,7 @@ feature 'Tag Rules', js: true do # FilterOrderCycles rule within ".customer_tag #tr_3" do - within "li.tag-item", text: "wholesale ✖" do find("a.remove-button").trigger('click') end + within "li.tag-item", text: "wholesale ✖" do find("a.remove-button").click end find(:css, "tags-input .tags input").set "volunteers-only3\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_3_preferred_matched_order_cycles_visibility", selected: 'VISIBLE' select2_select 'NOT VISIBLE', from: "enterprise_tag_rules_attributes_3_preferred_matched_order_cycles_visibility" @@ -172,7 +166,7 @@ feature 'Tag Rules', js: true do # FilterShippingMethods rule within ".customer_tag #tr_4" do - within "li.tag-item", text: "local ✖" do find("a.remove-button").trigger('click') end + within "li.tag-item", text: "local ✖" do find("a.remove-button").click end find(:css, "tags-input .tags input").set "volunteers-only4\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_4_preferred_matched_shipping_methods_visibility", selected: 'NOT VISIBLE' select2_select 'VISIBLE', from: "enterprise_tag_rules_attributes_4_preferred_matched_shipping_methods_visibility" @@ -234,15 +228,16 @@ feature 'Tag Rules', js: true do end it "deletes both default and customer rules from the database" do - # Make the whole page visible - page.driver.resize(1280, 2000) - click_link "Tag Rules" expect do - within "#tr_1" do first("a.delete-tag-rule").click end + accept_alert do + within "#tr_1" do first("a.delete-tag-rule").click end + end expect(page).to have_no_selector "#tr_1" - within "#tr_0" do first("a.delete-tag-rule").click end + accept_alert do + within "#tr_0" do first("a.delete-tag-rule").click end + end expect(page).to have_no_selector "#tr_0" end.to change{TagRule.count}.by(-2) end diff --git a/spec/features/admin/variant_overrides_spec.rb b/spec/features/admin/variant_overrides_spec.rb index b4633cc7d7..fbdfaf3185 100644 --- a/spec/features/admin/variant_overrides_spec.rb +++ b/spec/features/admin/variant_overrides_spec.rb @@ -303,7 +303,7 @@ feature %q{ within "tr#v_#{variant.id}" do vo.tag_list.each do |tag| within "li.tag-item", text: "#{tag} ✖" do - find("a.remove-button").trigger('click') + find("a.remove-button").click end end end diff --git a/spec/features/admin/variants_spec.rb b/spec/features/admin/variants_spec.rb index cce1733d7b..d47f7dc6bf 100644 --- a/spec/features/admin/variants_spec.rb +++ b/spec/features/admin/variants_spec.rb @@ -66,7 +66,9 @@ feature %q{ visit spree.admin_product_variants_path p within "tr#spree_variant_#{v.id}" do - page.find('a.delete-resource').click + accept_alert do + page.find('a.delete-resource').click + end end page.should_not have_selector "tr#spree_variant_#{v.id}" diff --git a/spec/features/consumer/authentication_spec.rb b/spec/features/consumer/authentication_spec.rb index be29540e94..dfacebf28f 100644 --- a/spec/features/consumer/authentication_spec.rb +++ b/spec/features/consumer/authentication_spec.rb @@ -114,6 +114,9 @@ feature "Authentication", js: true, retry: 3 do before do browse_as_medium end + after do + browse_as_large + end scenario "showing login" do open_off_canvas open_login_modal diff --git a/spec/features/consumer/multilingual_spec.rb b/spec/features/consumer/multilingual_spec.rb index e0c0793154..4e6ac07d8f 100644 --- a/spec/features/consumer/multilingual_spec.rb +++ b/spec/features/consumer/multilingual_spec.rb @@ -4,6 +4,8 @@ feature 'Multilingual', js: true do include AuthenticationWorkflow include WebHelper include ShopWorkflow + include UIComponentHelper + include CookieHelper it 'has two locales available' do expect(Rails.application.config.i18n[:default_locale]).to eq 'en' @@ -22,7 +24,7 @@ feature 'Multilingual', js: true do visit root_path expect(get_i18n_locale).to eq 'en' expect(get_i18n_translation('label_shops')).to eq 'Shops' - expect(page.driver.browser.cookies['locale']).to be_nil + expect(cookie_named('locale')).to be_nil expect(page).to have_content 'Interested in getting on the Open Food Network?' expect(page).to have_content 'SHOPS' @@ -96,6 +98,7 @@ feature 'Multilingual', js: true do end describe "using the language switcher UI" do + before { browse_as_large } context "when there is only one language available" do before do allow(ENV).to receive(:[]).and_call_original @@ -136,6 +139,6 @@ feature 'Multilingual', js: true do end def expect_menu_and_cookie_in_es - expect(page.driver.browser.cookies['locale'].value).to eq 'es' + expect(cookie_named('locale')[:value]).to eq 'es' expect(page).to have_content 'TIENDAS' end diff --git a/spec/features/consumer/producers_spec.rb b/spec/features/consumer/producers_spec.rb index ca8321dda7..514c71d7c4 100644 --- a/spec/features/consumer/producers_spec.rb +++ b/spec/features/consumer/producers_spec.rb @@ -30,7 +30,7 @@ feature %q{ end - pending "searches by URL" do + it "searches by URL" do visit producers_path(anchor: "/?query=xyzzy") expect(page).to have_content "Sorry, no results found for xyzzy" end diff --git a/spec/features/consumer/registration_spec.rb b/spec/features/consumer/registration_spec.rb index b0818cd79b..0a7756d104 100644 --- a/spec/features/consumer/registration_spec.rb +++ b/spec/features/consumer/registration_spec.rb @@ -33,13 +33,16 @@ feature "Registration", js: true do # Enter Login details fill_in "Email", with: user.email fill_in "Password", with: user.password - click_login_and_ensure_content "Hi there!" + + click_button "Login" + expect(page).to have_content("Hi there!") expect(URI.parse(current_url).path).to eq registration_path # Done reading introduction page.has_content? - perform_and_ensure(:click_button, "Let's get started!", lambda { page.has_content? 'Woot!' }) + click_button "Let's get started!" + expect(page).to have_content 'Woot!' # Filling in details fill_in 'enterprise_name', with: "My Awesome Enterprise" @@ -50,18 +53,24 @@ feature "Registration", js: true do fill_in 'enterprise_zipcode', with: '3070' expect(page).to have_select('enterprise_country', options: %w(Albania Australia), selected: 'Australia') select 'Vic', from: 'enterprise_state' - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Who is responsible for managing My Awesome Enterprise?' }) + click_button "Continue" + expect(page).to have_content 'Who is responsible for managing My Awesome Enterprise?' # Filling in Contact Details fill_in 'enterprise_contact', with: 'Saskia Munroe' page.should have_field 'enterprise_email_address', with: user.email fill_in 'enterprise_phone', with: '12 3456 7890' - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Last step to add My Awesome Enterprise!' }) + click_button "Continue" + expect(page).to have_content 'Last step to add My Awesome Enterprise!' # Choosing a type - perform_and_ensure(:click_link, 'producer-panel', lambda { page.has_selector? '#producer-panel.selected' } ) - perform_and_ensure(:click_button, "Create Profile", lambda { page.has_content? 'Nice one!' }) + click_link "producer-panel" + expect(page).to have_selector '#producer-panel.selected' + + # Next (profile is created at this point) + click_button "Create Profile" + expect(page).to have_content 'Nice one!' # Enterprise should be created e = Enterprise.find_by_name('My Awesome Enterprise') @@ -77,7 +86,8 @@ feature "Registration", js: true do fill_in 'enterprise_abn', with: '12345' fill_in 'enterprise_acn', with: '54321' choose 'Yes' # enterprise_charges_sales_tax - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Step 1. Select Logo Image' }) + click_button "Continue" + expect(page).to have_content 'Step 1. Select Logo Image' # Enterprise should be updated e.reload @@ -89,10 +99,12 @@ feature "Registration", js: true do # Images # Move from logo page - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Step 3. Select Promo Image' }) + click_button "Continue" + expect(page).to have_content 'Step 3. Select Promo Image' # Move from promo page - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'How can people find My Awesome Enterprise online?' }) + click_button "Continue" + expect(page).to have_content 'How can people find My Awesome Enterprise online?' # Filling in social fill_in 'enterprise_website', with: 'www.shop.com' @@ -100,7 +112,8 @@ feature "Registration", js: true do fill_in 'enterprise_linkedin', with: 'LiNkEdIn' fill_in 'enterprise_twitter', with: '@TwItTeR' fill_in 'enterprise_instagram', with: '@InStAgRaM' - perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Finished!' }) + click_button "Continue" + expect(page).to have_content 'Finished!' # Done e.reload @@ -125,7 +138,8 @@ feature "Registration", js: true do # Enter Login details fill_in "Email", with: user.email fill_in "Password", with: user.password - click_login_and_ensure_content I18n.t('limit_reached_headline') + click_button 'Login' + expect(page).to have_content I18n.t('limit_reached_headline') end end end @@ -157,7 +171,8 @@ feature "Registration", js: true do expect(page).to have_content "Terms of Service" expect(page).to have_selector "input.button.primary[disabled]" - perform_and_ensure(:check, "accept_terms", lambda { page.has_no_selector? "input.button.primary[disabled]" }) + check "accept_terms" + expect(page).to have_no_selector "input.button.primary[disabled]" click_button "Let's get started!" expect(find("div#progress-bar")).to be_visible @@ -174,15 +189,4 @@ feature "Registration", js: true do end end end - - def click_login_and_ensure_content(content) - # Buttons appear to be unresponsive for a while, so keep clicking them until content appears - using_wait_time 1 do - 3.times do - click_button "Login" - break if page.has_selector? "div#loading", text: "Hold on a moment, we're logging you in" - end - end - expect(page).to have_content content - end end diff --git a/spec/features/consumer/shopping/cart_spec.rb b/spec/features/consumer/shopping/cart_spec.rb index e0ce56cedc..09d4821f1c 100644 --- a/spec/features/consumer/shopping/cart_spec.rb +++ b/spec/features/consumer/shopping/cart_spec.rb @@ -154,7 +154,9 @@ feature "full-page cart", js: true do visit spree.cart_path variant.update_attributes! on_hand: 2 - fill_in "order_line_items_attributes_0_quantity", with: '4' + accept_alert do + fill_in "order_line_items_attributes_0_quantity", with: '4' + end click_button 'Update' expect(page).to have_content "Insufficient stock available, only 2 remaining" diff --git a/spec/features/consumer/shopping/embedded_groups_spec.rb b/spec/features/consumer/shopping/embedded_groups_spec.rb index b53f12c2eb..788bd2970e 100644 --- a/spec/features/consumer/shopping/embedded_groups_spec.rb +++ b/spec/features/consumer/shopping/embedded_groups_spec.rb @@ -10,7 +10,6 @@ feature "Using embedded shopfront functionality", js: true do before do Spree::Config[:enable_embedded_shopfronts] = true Spree::Config[:embedded_shopfronts_whitelist] = 'test.com' - page.driver.browser.js_errors = false allow_any_instance_of(ActionDispatch::Request).to receive(:referer).and_return('https://www.test.com') visit "/embedded-group-preview.html?#{group.permalink}" end diff --git a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb index 80f7e52eee..5a97040e32 100644 --- a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb +++ b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb @@ -76,11 +76,11 @@ feature "Using embedded shopfront functionality", js: true do end within "#shipping" do - find('input[type="radio"]').trigger 'click' + find('input[type="radio"]').click end within "#payment" do - find('input[type="radio"]').trigger 'click' + find('input[type="radio"]').click end place_order @@ -91,10 +91,11 @@ feature "Using embedded shopfront functionality", js: true do it "redirects to embedded hub on logout when embedded" do on_embedded_page do - + wait_for_shop_loaded find('ul.right li#login-link a').click login_with_modal + wait_for_shop_loaded wait_until { page.find('ul.right li.user-menu.has-dropdown').value.present? } logout_via_navigation @@ -105,6 +106,14 @@ feature "Using embedded shopfront functionality", js: true do private + # When you have pending changes and try to navigate away from a page, it asks you "Are you sure?". + # When we click the "Update" button to save changes, we need to wait + # until it is actually saved and "loading" disappears before doing anything else. + def wait_for_shop_loaded + page.has_no_content? "Loading" + page.has_no_css? "input[value='Updating cart...']" + end + def login_with_modal expect(page).to have_selector 'div.login-modal', visible: true diff --git a/spec/features/consumer/shopping/orders_spec.rb b/spec/features/consumer/shopping/orders_spec.rb index 3d1182e95e..bf18c8cb78 100644 --- a/spec/features/consumer/shopping/orders_spec.rb +++ b/spec/features/consumer/shopping/orders_spec.rb @@ -156,7 +156,9 @@ feature "Order Management", js: true do expect(Spree::LineItem.find_by_id(item2.id)).to be nil # Cancelling the order - click_link(I18n.t(:cancel_order)) + accept_alert do + click_link(I18n.t(:cancel_order)) + end expect(page).to have_content I18n.t(:orders_show_cancelled) expect(order.reload).to be_canceled end diff --git a/spec/features/consumer/shopping/products_spec.rb b/spec/features/consumer/shopping/products_spec.rb index c53027b12d..f844634a7e 100644 --- a/spec/features/consumer/shopping/products_spec.rb +++ b/spec/features/consumer/shopping/products_spec.rb @@ -32,7 +32,8 @@ feature "As a consumer I want to view products", js: true do visit shop_path select "monday", :from => "order_cycle_id" - perform_and_ensure(:click_link, product.name, lambda{ page.has_selector?('.reveal-modal')}) + click_link product.name + expect(page).to have_selector '.reveal-modal' modal_should_be_open_for product within(".reveal-modal") do @@ -47,7 +48,8 @@ feature "As a consumer I want to view products", js: true do visit shop_path select "monday", :from => "order_cycle_id" - perform_and_ensure(:click_link, product.name, lambda{ page.has_selector?('.reveal-modal')}) + click_link product.name + expect(page).to have_selector '.reveal-modal' modal_should_be_open_for product within(".reveal-modal") do diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 17d1d49a21..4b18a62434 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -103,14 +103,16 @@ feature "As a consumer I want to shop with a distributor", js: true do within("li.cart") { page.should have_content with_currency(1020.99) } # -- Changing order cycle - select "frogs", from: "order_cycle_id" + accept_alert do + select "frogs", from: "order_cycle_id" + end page.should have_content with_currency(19.99) # -- Cart should be cleared - # ng-animate means that the old product row is likely to be present, so we explicitly - # fill in the quantity in the incoming row + # ng-animate means that the old product row is likely to be present, so we ensure + # that we are not filling in the quantity on the outgoing row page.should_not have_selector "tr.product-cart" - within('product.ng-enter') { fill_in "variants[#{variant.id}]", with: 1 } + within('product:not(.ng-leave)') { fill_in "variants[#{variant.id}]", with: 1 } within("li.cart") { page.should have_content with_currency(19.99) } end diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 186508532d..5e28f8ae50 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -17,7 +17,7 @@ feature 'Shops', js: true do producer.set_producer_property 'Organic', 'NASAA 12345' end - pending "searches by URL" do + it "searches by URL" do visit shops_path(anchor: "/?query=xyzzy") expect(page).to have_content "Sorry, no results found for xyzzy" end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 66924edea8..25dac67716 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -39,16 +39,14 @@ require 'spree/testing_support/authorization_helpers' require 'spree/testing_support/preferences' # Capybara config -require 'capybara/poltergeist' -Capybara.javascript_driver = :poltergeist +require 'selenium-webdriver' +Capybara.javascript_driver = :chrome -Capybara.register_driver :poltergeist do |app| - options = {phantomjs_options: ['--load-images=no', '--ssl-protocol=any'], window_size: [1280, 3600], timeout: 2.minutes} - # Extend poltergeist's timeout to allow ample time to use pry in browser thread - #options.merge! {timeout: 5.minutes} - # Enable the remote inspector: Use page.driver.debug to open a remote debugger in chrome - #options.merge! {inspector: true} - Capybara::Poltergeist::Driver.new(app, options) +Capybara.register_driver :chrome do |app| + options = Selenium::WebDriver::Chrome::Options.new( + args: %w[headless disable-gpu no-sandbox window-size=1280,768] + ) + Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) end Capybara.default_max_wait_time = 30 @@ -99,8 +97,8 @@ RSpec.configure do |config| def restart_phantomjs Capybara.send('session_pool').values - .select { |s| s.driver.is_a?(Capybara::Poltergeist::Driver) } - .each { |s| s.driver.restart} + .select { |s| s.driver.is_a?(Capybara::Selenium::Driver) } + .each { |s| s.driver.reset! } end config.before(:all) { restart_phantomjs } diff --git a/spec/support/matchers/select2_matchers.rb b/spec/support/matchers/select2_matchers.rb index 58bfc690d8..5e57f05d73 100644 --- a/spec/support/matchers/select2_matchers.rb +++ b/spec/support/matchers/select2_matchers.rb @@ -21,7 +21,7 @@ RSpec::Matchers.define :have_select2 do |id, options={}| if results.all? results << all_options_present(from, options[:with_options]) if options.key? :with_options results << exact_options_present(from, options[:options]) if options.key? :options - results << no_options_present(from, options[:without_options]) if options.key? :without_options + results << all_options_absent(from, options[:without_options]) if options.key? :without_options end results.all? @@ -88,14 +88,6 @@ RSpec::Matchers.define :have_select2 do |id, options={}| end end - def no_options_present(from, options) - with_select2_open(from) do - options.none? do |option| - @node.has_selector? "div.select2-drop-active ul.select2-results li", text: option - end - end - end - def selected_option_is(from, text) within find(from) do find("a.select2-choice").text == text diff --git a/spec/support/matchers/table_matchers.rb b/spec/support/matchers/table_matchers.rb index 0a4c3b1e09..7b3d7ebf96 100644 --- a/spec/support/matchers/table_matchers.rb +++ b/spec/support/matchers/table_matchers.rb @@ -2,15 +2,11 @@ RSpec::Matchers.define :have_table_row do |row| match do |node| @row = row - - node.has_selector? "tr", text: row.join(" ").strip # Check for appearance rows_under(node).include? row # Robust check of columns end match_when_negated do |node| @row = row - - node.has_no_selector? "tr", text: row.join(" ").strip # Check for appearance !rows_under(node).include? row # Robust check of columns end diff --git a/spec/support/request/checkout_workflow.rb b/spec/support/request/checkout_workflow.rb index 11a13194bc..8a4ea7974d 100644 --- a/spec/support/request/checkout_workflow.rb +++ b/spec/support/request/checkout_workflow.rb @@ -4,15 +4,15 @@ module CheckoutWorkflow end def checkout_as_guest - find("button", text: "Checkout as guest").trigger "click" + find("button", text: "Checkout as guest").click end def place_order - find("button", text: "Place order now").trigger "click" + find("button", text: "Place order now").click end def toggle_accordion(id) - find("##{id} dd a").trigger "click" + find("##{id} dd a").click end def toggle_details diff --git a/spec/support/request/cookie_helper.rb b/spec/support/request/cookie_helper.rb new file mode 100644 index 0000000000..a7a6d8cd0e --- /dev/null +++ b/spec/support/request/cookie_helper.rb @@ -0,0 +1,5 @@ +module CookieHelper + def cookie_named(name) + Capybara.current_session.driver.browser.manage.cookie_named(name) + end +end diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 9df7f72126..98b0a52d86 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -25,7 +25,7 @@ module ShopWorkflow end def toggle_accordion(name) - find("dd a", text: name).trigger "click" + find("dd a", text: name).click end def add_variant_to_order_cycle(exchange, variant) diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index 1203a50222..27f5cdae0a 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -1,10 +1,12 @@ module UIComponentHelper def browse_as_medium - page.driver.resize(1024, 768) + Capybara.current_session.current_window + .resize_to(1024, 768) end def browse_as_large - page.driver.resize(1280, 800) + Capybara.current_session.current_window + .resize_to(1280, 800) end def click_login_button @@ -43,7 +45,7 @@ module UIComponentHelper end def open_enterprise_modal(enterprise) - page.find("a", text: enterprise.name).trigger "click" + page.find("a", text: enterprise.name).click end def modal_should_be_open_for(object) diff --git a/spec/support/request/web_helper.rb b/spec/support/request/web_helper.rb index fd9cceb3b0..c37014e637 100644 --- a/spec/support/request/web_helper.rb +++ b/spec/support/request/web_helper.rb @@ -42,7 +42,7 @@ module WebHelper end def flash_message - find('.flash', visible: false).text.strip + find('.flash', visible: false).text(:all).strip end def handle_js_confirm(accept=true) @@ -118,17 +118,28 @@ module WebHelper page.execute_script "jQuery('#{selector}').select2('close');" end - def perform_and_ensure(action, *args, assertion) - # Buttons/Links/Checkboxes can be unresponsive for a while - # so keep clicking them until assertion is satified - using_wait_time 0.5 do - 10.times do - send(action, *args) - return if assertion.call - end - # Only make it here if we have tried 10 times - expect(assertion.call).to be true + def select2_search_async(value, options) + id = find_label_by_text(options[:from]) + options[:from] = "#s2id_#{id}" + targetted_select2_search_async(value, options) + end + + def targetted_select2_search_async(value, options) + page.execute_script %Q{$('#{options[:from]}').select2('open')} + page.execute_script "$('#{options[:dropdown_css]} input.select2-input').val('#{value}').trigger('keyup-change');" + select_select2_result_async(value) + end + + def select_select2_result_async(value) + while (page.has_selector? "div.select2-searching") do + return if page.has_selector? "div.select2-no-results" + sleep 0.2 end + page.execute_script(%Q{$("div.select2-result-label:contains('#{value}')").mouseup()}) + end + + def accept_js_alert + page.driver.browser.switch_to.alert.accept end private