From 925a7bd48ba8bc8fd51227a17652bd1835eef551 Mon Sep 17 00:00:00 2001 From: Alan Guo Xiang Tan Date: Thu, 23 Feb 2023 15:01:39 +0800 Subject: [PATCH] DEV: Port sidebar mobile view acceptance tests to system tests (#20421) The acceptance tests are flaky so I've decided to port them to system test which makes them easier to work with and reason about. --- .../discourse/app/components/site-header.js | 3 + .../tests/acceptance/sidebar-mobile-test.js | 86 ------------------- spec/rails_helper.rb | 3 + .../page_objects/components/composer.rb | 14 ++- .../components/sidebar_header_dropdown.rb | 42 ++++++++- spec/system/viewing_sidebar_mobile_spec.rb | 74 ++++++++++++++++ 6 files changed, 131 insertions(+), 91 deletions(-) delete mode 100644 app/assets/javascripts/discourse/tests/acceptance/sidebar-mobile-test.js create mode 100644 spec/system/viewing_sidebar_mobile_spec.rb diff --git a/app/assets/javascripts/discourse/app/components/site-header.js b/app/assets/javascripts/discourse/app/components/site-header.js index a549b517450..f215fa6ec5d 100644 --- a/app/assets/javascripts/discourse/app/components/site-header.js +++ b/app/assets/javascripts/discourse/app/components/site-header.js @@ -65,6 +65,7 @@ const SiteHeaderComponent = MountWidget.extend( window.requestAnimationFrame(() => { this._setAnimateOpeningProperties(panel); + if (DEBUG && isTesting()) { unregisterWaiter(waiter); } @@ -77,6 +78,7 @@ const SiteHeaderComponent = MountWidget.extend( headerCloak.classList.add("animate"); this._scheduledRemoveAnimate = discourseLater(() => { panel.classList.remove("animate"); + panel.classList.add("animated"); headerCloak.classList.remove("animate"); }, 200); panel.style.setProperty("--offset", 0); @@ -88,6 +90,7 @@ const SiteHeaderComponent = MountWidget.extend( this._animate = true; const headerCloak = document.querySelector(".header-cloak"); panel.classList.add("animate"); + panel.classList.remove("animated"); headerCloak.classList.add("animate"); if (menuOrigin === "left") { panel.style.setProperty("--offset", `-100vw`); diff --git a/app/assets/javascripts/discourse/tests/acceptance/sidebar-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/sidebar-mobile-test.js deleted file mode 100644 index 071a1bb5cc3..00000000000 --- a/app/assets/javascripts/discourse/tests/acceptance/sidebar-mobile-test.js +++ /dev/null @@ -1,86 +0,0 @@ -import I18n from "I18n"; -import { test } from "qunit"; - -import { click, visit } from "@ember/test-helpers"; - -import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers"; - -acceptance("Sidebar - Mobile - User with sidebar enabled", function (needs) { - needs.user(); - - needs.settings({ - navigation_menu: "sidebar", - }); - - needs.mobileView(); - - test("hidden by default", async function (assert) { - await visit("/"); - - assert.ok( - !exists(".sidebar-hamburger-dropdown"), - "sidebar is not displayed" - ); - }); - - test("clicking outside sidebar collapses it", async function (assert) { - await visit("/"); - - await click(".hamburger-dropdown"); - - assert.ok(exists(".sidebar-hamburger-dropdown"), "sidebar is displayed"); - - await click("#main-outlet"); - - assert.ok(!exists(".sidebar-hamburger-dropdown"), "sidebar is collapsed"); - }); - - test("clicking on a link or button in sidebar collapses it", async function (assert) { - await visit("/"); - - await click(".hamburger-dropdown"); - await click(".sidebar-section-community .sidebar-section-header-button"); - - assert.ok( - !exists(".sidebar-hamburger-dropdown"), - "sidebar is collapsed when a button in sidebar is clicked" - ); - - await click(".hamburger-dropdown"); - await click(".sidebar-section-community .sidebar-section-link-everything"); - - assert.ok( - !exists(".sidebar-hamburger-dropdown"), - "sidebar is collapsed when a link in sidebar is clicked" - ); - }); - - test("button to toggle between mobile and desktop view", async function (assert) { - await visit("/"); - await click(".hamburger-dropdown"); - - assert.ok( - exists( - `.sidebar-footer-actions-toggle-mobile-view[title="${I18n.t( - "desktop_view" - )}"]` - ), - "displays the right title for the button" - ); - - assert.ok( - exists(".sidebar-footer-actions-toggle-mobile-view .d-icon-desktop"), - "displays the desktop icon for the button" - ); - }); - - test("keyboard shortcuts button is hidden", async function (assert) { - await visit("/"); - await click(".hamburger-dropdown"); - - assert.notOk( - exists(".sidebar-footer-actions-keyboard-shortcuts"), - "keyboard shortcuts button is not shown on mobile" - ); - }); -}); diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index e526c685b9f..ecdd9227047 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -247,6 +247,9 @@ RSpec.configure do |config| Capybara.threadsafe = true Capybara.disable_animation = false + # Click offsets is calculated from top left of element + Capybara.w3c_click_offset = false + Capybara.configure do |capybara_config| capybara_config.server_host = "localhost" capybara_config.server_port = 31_337 + ENV["TEST_ENV_NUMBER"].to_i diff --git a/spec/system/page_objects/components/composer.rb b/spec/system/page_objects/components/composer.rb index 1ac5ebfb6af..01d0012e079 100644 --- a/spec/system/page_objects/components/composer.rb +++ b/spec/system/page_objects/components/composer.rb @@ -3,13 +3,19 @@ module PageObjects module Components class Composer < PageObjects::Components::Base + COMPOSER_ID = "#reply-control" + + def opened? + page.has_css?("#{COMPOSER_ID}.open") + end + def open_composer_actions find(".composer-action-title .btn").click self end def fill_title(title) - find("#reply-control #reply-title").fill_in(with: title) + find("#{COMPOSER_ID} #reply-title").fill_in(with: title) self end @@ -37,7 +43,7 @@ module PageObjects end def create - find("#reply-control .btn-primary").click + find("#{COMPOSER_ID} .btn-primary").click end def action(action_title) @@ -45,11 +51,11 @@ module PageObjects end def button_label - find("#reply-control .btn-primary .d-button-label") + find("#{COMPOSER_ID} .btn-primary .d-button-label") end def composer_input - find("#reply-control .d-editor .d-editor-input") + find("#{COMPOSER_ID} .d-editor .d-editor-input") end end end diff --git a/spec/system/page_objects/components/sidebar_header_dropdown.rb b/spec/system/page_objects/components/sidebar_header_dropdown.rb index 8087952e9da..1d74577f927 100644 --- a/spec/system/page_objects/components/sidebar_header_dropdown.rb +++ b/spec/system/page_objects/components/sidebar_header_dropdown.rb @@ -5,10 +5,50 @@ module PageObjects class SidebarHeaderDropdown < PageObjects::Components::Base def click page.find(".hamburger-dropdown").click + + # `.animated` is important here because we want to wait until dropdown has finished its animation completely + page.has_css?(".menu-panel.animated") + self end + SIDEBAR_HAMBURGER_DROPDOWN = ".sidebar-hamburger-dropdown" + def visible? - page.has_css?(".sidebar-hamburger-dropdown") + page.has_css?(SIDEBAR_HAMBURGER_DROPDOWN) + end + + def hidden? + page.has_no_css?(SIDEBAR_HAMBURGER_DROPDOWN) + end + + def has_no_keyboard_shortcuts_button? + page.has_no_css?(".sidebar-footer-actions-keyboard-shortcuts") + end + + def click_community_header_button + page.click_button( + I18n.t("js.sidebar.sections.community.header_action_title"), + class: "sidebar-section-header-button", + ) + end + + def click_everything_link + page.click_link( + I18n.t("js.sidebar.sections.community.links.everything.content"), + class: "sidebar-section-link-everything", + ) + end + + def click_toggle_to_desktop_view_button + page.click_button( + I18n.t("js.desktop_view"), + class: "sidebar-footer-actions-toggle-mobile-view", + ) + end + + def click_outside + dropdown = page.find(SIDEBAR_HAMBURGER_DROPDOWN) + dropdown.click(x: dropdown.rect.width + 1, y: 1) end end end diff --git a/spec/system/viewing_sidebar_mobile_spec.rb b/spec/system/viewing_sidebar_mobile_spec.rb new file mode 100644 index 00000000000..aaca7670e46 --- /dev/null +++ b/spec/system/viewing_sidebar_mobile_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +describe "Viewing sidebar mobile", type: :system, js: true, mobile: true do + fab!(:user) { Fabricate(:user) } + let(:sidebar_dropdown) { PageObjects::Components::SidebarHeaderDropdown.new } + let(:composer) { PageObjects::Components::Composer.new } + + before { sign_in(user) } + + it "does not display the sidebar by default" do + visit("/latest") + + expect(sidebar_dropdown).to be_hidden + end + + it "does not display the keyboard shortcuts button" do + visit("/latest") + + sidebar_dropdown.click + + expect(sidebar_dropdown).to be_visible + expect(sidebar_dropdown).to have_no_keyboard_shortcuts_button + end + + it "collapses the sidebar when clicking outside of it" do + visit("/latest") + + sidebar_dropdown.click + + expect(sidebar_dropdown).to be_visible + + sidebar_dropdown.click_outside + + expect(sidebar_dropdown).to be_hidden + end + + it "collpases the sidebar when clicking on a link in the sidebar" do + visit("/latest") + + sidebar_dropdown.click + + expect(sidebar_dropdown).to be_visible + + sidebar_dropdown.click_everything_link + + expect(sidebar_dropdown).to be_hidden + end + + it "collapses the sidebar when clicking on a button in the sidebar" do + visit("/latest") + + sidebar_dropdown.click + + expect(sidebar_dropdown).to be_visible + + sidebar_dropdown.click_community_header_button + + expect(composer).to be_opened + expect(sidebar_dropdown).to be_hidden + end + + it "toggles to desktop view after clicking on the toggle to desktop view button" do + visit ("/latest") + + expect(page).to have_css(".mobile-view") + + sidebar_dropdown.click + sidebar_dropdown.click_toggle_to_desktop_view_button + + visit ("/latest") + + expect(page).to have_css(".desktop-view") + end +end