From bef1c4a1e0c90c6f26af90bc3c38093c7254c785 Mon Sep 17 00:00:00 2001 From: fille du chaos Date: Mon, 17 Apr 2023 10:55:02 +0100 Subject: [PATCH] Migrate initializeDrawerSliders and initializeHeroBannerClose to Webpack (#19324) * feat: tests for tag page sidebar drawers on mobile * feat: tests for hero area/banner on home feed * refactor: move ui interaction initialisers to packs * remove old filter select implementation --- app/assets/javascripts/initializePage.js | 3 - .../packs/drawerSliders.js} | 17 +--- .../packs/heroBannerClose.js} | 12 +-- app/views/articles/index.html.erb | 2 +- .../stories/tagged_articles/index.html.erb | 2 +- .../homeFeedFlows/heroBanner.spec.js | 61 +++++++++++++ .../tagsFlows/tagIndexMobileSidebars.spec.js | 85 +++++++++++++++++++ cypress/support/commands.js | 51 +++++++++++ 8 files changed, 209 insertions(+), 24 deletions(-) rename app/{assets/javascripts/initializers/initializeDrawerSliders.js => javascript/packs/drawerSliders.js} (74%) rename app/{assets/javascripts/initializers/initializeHeroBannerClose.js => javascript/packs/heroBannerClose.js} (68%) create mode 100644 cypress/e2e/seededFlows/homeFeedFlows/heroBanner.spec.js create mode 100644 cypress/e2e/seededFlows/tagsFlows/tagIndexMobileSidebars.spec.js diff --git a/app/assets/javascripts/initializePage.js b/app/assets/javascripts/initializePage.js index 0ab00dadb..d3c2ceae1 100644 --- a/app/assets/javascripts/initializePage.js +++ b/app/assets/javascripts/initializePage.js @@ -5,7 +5,6 @@ initializeArticleDate, initializeArticleReactions, initializeSettings, initializeRuntimeBanner, initializeTimeFixer, initializeDashboardSort, initializeCreditsPage, - initializeDrawerSliders, initializeHeroBannerClose, initializeOnboardingTaskCard, initScrolling, nextPage:writable, fetching:writable, done:writable, initializePaymentPointers, @@ -21,8 +20,6 @@ function callInitializers() { initializeTimeFixer(); initializeDashboardSort(); initializeCreditsPage(); - initializeDrawerSliders(); - initializeHeroBannerClose(); initializeOnboardingTaskCard(); initializeDateHelpers(); } diff --git a/app/assets/javascripts/initializers/initializeDrawerSliders.js b/app/javascript/packs/drawerSliders.js similarity index 74% rename from app/assets/javascripts/initializers/initializeDrawerSliders.js rename to app/javascript/packs/drawerSliders.js index 675ee60b7..834e46324 100644 --- a/app/assets/javascripts/initializers/initializeDrawerSliders.js +++ b/app/javascript/packs/drawerSliders.js @@ -1,6 +1,6 @@ -/* global InstantClick, slideSidebar */ +/* global slideSidebar */ -function initializeDrawerSliders() { +const initializeDrawerSliders = () => { if (document.getElementById('on-page-nav-controls')) { if (document.getElementById('sidebar-bg-left')) { document.getElementById('sidebar-bg-left').onclick = (_event) => { @@ -29,15 +29,6 @@ function initializeDrawerSliders() { slideSidebar('left', 'outOfView'); }); } +}; - const feedFilterSelect = document.getElementById('feed-filter-select'); - - if (feedFilterSelect) { - feedFilterSelect.addEventListener('change', (event) => { - const url = event.target.value; - - InstantClick.preload(url); - InstantClick.display(url); - }); - } -} +initializeDrawerSliders(); diff --git a/app/assets/javascripts/initializers/initializeHeroBannerClose.js b/app/javascript/packs/heroBannerClose.js similarity index 68% rename from app/assets/javascripts/initializers/initializeHeroBannerClose.js rename to app/javascript/packs/heroBannerClose.js index 063bc9928..fef556fac 100644 --- a/app/assets/javascripts/initializers/initializeHeroBannerClose.js +++ b/app/javascript/packs/heroBannerClose.js @@ -1,8 +1,6 @@ -'use strict'; - -function initializeHeroBannerClose() { - let bannerWrapper = document.getElementById('hero-html-wrapper'); - let closeIcon = document.getElementById('js-hero-banner__x'); +const initializeHeroBannerClose = () => { + const bannerWrapper = document.getElementById('hero-html-wrapper'); + const closeIcon = document.getElementById('js-hero-banner__x'); // Currently js-hero-banner__x button icon ID needs to be written into the abstract html // In the future this could be extracted so the implementer doesn't need to worry about it. @@ -14,4 +12,6 @@ function initializeHeroBannerClose() { bannerWrapper.style.display = 'none'; }); } -} +}; + +initializeHeroBannerClose(); diff --git a/app/views/articles/index.html.erb b/app/views/articles/index.html.erb index bd23d44b6..d15aa8c3c 100644 --- a/app/views/articles/index.html.erb +++ b/app/views/articles/index.html.erb @@ -103,5 +103,5 @@ <%= render "articles/sidebar_additional" %> - <%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "feedPreviewCards", defer: true %> + <%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "feedPreviewCards", "heroBannerClose", defer: true %> <% end %> diff --git a/app/views/stories/tagged_articles/index.html.erb b/app/views/stories/tagged_articles/index.html.erb index f460bb336..91825a42a 100644 --- a/app/views/stories/tagged_articles/index.html.erb +++ b/app/views/stories/tagged_articles/index.html.erb @@ -130,5 +130,5 @@ <%= render "stories/tagged_articles/sidebar_additional" %> - <%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "feedPreviewCards", "hideBookmarkButtons", defer: true %> + <%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "feedPreviewCards", "hideBookmarkButtons", "drawerSliders", defer: true %> <% end %> diff --git a/cypress/e2e/seededFlows/homeFeedFlows/heroBanner.spec.js b/cypress/e2e/seededFlows/homeFeedFlows/heroBanner.spec.js new file mode 100644 index 000000000..ced4da5c5 --- /dev/null +++ b/cypress/e2e/seededFlows/homeFeedFlows/heroBanner.spec.js @@ -0,0 +1,61 @@ +const campaignHtml = ` +
+

This is a test campaign

+ +
+`; + +describe('Home Feed Hero Area', () => { + beforeEach(() => { + cy.testSetup(); + cy.fixture('users/adminUser.json').as('user'); + + cy.get('@user').then((user) => { + cy.loginUser(user).then(() => { + cy.createHtmlVariant({ + name: 'TestCampaignHtml', + html: campaignHtml, + approved: true, + }).then(() => { + cy.setCampaign({ + display_name: 'Test Campaign', + hero_html_variant_name: 'TestCampaignHtml', + }).then(() => { + cy.visit('/'); + }); + }); + }); + }); + }); + + afterEach(() => { + // Dismissing a banner sets a flag in local storage that we want to ensure is removed after each test + // cy.visit('/404'); + cy.clearLocalStorage(); + }); + + context('when there is an active campaign', () => { + it('displays a banner that can be dismissed', () => { + cy.get('[aria-label="Campaign banner"]') + .as('heroArea') + .contains('This is a test campaign') + .should('exist'); + + cy.get('@heroArea').within(() => { + cy.get('[aria-label="Close campaign banner"]').click(); + }); + + cy.get('@heroArea').should('not.be.visible'); + }); + + it('does not display the banner if the campaign has already been dismissed', () => { + cy.get('[aria-label="Campaign banner"]').within(() => { + cy.get('[aria-label="Close campaign banner"]').click(); + }); + + cy.reload(); + + cy.get('[aria-label="Campaign banner"]').should('not.be.visible'); + }); + }); +}); diff --git a/cypress/e2e/seededFlows/tagsFlows/tagIndexMobileSidebars.spec.js b/cypress/e2e/seededFlows/tagsFlows/tagIndexMobileSidebars.spec.js new file mode 100644 index 000000000..95a33ce08 --- /dev/null +++ b/cypress/e2e/seededFlows/tagsFlows/tagIndexMobileSidebars.spec.js @@ -0,0 +1,85 @@ +describe('Tag index page mobile sidebars', () => { + beforeEach(() => { + cy.testSetup(); + cy.fixture('users/articleEditorV1User.json').as('user'); + + cy.get('@user').then((user) => { + cy.loginAndVisit(user, '/').then(() => { + cy.createArticle({ + title: 'Ruby', + tags: ['tag1'], + content: 'This is a test article', + published: true, + }).then(() => { + cy.createArticle({ + title: 'JavaScript??', + tags: ['tag1', 'discuss'], + content: 'This is a discussion', + published: true, + }).then(() => { + cy.visit('/t/tag1'); + }); + }); + }); + }); + + cy.viewport('iphone-x'); + }); + + it('hides the left sidebar in an interactable drawer', () => { + cy.get('#sidebar-wrapper-left') + .as('leftSidebar') + .within(() => { + // There's a tag-specific "Create Post" button in the left sidebar + cy.findByRole('link', { name: 'Create Post', hidden: true }) + .as('createPostButton') + .should('not.be.visible'); + + // There is one already-seeded article besides the ones we are creating + cy.findByText('3 Posts Published', { hidden: true }) + .as('postsCount') + .should('not.be.visible'); + }); + + cy.findByRole('button', { name: 'nav-button-left' }).click(); + cy.get('@createPostButton').should('be.visible'); + cy.get('@postsCount').should('be.visible'); + + cy.get('@leftSidebar').within(() => { + cy.get('.sidebar-bg').click({ force: true }); + }); + cy.get('@createPostButton').should('not.be.visible'); + cy.get('@postsCount').should('not.be.visible'); + }); + + it('hides the right sidebar in an interactable drawer', () => { + cy.get('#sidebar-wrapper-right') + .as('rightSidebar') + .within(() => { + // The right sidebar has discussion threads & follow suggestions for the tag + cy.findByText('#discuss', { hidden: true }) + .as('discussions') + .should('not.be.visible'); + + cy.findByText('who to follow', { hidden: true }) + .as('followSuggestions') + .should('not.be.visible'); + + cy.findByRole('link', { name: /JavaScript??/, hidden: true }) + .as('discussionThread') + .should('not.be.visible'); + }); + + cy.findByRole('button', { name: 'nav-button-right' }).click(); + cy.get('@discussions').should('be.visible'); + cy.get('@followSuggestions').should('be.visible'); + cy.get('@discussionThread').should('be.visible'); + + cy.get('@rightSidebar').within(() => { + cy.get('.sidebar-bg').click({ force: true }); + }); + cy.get('@discussions').should('not.be.visible'); + cy.get('@followSuggestions').should('not.be.visible'); + cy.get('@discussionThread').should('not.be.visible'); + }); +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 13bafda29..7714d973f 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -394,3 +394,54 @@ Cypress.Commands.add('assertValueCopiedToClipboard', (value) => { }); }); }); + +Cypress.Commands.add( + 'createHtmlVariant', + ({ + name = '', + group = 'campaign', + target_tag = 'tag1', + html = '', + published = true, + approved = false, + }) => { + return cy.request('POST', '/admin/customization/html_variants', { + name, + group, + target_tag, + html, + published, + approved, + commit: 'Create HTML Variant', + }); + }, +); + +Cypress.Commands.add( + 'setCampaign', + ({ + display_name = '', + hero_html_variant_name = '', + articles_require_approval = false, + sidebar_enabled = false, + sidebar_image = 'https://example.com/image.png', + url = '', + featured_tags = '', + call_to_action = '', + articles_expiry_time = '4', + }) => { + return cy.request('POST', '/admin/settings/campaigns', { + settings_campaign: { + display_name, + hero_html_variant_name, + articles_require_approval, + sidebar_enabled, + sidebar_image, + url, + featured_tags, + call_to_action, + articles_expiry_time, + }, + }); + }, +);