diff --git a/Changelog.md b/Changelog.md index 6fd920b47..4921679c3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -37,6 +37,7 @@ Although the chat was never enabled per default and was marked as experimental, ## Refactor * Replaced some `http://` links in the UI with their `https://` counterparts [#8207](https://github.com/diaspora/diaspora/pull/8207) +* Testing: Replaced phantomjs with headless Chrome/Chromium [#8234](https://github.com/diaspora/diaspora/pull/8234) ## Bug fixes * Update comment counter when weleting a comment in the Single Post View [#7938](https://github.com/diaspora/diaspora/pull/7938) diff --git a/Gemfile b/Gemfile index 7ae357651..a0b2d4f59 100644 --- a/Gemfile +++ b/Gemfile @@ -280,9 +280,9 @@ group :test do # Cucumber (integration tests) - gem "capybara", "3.15.0" - gem "database_cleaner", "1.8.3" - gem "poltergeist", "1.18.1" + gem "apparition", "0.6.0" + gem "capybara", "3.15.0" + gem "database_cleaner", "1.8.3" gem "cucumber-api-steps", "0.14", require: false @@ -304,6 +304,7 @@ group :development, :test do gem "cucumber-rails", "2.0.0", require: false # Jasmine (client side application tests (JS)) + gem "chrome_remote", "0.3.0" gem "jasmine", "3.6.0" gem "jasmine-jquery-rails", "2.0.3" gem "rails-assets-jasmine-ajax", "4.0.0", source: "https://gems.diasporafoundation.org" diff --git a/Gemfile.lock b/Gemfile.lock index 974a66f52..bed503654 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,6 +57,9 @@ GEM addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) aes_key_wrap (1.0.1) + apparition (0.6.0) + capybara (~> 3.13, < 4) + websocket-driver (>= 0.6.5) arel (9.0.0) asset_sync (2.11.0) activemodel (>= 4.1.0) @@ -116,9 +119,10 @@ GEM timers (>= 4.1.1) celluloid-supervision (0.20.6) timers (>= 4.1.1) + chrome_remote (0.3.0) + websocket-driver (~> 0.6) chunky_png (1.3.11) citrus (3.0.2) - cliver (0.3.2) coderay (1.1.2) compass (1.0.3) chunky_png (~> 1.2) @@ -235,7 +239,7 @@ GEM http-cookie (~> 1.0.0) faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) - ffi (1.12.2) + ffi (1.15.0) ffi-compiler (1.0.1) ffi (>= 1.0.0) rake @@ -322,7 +326,7 @@ GEM http-cookie (1.0.3) domain_name (~> 0.5) http-form_data (2.3.0) - http-parser (1.2.1) + http-parser (1.2.3) ffi-compiler (>= 1.0, < 2.0) http_accept_language (2.1.1) http_parser.rb (0.6.0) @@ -472,10 +476,6 @@ GEM ast (~> 2.4.0) pg (1.2.3) phantomjs (2.1.1.0) - poltergeist (1.18.1) - capybara (>= 2.1, < 4) - cliver (~> 0.3.1) - websocket-driver (>= 0.2.0) pronto (0.10.0) gitlab (~> 4.0, >= 4.0.0) httparty (>= 0.13.7) @@ -659,7 +659,7 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sassc (2.2.1) + sassc (2.4.0) ffi (~> 1.9) sawyer (0.8.2) addressable (>= 2.3.5) @@ -790,12 +790,14 @@ DEPENDENCIES acts-as-taggable-on (= 6.5.0) acts_as_api (= 1.0.1) addressable (= 2.7.0) + apparition (= 0.6.0) asset_sync (= 2.11.0) autoprefixer-rails (= 8.6.5) bootstrap-sass (= 3.4.1) bootstrap-switch-rails (= 3.3.3) capybara (= 3.15.0) carrierwave (= 1.3.1) + chrome_remote (= 0.3.0) compass-rails (= 3.1.0) configurate (= 0.5.0) cucumber-api-steps (= 0.14) @@ -849,7 +851,6 @@ DEPENDENCIES open_graph_reader (= 0.7.0) openid_connect (= 1.1.8) pg (= 1.2.3) - poltergeist (= 1.18.1) pronto (= 0.10.0) pronto-eslint (= 0.10.0) pronto-haml (= 0.10.0) diff --git a/config/cucumber.yml b/config/cucumber.yml index 35ca76a82..133853dcb 100644 --- a/config/cucumber.yml +++ b/config/cucumber.yml @@ -9,7 +9,7 @@ screenshot_opts = "--require features --format pretty" %> # 'normal' test runs -default: <%= std_opts %> -r features --tags 'not @nophantomjs' +default: <%= std_opts %> -r features wip: -r features --tags @wip:3 --wip features rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags 'not @wip and not @screenshots' diff --git a/docker/develop/Dockerfile b/docker/develop/Dockerfile index 6df7b9795..45617302d 100644 --- a/docker/develop/Dockerfile +++ b/docker/develop/Dockerfile @@ -43,13 +43,6 @@ RUN addgroup --gid $DIA_GID diaspora && \ chown -R diaspora:diaspora $HOME /diaspora -RUN curl -L \ - https://cifiles.diasporafoundation.org/phantomjs-2.1.1-linux-x86_64.tar.bz2 \ - | tar -xj -C /usr/local/bin \ - --transform='s#.*/##' \ - phantomjs-2.1.1-linux-x86_64/bin/phantomjs - - ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_BIN="$GEM_HOME/bin" \ BUNDLE_APP_CONFIG="/diaspora/.bundle" diff --git a/features/desktop/change_settings.feature b/features/desktop/change_settings.feature index ce60f7422..4655b2a9d 100644 --- a/features/desktop/change_settings.feature +++ b/features/desktop/change_settings.feature @@ -19,10 +19,12 @@ Feature: Change settings Scenario: Change my email preferences When I uncheck "user_email_preferences_mentioned" + And I scroll a bit And I press "change_email_preferences" Then I should see "Email notifications changed" And the "user_email_preferences_mentioned" checkbox should not be checked When I uncheck "user_email_preferences_mentioned_in_comment" + And I scroll a bit And I press "change_email_preferences" Then I should see "Email notifications changed" And the "user_email_preferences_mentioned_in_comment" checkbox should not be checked diff --git a/features/desktop/comments.feature b/features/desktop/comments.feature index 2a1afbf54..0ef2ca6c8 100644 --- a/features/desktop/comments.feature +++ b/features/desktop/comments.feature @@ -19,7 +19,6 @@ Feature: commenting When I focus the comment field And I fill in the following: | text | is that a poodle? | - And I reject the alert after I follow "My activity" And I press "Comment" Then I should see "is that a poodle?" within ".comment" And I should see "less than a minute ago" within ".comment time" diff --git a/features/desktop/edits_profile.feature b/features/desktop/edits_profile.feature index 90e7b06bb..f99d7dbc6 100644 --- a/features/desktop/edits_profile.feature +++ b/features/desktop/edits_profile.feature @@ -34,7 +34,6 @@ Feature: editing your profile And the "#profile_public_details" bootstrap-switch should be off When I fill in "profile_bio" with "This is a new awesome bio" - And I reject the alert after I follow "My activity" Then I should be on my edit profile page When I fill in "profile[tag_string]" with "#kamino" diff --git a/features/desktop/follows_tags.feature b/features/desktop/follows_tags.feature index fcdfbf3a5..eeabe19fa 100644 --- a/features/desktop/follows_tags.feature +++ b/features/desktop/follows_tags.feature @@ -33,7 +33,7 @@ Feature: posting Then I should see "#boss from the #boss tag page" within "body" Scenario: can stop following a tag from the tag page - When I press "Following #boss" + When I press "Stop following #boss" And I go to the followed tags stream page Then I should not see "#boss" within "#tags_list" diff --git a/features/desktop/getting_started.feature b/features/desktop/getting_started.feature index bbebd5efa..a41d68bd3 100644 --- a/features/desktop/getting_started.feature +++ b/features/desktop/getting_started.feature @@ -11,10 +11,10 @@ Feature: new user registration Scenario: new user goes through the setup wizard When I fill in the following: | profile_first_name | O | - And I confirm the alert after I follow "awesome_button" - Then I should be on the stream page - And the publisher should be expanded - And I close the publisher + Then I wait until ajax requests finished + When I go to the stream page + Then the publisher should be expanded + When I close the publisher Then I should not see "awesome_button" And I should not see any posts in my stream diff --git a/features/desktop/invitations.feature b/features/desktop/invitations.feature index 75a5758ed..fa43a32ce 100644 --- a/features/desktop/invitations.feature +++ b/features/desktop/invitations.feature @@ -12,12 +12,11 @@ Feature: Invitations And I press "Create account" Then I should be on the getting started page And I should see "Well, hello there!" - And I fill in the following: + When I fill in the following: | profile_first_name | O | - - And I confirm the alert after I follow "awesome_button" - Then I should be on the stream page - And I close the publisher + Then I wait until ajax requests finished + When I go to the stream page + Then I close the publisher Scenario: accept invitation from user Given I have been invited by "alice@alice.alice" @@ -27,11 +26,10 @@ Feature: Invitations Then I should be on the getting started page And I should see "Well, hello there!" And I should be able to friend "alice@alice.alice" - And I fill in the following: + When I fill in the following: | profile_first_name | O | - - And I confirm the alert after I follow "awesome_button" - Then I should be on the stream page + Then I wait until ajax requests finished + When I go to the stream page And I close the publisher And I log out And I sign in as "alice@alice.alice" diff --git a/features/desktop/media-embed.feature b/features/desktop/media-embed.feature index 6df7da211..23ff9795c 100644 --- a/features/desktop/media-embed.feature +++ b/features/desktop/media-embed.feature @@ -1,5 +1,4 @@ # We can create a separate cucumber profile that will run these tests with Selenium -@nophantomjs @javascript Feature: oembed In order to make videos easy accessible diff --git a/features/desktop/mentions.feature b/features/desktop/mentions.feature index d68358b58..8cba48e96 100644 --- a/features/desktop/mentions.feature +++ b/features/desktop/mentions.feature @@ -42,7 +42,7 @@ Feature: Mentions Then I should see "Bob Jones" within ".tt-suggestion" When I click on the first user in the mentions dropdown list When I press the "A" key in the publisher - And I append "@Bob" to the publisher + And I type "@Bob" into the publisher Then I should not see the mentions dropdown list When I press "Share" Then I should see "Bob Jones" within ".stream-element" @@ -80,8 +80,8 @@ Feature: Mentions And I enter "@Bob" in the comment field Then I should see "Bob Jones" within ".tt-suggestion" When I click on the first user in the mentions dropdown list - And I press the "A" key in the publisher - And I append "@Bob" to the publisher + And I enter " A " in the comment field + And I enter "@Bob" in the comment field Then I should not see the mentions dropdown list When I press "Comment" Then I should see "Bob Jones" within ".comments .comment:last-child" diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature index bf6301c12..b914df545 100644 --- a/features/desktop/post_preview.feature +++ b/features/desktop/post_preview.feature @@ -54,7 +54,7 @@ Feature: preview posts in the stream Given I expand the publisher And I mention Alice in the publisher And I preview the post - And I confirm the alert after I follow "Alice Smith" + And I follow "Alice Smith" Then I should see "Alice Smith" Scenario: preview a post on tag page diff --git a/features/desktop/single_post_view_moderation.feature b/features/desktop/single_post_view_moderation.feature index af90de2c4..816354ccf 100644 --- a/features/desktop/single_post_view_moderation.feature +++ b/features/desktop/single_post_view_moderation.feature @@ -44,7 +44,7 @@ And I sign in as "alice@alice.alice" And I open the show page of the "Here is a post to test with" post - And I confirm the alert after I click to report the post + And I confirm the prompt after I click to report the post And I should see a flash message containing "The report has successfully been created" diff --git a/features/mobile/edits_profile.feature b/features/mobile/edits_profile.feature index 402545bf2..9120898f2 100644 --- a/features/mobile/edits_profile.feature +++ b/features/mobile/edits_profile.feature @@ -39,7 +39,7 @@ Feature: editing the profile in the mobile view Then I should see "#kamino" within "ul#as-selections-tags" And I should see "#starwars" within "ul#as-selections-tags" - When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload" + When I accept the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload" And I attach the file "spec/fixtures/button.png" to hidden "qqfile" within "#file-upload" Then I should see "button.png completed" And I should see a "img" within "#profile_photo_upload" diff --git a/features/mobile/getting_started.feature b/features/mobile/getting_started.feature index 1a8b240ec..12b341b92 100644 --- a/features/mobile/getting_started.feature +++ b/features/mobile/getting_started.feature @@ -17,7 +17,7 @@ Feature: editing the getting started in the mobile view And I should not see "awesome_button" Scenario: new user adds a profile photo and tags - When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload" + When I accept the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload" And I attach the file "spec/fixtures/button.png" to hidden "qqfile" within "#file-upload" Then I should see a "img" within "#profile_photo_upload" diff --git a/features/mobile/posts_from_main_page.feature b/features/mobile/posts_from_main_page.feature index 338b271aa..d8aad60b9 100644 --- a/features/mobile/posts_from_main_page.feature +++ b/features/mobile/posts_from_main_page.feature @@ -43,7 +43,7 @@ Feature: posting from the mobile main page Scenario: back out of posting a photo-only post Given I visit the mobile publisher page - When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload-publisher" + When I accept the alert after I attach the file "spec/fixtures/bad_urls.txt" to "qqfile" within "#file-upload-publisher" Then I should not see an uploaded image within the photo drop zone When I attach the file "spec/fixtures/button.png" to hidden "qqfile" within "#file-upload-publisher" And I should see "button.png completed" diff --git a/features/step_definitions/aspects_steps.rb b/features/step_definitions/aspects_steps.rb index b00ddf731..4a5c9e577 100644 --- a/features/step_definitions/aspects_steps.rb +++ b/features/step_definitions/aspects_steps.rb @@ -119,6 +119,7 @@ When /^(.*) in the aspect creation modal$/ do |action| end When /^I drag "([^"]*)" (up|down)$/ do |aspect_name, direction| + expect(page).to have_js_defined("$('body').sortable") page.execute_script("$('#aspect_nav .list-group').sortable('option', 'tolerance', 'pointer');") aspect_id = @me.aspects.where(name: aspect_name).first.id aspect = find(:xpath, "//div[@id='aspect_nav']/ul/a[@data-aspect-id='#{aspect_id}']") diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb index 8f2bde9f5..19eb58138 100644 --- a/features/step_definitions/custom_web_steps.rb +++ b/features/step_definitions/custom_web_steps.rb @@ -85,11 +85,23 @@ And /^I click on the first selector "([^"]*)"$/ do |selector| end And /^I confirm the alert after (.*)$/ do |action| + accept_confirm do + step action + end +end + +And /^I accept the alert after (.*)$/ do |action| accept_alert do step action end end +And /^I confirm the prompt after (.*)$/ do |action| + accept_prompt do + step action + end +end + And /^I reject the alert after (.*)$/ do |action| dismiss_confirm do step action @@ -161,6 +173,10 @@ Then /^I should see (\d+) contacts$/ do |n_posts| has_css?("#people-stream .stream-element", count: n_posts.to_i).should be true end +When /^I scroll a bit$/ do + page.execute_script("window.scrollBy(0,200)") +end + And /^I scroll down$/ do page.execute_script("window.scrollBy(0,3000000)") end diff --git a/features/step_definitions/implicit_flow_steps.rb b/features/step_definitions/implicit_flow_steps.rb index ee4d4bbfb..dfc869eea 100644 --- a/features/step_definitions/implicit_flow_steps.rb +++ b/features/step_definitions/implicit_flow_steps.rb @@ -54,7 +54,6 @@ Then /^I should not see any tokens in the redirect url$/ do end When /^I parse the bearer tokens and use it to access user info$/ do - current_url = page.driver.network_traffic.last.url # We get a redirect to example.org that we can't follow access_token = current_url[/(?<=access_token=)[^&]+/] expect(access_token).to be_present get api_openid_connect_user_info_path, access_token: access_token diff --git a/features/step_definitions/location_steps.rb b/features/step_definitions/location_steps.rb index 268aec049..0998d56a2 100644 --- a/features/step_definitions/location_steps.rb +++ b/features/step_definitions/location_steps.rb @@ -2,18 +2,12 @@ When /^I allow geolocation$/ do page.execute_script <<-JS - window.navigator = { - geolocation: { - getCurrentPosition: function(success) { - success({coords: {latitude: 42.42424242, longitude: 3.14159}}); + OSM.Locator = function() { + return { + getAddress: function(callback) { + callback("locator address", {latitude: 42.42424242, longitude: 3.14159}); } } - }; - - $.getJSON = function(url, myCallback) { - if (url === "https://nominatim.openstreetmap.org/reverse?format=json&lat=42.42424242&lon=3.14159&addressdetails=3") { - return myCallback({display_name: "locator address"}); - } - }; + } JS end diff --git a/features/step_definitions/publisher_steps.rb b/features/step_definitions/publisher_steps.rb index f0d6a8c46..5afa5f5fe 100644 --- a/features/step_definitions/publisher_steps.rb +++ b/features/step_definitions/publisher_steps.rb @@ -47,6 +47,10 @@ When /^I append "([^"]*)" to the publisher$/ do |text| append_to_publisher(text) end +When /^I type "([^"]*)" into the publisher$/ do |text| + type_into_publisher(text) +end + When /^I attach "([^"]*)" to the publisher$/ do |path| upload_file_with_publisher(path) end diff --git a/features/step_definitions/stream_steps.rb b/features/step_definitions/stream_steps.rb index 853df81ca..0702f4bd3 100644 --- a/features/step_definitions/stream_steps.rb +++ b/features/step_definitions/stream_steps.rb @@ -26,6 +26,7 @@ Then /^the post "([^"]*)" should have a like from "([^"]*)"$/ do |post_text, use within_post(post_text) do find(".expand-likes").click find(".likes .avatar")["data-original-title"].should have_content(username) + find(".likes .entypo-heart").hover # unfocus avatar to get rid of tooltip end end @@ -68,14 +69,14 @@ When /^I prepare hiding the first post$/ do end When /^I click to delete the first post$/ do - accept_alert do + accept_confirm do step "I prepare the deletion of the first post" end expect(find(".stream")).to have_no_css(".stream-element.loaded.deleting") end When /^I click to hide the first post$/ do - accept_alert do + accept_confirm do step "I prepare hiding the first post" end end diff --git a/features/step_definitions/tag_steps.rb b/features/step_definitions/tag_steps.rb index d7d104b9c..7a6dbabac 100644 --- a/features/step_definitions/tag_steps.rb +++ b/features/step_definitions/tag_steps.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true When(/^I unfollow the "(.*?)" tag$/) do |tag| - accept_alert do + accept_confirm do within("#tags_list") do li = find("li", text: tag) li.hover diff --git a/features/step_definitions/web_steps.rb b/features/step_definitions/web_steps.rb index 3cb2a75fb..a5136747e 100644 --- a/features/step_definitions/web_steps.rb +++ b/features/step_definitions/web_steps.rb @@ -92,8 +92,7 @@ end When /^(?:|I )attach the file "([^"]*)" to (?:hidden )?"([^"]*)"(?: within "([^"]*)")?$/ do |path, field, selector| with_scope(selector) do - page.execute_script("$(\"input[name='#{field}']\").css('opacity', '1');") - attach_file(field, Rails.root.join(path).to_s) + attach_file(field, Rails.root.join(path).to_s, make_visible: true) end # wait for the image to be ready page.assert_no_selector(".loading") diff --git a/features/support/env.rb b/features/support/env.rb index cadd313bc..1d67651d3 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -12,7 +12,7 @@ require "cucumber/rails" require "capybara/rails" require "capybara/cucumber" require "capybara/session" -require "capybara/poltergeist" +require "capybara/apparition" require "cucumber/api_steps" @@ -23,11 +23,11 @@ Rails.application.routes.default_url_options[:port] = AppConfig.pod_uri.port Capybara.server = :webrick -Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, timeout: 30) +Capybara.register_driver :apparition do |app| + # Pass headless: false here if you need to see the browser + Capybara::Apparition::Driver.new(app, headless: true) end - -Capybara.javascript_driver = :poltergeist +Capybara.javascript_driver = :apparition # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In # order to ease the transition to Capybara we set the default here. If you'd diff --git a/features/support/matchers.rb b/features/support/matchers.rb index d87247046..931336234 100644 --- a/features/support/matchers.rb +++ b/features/support/matchers.rb @@ -39,6 +39,19 @@ RSpec::Matchers.define :have_value do |expected| end end +RSpec::Matchers.define :have_js_defined do |expected| + match do |actual| + await_condition { actual.evaluate_script("#{expected} !== undefined") == true } + end + + failure_message_for_should do |actual| + "expected #{actual.inspect} to have a value for #{expected.inspect} in Javascript but it did not" + end + failure_message_for_should_not do |actual| + "expected #{actual.inspect} to not have a value for #{expected.inspect} in Javascript but it had" + end +end + def await_condition &condition start_time = Time.zone.now until condition.call diff --git a/features/support/paths.rb b/features/support/paths.rb index 7962fe17d..d6c7ff157 100644 --- a/features/support/paths.rb +++ b/features/support/paths.rb @@ -70,10 +70,12 @@ module NavigationHelpers end def confirm_on_page(page_name) - if page_name == "my profile page" - expect(page).to have_path_in([person_path(@me.person), user_profile_path(@me.username)]) - else - expect(page).to have_path(path_to(page_name)) + page.driver.send(:retry_if_wrong_world) do + if page_name == "my profile page" + expect(page).to have_path_in([person_path(@me.person), user_profile_path(@me.username)]) + else + expect(page).to have_path(path_to(page_name)) + end end end end diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index 349a0c542..a7c59a6cc 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -6,10 +6,24 @@ module PublishingCukeHelpers end def append_to_publisher(txt) - status_message_text = find("#status_message_text").value - fill_in id: "status_message_text", with: "#{status_message_text} #{txt}" + update_publisher_with(txt) do |input| + fill_in id: "status_message_text", with: "#{input.value} #{txt}" + end + end + + def type_into_publisher(txt) + update_publisher_with(txt) {|input| input.send_keys txt } + end + + def update_publisher_with(txt) + input = find("#status_message_text") + + yield input + # trigger JavaScript event listeners - find("#status_message_text").native.send_key(:end) + input.native.send_key(:end) + + expect(input).to have_value(txt) # Wait for all key presses being processed end def upload_file_with_publisher(path) diff --git a/spec/javascripts/app/views/content_view_spec.js b/spec/javascripts/app/views/content_view_spec.js index a10a3cfc6..6e8ebe869 100644 --- a/spec/javascripts/app/views/content_view_spec.js +++ b/spec/javascripts/app/views/content_view_spec.js @@ -37,42 +37,39 @@ describe("app.views.Content", function(){ }); }); - // These tests don't work in PhantomJS because it doesn't support HTML5