From 5266dd1afb0b7df1819e5c4dee4a1af8b12ad0de Mon Sep 17 00:00:00 2001 From: Ridhwana Date: Fri, 25 Aug 2023 14:49:39 +0200 Subject: [PATCH] Showing and hiding tags in the Following and Hidden Tags Pages (#19954) * feat: remove updated weights * feat: click on following on the following tags page * feat: add and listen for the following button click * fix: dropdowns * feat: handle hide button click * feat: update the nav link for following tags * feat: handel the 'unhide button' on the hidden tags page * feat: add the styling for the buttons * feat: add localization * feat: remove the brand from the card * feat: add some styling to the page * feat: init scrolling * chore: update the name of the file * feat: abstract out the comment fetch code * fix: close the attribute * feta: make some adjustments to where the tag adn the follow show up * rename class from plural to singular * feat: updae the comment * feat: add a mutation observer to initialize the dropdown * test: follow_craete * chore: remove irrelevant test * feat: update the cypress seeds * feat: update the cypress seeds * spec: write soem initial tests for the following tags page * spec: update the unfollow cypress spec * spec: update the hide cypress spec * spec: update the posts published spec * note to add test for pagination * spec: hidden tags page * feat: remove aria pressed attributes * fix: ordering by explicit points gets the page params confused and returns the incorrect and not all results on pagination * fix: use explicit points * feat: remove the message at the top of the following and hidden tags page * chore: remove comment and rather add it to the PR itself * refactor: do all the actions on success * feat: refactor the dashboard tag file * refactor: only show the tagId and followId dataset attributes on the dashboard__tag__container * feat: disconnect the observer * chore: add some documentation * feat: add fr localization * chore: empty line * fix: update the dashboardTags page to first declare the observer" " " * fix: update the rails test * Empty commit * fix: because I added more tags, the dropdown was longre and covering the body of the editor hence it could not find the text, so I've escaped after selecting my tags --- .../javascripts/initializers/initScrolling.js | 60 +++++- app/assets/stylesheets/dashboard.scss | 11 ++ app/controllers/followings_controller.rb | 2 +- app/controllers/follows_controller.rb | 1 + app/javascript/packs/dashboardTags.js | 178 ++++++++++++++++++ .../dashboardTagsDisableUnchangedButtons.js | 36 ---- app/views/dashboards/_actions.html.erb | 4 +- app/views/dashboards/_tags.html.erb | 59 ++++-- app/views/dashboards/following_tags.html.erb | 6 +- app/views/dashboards/hidden_tags.html.erb | 5 +- app/views/followings/tags.json.jbuilder | 9 +- config/locales/views/dashboard/en.yml | 11 +- config/locales/views/dashboard/fr.yml | 11 +- .../dashboardFlows/followingTags.spec.js | 101 ++++++++++ .../dashboardFlows/hiddenTags.spec.js | 44 +++++ .../postBrowserPersistence.spec.js | 3 +- spec/requests/followings_spec.rb | 2 +- spec/requests/follows_create_spec.rb | 28 ++- spec/support/seeds/seeds_e2e.rb | 15 +- ...ser_scrolls_down_dashboard_follows_spec.rb | 13 -- 20 files changed, 486 insertions(+), 113 deletions(-) create mode 100644 app/javascript/packs/dashboardTags.js delete mode 100644 app/javascript/packs/dashboardTagsDisableUnchangedButtons.js create mode 100644 cypress/e2e/seededFlows/dashboardFlows/followingTags.spec.js create mode 100644 cypress/e2e/seededFlows/dashboardFlows/hiddenTags.spec.js diff --git a/app/assets/javascripts/initializers/initScrolling.js b/app/assets/javascripts/initializers/initScrolling.js index 7a43ab6e9..530be215d 100644 --- a/app/assets/javascripts/initializers/initScrolling.js +++ b/app/assets/javascripts/initializers/initScrolling.js @@ -140,20 +140,62 @@ function buildFollowsHTML(follows) { * @returns an HTML block for a tag follow. */ function buildTagsHTML(tag) { - var antifollow = ''; - if (tag.points < 0) { - antifollow = - 'Anti-follow'; + let followingButtonContainer = ''; + let unhideButtonContainer = ''; + + if (tag.explicit_points < 0) { + unhideButtonContainer = `
+ +
`; } - return `
-

+ if (tag.explicit_points >= 0) { + followingButtonContainer = `
+
+ +
+ +
`; + } + + let short_summary = ''; + if (tag.short_summary) { + short_summary = `

${tag.short_summary}

`; + } + + // TODO: remove the data-follow-id and the data-tag-id in the child components + return ` +
+
+

#${tag.name} -

- - +

+
${tag.taggings_count.toLocaleString()} posts
+
+ ${short_summary} + + ${unhideButtonContainer} + ${followingButtonContainer} `; } diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss index a807b5ab3..13b777e12 100644 --- a/app/assets/stylesheets/dashboard.scss +++ b/app/assets/stylesheets/dashboard.scss @@ -400,3 +400,14 @@ $column-flex: 1; font-weight: bold; } } + +// dashboard pages +.dashboard__tag__container { + height: 195px; + justify-content: space-between; + + .crayons-tag { + padding-top: 0; + padding-bottom: 0; + } +} diff --git a/app/controllers/followings_controller.rb b/app/controllers/followings_controller.rb index a855be45c..5ea63074b 100644 --- a/app/controllers/followings_controller.rb +++ b/app/controllers/followings_controller.rb @@ -19,7 +19,7 @@ class FollowingsController < ApplicationController else relation.where(explicit_points: (0...)) end - relation = relation.order(explicit_points: :desc) + relation = relation.order(created_at: :desc) @followed_tags = load_follows_and_paginate(relation) end diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index 0414783d5..075e4b00f 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -103,6 +103,7 @@ class FollowsController < ApplicationController def follow(followable, need_notification: false) user_follow = current_user.follow(followable) + user_follow.update!(explicit_points: params[:explicit_points]) if params[:explicit_points].present? Notification.send_new_follower_notification(user_follow) if need_notification I18n.t("follows_controller.followed") rescue ActiveRecord::RecordInvalid diff --git a/app/javascript/packs/dashboardTags.js b/app/javascript/packs/dashboardTags.js new file mode 100644 index 000000000..907bdd799 --- /dev/null +++ b/app/javascript/packs/dashboardTags.js @@ -0,0 +1,178 @@ +import { initializeDropdown } from '@utilities/dropdownUtils'; + +listenForButtonClicks(); + +/** + * Adds an event listener to the inner page content, to handle any and all follow button clicks with a single handler + */ +function listenForButtonClicks() { + document + .getElementById('following-wrapper') + .addEventListener('click', handleClick); +} + +/** + * Checks a click event's target to see which button was clicked and calls the relevant handlers + * + * @param {HTMLElement} target The target of the click event + */ +function handleClick({ target }) { + const tagContainer = target.closest('.dashboard__tag__container'); + + if (target.classList.contains('follow-button')) { + handleFollowingButtonClick(tagContainer); + } + + if (target.classList.contains('hide-button')) { + handleHideButtonClick(tagContainer); + } + + if (target.classList.contains('unhide-button')) { + handleUnhideButtonClick(tagContainer); + } +} + +function fetchFollows(body) { + const tokenMeta = document.querySelector("meta[name='csrf-token']"); + const csrfToken = tokenMeta && tokenMeta.getAttribute('content'); + + return window.fetch('/follows', { + method: 'POST', + headers: { + 'X-CSRF-Token': csrfToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + credentials: 'same-origin', + }); +} + +function handleFollowingButtonClick(tagContainer) { + const { tagId, followId } = tagContainer.dataset; + + const data = { + followable_type: 'Tag', + followable_id: tagId, + verb: 'unfollow', + }; + + fetchFollows(data) + .then(() => { + removeElementFromPage(followId); + updateNavigationItemCount(); + }) + .catch((error) => console.error(error)); +} + +function handleHideButtonClick(tagContainer) { + const { tagId, followId } = tagContainer.dataset; + + const data = { + followable_type: 'Tag', + followable_id: tagId, + verb: 'follow', + explicit_points: -1, + }; + + fetchFollows(data) + .then(() => { + removeElementFromPage(followId); + + // update the current navigation item count + updateNavigationItemCount(); + + // update the hidden tags navigation item + const hiddenTagsNavigationItem = document.querySelector( + '.js-hidden-tags-link .c-indicator', + ); + updateNavigationItemCount(hiddenTagsNavigationItem, 1); + }) + .catch((error) => console.error(error)); +} + +function handleUnhideButtonClick(tagContainer) { + const { tagId, followId } = tagContainer.dataset; + + const data = { + followable_type: 'Tag', + followable_id: tagId, + verb: 'follow', + explicit_points: 1, + }; + + fetchFollows(data) + .then(() => { + removeElementFromPage(followId); + // update the current navigation item count + updateNavigationItemCount(); + + // update the following tags navigation item + const followingTagsNavigationItem = document.querySelector( + '.js-following-tags-link .c-indicator', + ); + updateNavigationItemCount(followingTagsNavigationItem, 1); + }) + .catch((error) => console.error(error)); +} + +function removeElementFromPage(followId) { + document.getElementById(`follows-${followId}`).remove(); +} + +function updateNavigationItemCount( + navItem = document.querySelector('.crayons-link--current .c-indicator'), + adjustment = -1, +) { + const currentFollowingTagsCount = parseInt(navItem.innerHTML, 10); + navItem.textContent = currentFollowingTagsCount + adjustment; +} + +/** + * Initializes the dropdown within each card + */ +const allButtons = document.querySelectorAll('.follow-button'); +allButtons.forEach((button) => { + const { tagId } = button.closest('.dashboard__tag__container').dataset; + initializeDropdown({ + triggerElementId: `options-dropdown-trigger-${tagId}`, + dropdownContentId: `options-dropdown-${tagId}`, + }); +}); + +/** + * When there is a change to the DOMTree, we find the added node and initializes the dropdown + */ +const observer = new MutationObserver((mutationsList) => { + mutationsList.forEach((mutation) => { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach((node) => { + // to remove options like #text '\n ' + if (node.hasChildNodes()) { + const { tagId } = node.closest('.dashboard__tag__container').dataset; + initializeDropdown({ + triggerElementId: `options-dropdown-trigger-${tagId}`, + dropdownContentId: `options-dropdown-${tagId}`, + }); + } + }); + } + }); +}); + +/** + * Observes when there additions to the DOM(like when we paginate) within the wrapper + */ +document.querySelectorAll('#following-wrapper').forEach((tagContainer) => { + observer.observe(tagContainer, { + childList: true, + subtree: true, + }); +}); + +InstantClick.on('change', () => { + observer.disconnect(); +}); + +window.addEventListener('beforeunload', () => { + observer.disconnect(); +}); diff --git a/app/javascript/packs/dashboardTagsDisableUnchangedButtons.js b/app/javascript/packs/dashboardTagsDisableUnchangedButtons.js deleted file mode 100644 index 45ff28bc0..000000000 --- a/app/javascript/packs/dashboardTagsDisableUnchangedButtons.js +++ /dev/null @@ -1,36 +0,0 @@ -document - .getElementById('follows_update_form') - .addEventListener('submit', checkChanged); - -document.addEventListener('change', (event) => { - if (event.target && event.target.name == 'follows[][explicit_points]') { - addChanged(event.target); - } -}); - -function addChanged(element) { - element.setAttribute('changed', true); -} - -function checkChanged(event) { - if (document.querySelector('input[changed]')) { - disableAllUnchanged(); - } else { - event.preventDefault(); - } -} - -function disableAllUnchanged() { - document.querySelectorAll('div[id^="follows"]').forEach(disableUnchanged); -} - -function disableUnchanged(item) { - const inputs = item.getElementsByTagName('input'); - const id = inputs[0]; - const point = inputs[1]; - - if (!point.hasAttribute('changed')) { - point.setAttribute('disabled', true); - id.setAttribute('disabled', true); - } -} diff --git a/app/views/dashboards/_actions.html.erb b/app/views/dashboards/_actions.html.erb index 4caf8734e..f25d3f2a2 100644 --- a/app/views/dashboards/_actions.html.erb +++ b/app/views/dashboards/_actions.html.erb @@ -30,7 +30,7 @@ <% end %>
  • - " + " href="<%= dashboard_following_tags_path %>" <%= params[:action] == "following_tags" ? ' aria-current="page"'.html_safe : "" %>> <%= t("views.dashboard.actions.following_tags") %> @@ -83,7 +83,7 @@ <%- end %>
  • - " + " href="<%= dashboard_hidden_tags_path %>" <%= params[:action] == "hidden_tags" ? ' aria-current="page"'.html_safe : "" %>> <%= t("views.dashboard.actions.hidden_tags") %> diff --git a/app/views/dashboards/_tags.html.erb b/app/views/dashboards/_tags.html.erb index 56d4aa4ae..4ee4e30ad 100644 --- a/app/views/dashboards/_tags.html.erb +++ b/app/views/dashboards/_tags.html.erb @@ -1,28 +1,51 @@ -<%= javascript_packs_with_chunks_tag "dashboardTagsDisableUnchangedButtons", defer: true %> +<%= javascript_packs_with_chunks_tag "dashboardTags", defer: true %>
    <% tags.each do |follow| %> <% tag = follow.followable %> <% if tag %> -
    -

    - <%= render_tag_link(tag.name) %> -

    - -

    - <%= strip_tags(tag.short_summary) %> -

    - - <%= fields(follow) do |f| %> - <%= f.hidden_field(:id, name: "follows[][id]", form: "follows_update_form", id: "follow_id_#{follow.followable}") %> - <%= f.number_field(:explicit_points, step: :any, required: true, class: "crayons-textfield flex-1 fs-s", name: "follows[][explicit_points]", form: "follows_update_form", "aria-label": t("views.dashboard.tags.number.aria_label", name: follow.followable), - id: "explicit_points_#{follow.followable}") %> +
    +
    +

    + <%= render_tag_link(tag.name) %> +

    +
    <%= t("views.tags.published", count: number_with_delimiter(tag.taggings_count, delimiter: ",")) %>
    +
    + <% if tag.short_summary.present? %> +

    <%= sanitize tag.short_summary %>

    <% end %> + +
    + <%# we could use positive explicit points %> + <% if page === "following" %> +
    +
    + +
    + +
    + <% end %> + + <% if page === "hidden" %> +
    + +
    + <% end %> +
    <% end %> <% end %>
    - -<%= form_with url: bulk_update_follows_path, method: :patch, local: true, class: "sticky bg-base-inverted mt-3 pt-3 pl-3 pb-1 z-elevate", html: { style: "bottom: 0;margin-left:-1px" }, id: "follows_update_form" do |f| %> - -<% end %> diff --git a/app/views/dashboards/following_tags.html.erb b/app/views/dashboards/following_tags.html.erb index 594f3c53b..c4418c416 100644 --- a/app/views/dashboards/following_tags.html.erb +++ b/app/views/dashboards/following_tags.html.erb @@ -13,11 +13,7 @@
    <% if @followed_tags.any? %> -
    - <%= t("views.dashboard.following_tags.adjust") %> - <%= t("views.dashboard.following_tags.default") %> -
    - <%= render "tags", tags: @followed_tags %> + <%= render "tags", tags: @followed_tags, page: "following" %> <% else %>
    <%= t("views.dashboard.following_tags.empty_html", link: tags_path) %>
    <% end %> diff --git a/app/views/dashboards/hidden_tags.html.erb b/app/views/dashboards/hidden_tags.html.erb index 1e81fa240..53e0849c5 100644 --- a/app/views/dashboards/hidden_tags.html.erb +++ b/app/views/dashboards/hidden_tags.html.erb @@ -13,10 +13,7 @@
    <% if @hidden_tags.any? %> -
    - <%= t("views.dashboard.hidden_tags.adjust") %> -
    - <%= render "tags", tags: @hidden_tags %> + <%= render "tags", tags: @hidden_tags, page: "hidden" %> <% else %>
    <%= t("views.dashboard.hidden_tags.empty_html", link: tags_path) %>
    <% end %> diff --git a/app/views/followings/tags.json.jbuilder b/app/views/followings/tags.json.jbuilder index 272ee1aa7..c98b32671 100644 --- a/app/views/followings/tags.json.jbuilder +++ b/app/views/followings/tags.json.jbuilder @@ -5,7 +5,10 @@ json.array! @followed_tags do |follow| json.type_of "tag_following" json.extract!(follow, :id, :points, :explicit_points) - json.name followable.name - json.token form_authenticity_token - json.color Color::CompareHex.new(colors).brightness(0.8) + json.taggings_count followable.taggings_count + json.name followable.name + json.token form_authenticity_token + json.short_summary sanitize(followable.short_summary) + json.color Color::CompareHex.new(colors).brightness(0.8) + json.tag_id followable.id end diff --git a/config/locales/views/dashboard/en.yml b/config/locales/views/dashboard/en.yml index 63d994f52..219430de9 100644 --- a/config/locales/views/dashboard/en.yml +++ b/config/locales/views/dashboard/en.yml @@ -108,20 +108,19 @@ en: empty: You don't follow any podcasts yet... following_tags: heading: Dashboard » Following tags - adjust: Adjust the tag weight to modify your home feed. Higher values mean more appearances for that tag. - default: Default 1.0 empty_html: "Follow tags to personalize your feed. You can explore popular tags
    here." following_users: heading: Dashboard » Following users empty: You don't follow any users... hidden_tags: heading: Dashboard » Hidden tags - adjust: Adjust the tag weight to modify your home feed. Lower values mean fewer appearances for that tag. empty_html: "You don't have any hidden tags..." tags: - number: - aria_label: "%{name} tag weight" - update: Update Weights + following_button: Following + options: + icon: Options + hide: Hide tag + unhide_button: Unhide listings: meta: title: Listings Dashboard diff --git a/config/locales/views/dashboard/fr.yml b/config/locales/views/dashboard/fr.yml index cda97718e..9781c500f 100644 --- a/config/locales/views/dashboard/fr.yml +++ b/config/locales/views/dashboard/fr.yml @@ -108,20 +108,19 @@ fr: empty: You don't follow any podcasts yet... following_tags: heading: Dashboard » Following tags - adjust: Adjust the tag weight to modify your home feed. Higher values mean more appearances for that tag. - default: Default 1.0 empty_html: "Follow tags to personalize your feed. You can explore popular tags here." following_users: heading: Tableau de bord » Utilisateurs suivis empty: Vous ne suivez aucun utilisateur... hidden_tags: heading: Dashboard » Hidden tags - adjust: Adjust the tag weight to modify your home feed. Lower values mean fewer appearances for that tag. empty_html: "You don't have any hidden tags..." tags: - number: - aria_label: "%{name} tag weight" - update: Update Weights + following_button: Following + options: + icon: Options + hide: Hide tag + unhide_button: Unhide listings: meta: title: Listings Dashboard diff --git a/cypress/e2e/seededFlows/dashboardFlows/followingTags.spec.js b/cypress/e2e/seededFlows/dashboardFlows/followingTags.spec.js new file mode 100644 index 000000000..6045e8351 --- /dev/null +++ b/cypress/e2e/seededFlows/dashboardFlows/followingTags.spec.js @@ -0,0 +1,101 @@ +function openOptionsMenu(callback) { + cy.findAllByRole('button', { name: 'Options' }) + .first() + .should('have.attr', 'aria-haspopup', 'true') + .should('have.attr', 'aria-expanded', 'false') + .click() + .then(([button]) => { + expect(button.getAttribute('aria-expanded')).to.equal('true'); + const dropdownId = button.getAttribute('aria-controls'); + + cy.get(`#${dropdownId}`).within(callback); + }); +} + +describe('Dashboard: Following Tags', () => { + beforeEach(() => { + cy.testSetup(); + cy.fixture('users/adminUser.json').as('user'); + + cy.get('@user').then((user) => { + cy.loginAndVisit(user, '/dashboard/following_tags').then(() => { + cy.findByRole('heading', { name: 'Dashboard » Following tags' }); + }); + }); + }); + + it('shows the correct number of tags on the page', () => { + cy.get('.dashboard__tag__container').should('have.length', 5); + }); + + it('shows the appropriate buttons on the card', () => { + cy.findByRole('button', { name: 'Following tag: tag0' }); + openOptionsMenu(() => { + cy.findByRole('button', { name: 'Hide tag: tag0' }).click(); + }); + }); + + it('unfollows a tag', () => { + cy.get('.dashboard__tag__container').should('have.length', 5); + + cy.intercept('/follows').as('followsRequest'); + cy.findByRole('button', { name: 'Following tag: tag0' }).as( + 'followingButton', + ); + + cy.get('@followingButton').click(); + cy.wait('@followsRequest'); + + // it removes the item from the 'Following tags' page + cy.get('.dashboard__tag__container').should('have.length', 4); + cy.findByRole('button', { name: 'Following tag: tag0' }).should( + 'not.exist', + ); + + // it decreases the count from the 'Following tags' nav item + cy.get('.js-following-tags-link .c-indicator').as('followingTagsCount'); + cy.get('@followingTagsCount').should('contain', '4'); + }); + + it('hides a tag', () => { + cy.get('.dashboard__tag__container').should('have.length', 5); + + cy.intercept('/follows').as('followsRequest'); + openOptionsMenu(() => { + cy.findByRole('button', { name: 'Hide tag: tag0' }).as('hideButton'); + }); + + cy.get('@hideButton').click(); + cy.wait('@followsRequest'); + + // it removes the item from the 'Following tags' page + cy.get('.dashboard__tag__container').should('have.length', 4); + cy.findByRole('button', { name: 'Following tag: tag0' }).should( + 'not.exist', + ); + + // it decreases the count from the 'Following tags' nav item + cy.get('.js-following-tags-link .c-indicator').as('followingTagsCount'); + cy.get('@followingTagsCount').should('contain', '4'); + + // it increases the count from the 'Hidden tags' nav item + cy.get('.js-hidden-tags-link .c-indicator').as('hiddenTagsCount'); + cy.get('@hiddenTagsCount').should('contain', '6'); + }); + + it('shows the number of posts published for a tag', () => { + cy.get('.dashboard__tag__container') + .first() + .within(() => { + cy.findByText('0 posts'); + }); + + cy.get('.dashboard__tag__container') + .eq(1) + .within(() => { + cy.findByText('1 posts'); + }); + }); + + // TODO: add a test for the pagination +}); diff --git a/cypress/e2e/seededFlows/dashboardFlows/hiddenTags.spec.js b/cypress/e2e/seededFlows/dashboardFlows/hiddenTags.spec.js new file mode 100644 index 000000000..c3af373e3 --- /dev/null +++ b/cypress/e2e/seededFlows/dashboardFlows/hiddenTags.spec.js @@ -0,0 +1,44 @@ +describe('Dashboard: Hidden Tags', () => { + beforeEach(() => { + cy.testSetup(); + cy.fixture('users/adminUser.json').as('user'); + + cy.get('@user').then((user) => { + cy.loginAndVisit(user, '/dashboard/hidden_tags').then(() => { + cy.findByRole('heading', { name: 'Dashboard » Hidden tags' }); + }); + }); + }); + + it('shows the correct number of tags on the page', () => { + cy.get('.dashboard__tag__container').should('have.length', 5); + }); + + it('shows the appropriate buttons on the card', () => { + cy.findByRole('button', { name: 'Unhide tag: tag5' }); + }); + + it('unhides a tag', () => { + cy.get('.dashboard__tag__container').should('have.length', 5); + + cy.intercept('/follows').as('followsRequest'); + cy.findByRole('button', { name: 'Unhide tag: tag5' }).as('unhideButton'); + + cy.get('@unhideButton').click(); + cy.wait('@followsRequest'); + + // it removes the item from the 'Hidden tags' page + cy.get('.dashboard__tag__container').should('have.length', 4); + cy.findByRole('button', { name: 'Unhide tag: tag5' }).should('not.exist'); + + // it decreases the count from the 'Hidden tags' nav item + cy.get('.js-hidden-tags-link .c-indicator').as('hiddenTagsCount'); + cy.get('@hiddenTagsCount').should('contain', '4'); + + // it decreases the count from the 'Following tags' nav item + cy.get('.js-following-tags-link .c-indicator').as('followingTagsCount'); + cy.get('@followingTagsCount').should('contain', '6'); + }); + + // TODO: add a test for the pagination +}); diff --git a/cypress/e2e/seededFlows/publishingFlows/postBrowserPersistence.spec.js b/cypress/e2e/seededFlows/publishingFlows/postBrowserPersistence.spec.js index 6e4eede9d..a81c8eca8 100644 --- a/cypress/e2e/seededFlows/publishingFlows/postBrowserPersistence.spec.js +++ b/cypress/e2e/seededFlows/publishingFlows/postBrowserPersistence.spec.js @@ -220,7 +220,8 @@ describe('Post Editor', () => { cy.get('@articleForm') .findByRole('textbox', { name: 'Add up to 4 tags' }) .as('postTags') - .type('tag1, tag2, tag3,'); + .type('tag1, tag2, tag3,') + .type('{esc}'); getPostContent() .should('have.value', `This is a Test Post's contents.`) // checking for original value first diff --git a/spec/requests/followings_spec.rb b/spec/requests/followings_spec.rb index 8c11e911f..bf6780da2 100644 --- a/spec/requests/followings_spec.rb +++ b/spec/requests/followings_spec.rb @@ -79,7 +79,7 @@ RSpec.describe "FollowingsController" do expect(response).to have_http_status(:ok) expect(response.parsed_body.count).to eq(2) - expect(response.parsed_body.pluck("name")).to eq(%w[tagone tagthree]) + expect(response.parsed_body.pluck("name")).to eq(%w[tagthree tagone]) end it "returns the user's hidden tag list" do diff --git a/spec/requests/follows_create_spec.rb b/spec/requests/follows_create_spec.rb index 0891dd0a4..79c7f2306 100644 --- a/spec/requests/follows_create_spec.rb +++ b/spec/requests/follows_create_spec.rb @@ -3,6 +3,7 @@ require "rails_helper" RSpec.describe "Follows #create" do let(:current_user) { create(:user) } let(:user) { create(:user) } + let(:tag) { create(:tag) } let(:headers) { { "Content-Type": "application/json", Accept: "application/json" } } let(:follow_payload) do { @@ -11,6 +12,14 @@ RSpec.describe "Follows #create" do verb: "follow" }.to_json end + let(:follow_tag_payload) do + { + followable_type: "Tag", + followable_id: tag.id, + verb: "follow", + explicit_points: -1 + }.to_json + end before do sign_in current_user @@ -39,11 +48,22 @@ RSpec.describe "Follows #create" do end end - it "follows" do - post "/follows", headers: headers, params: follow_payload + context "when follows" do + it "returns followed" do + post "/follows", headers: headers, params: follow_payload - expect(response).to have_http_status(:ok) - expect(response.parsed_body["outcome"]).to eq("followed") + expect(response).to have_http_status(:ok) + expect(response.parsed_body["outcome"]).to eq("followed") + end + + it "updates explicit points" do + post "/follows", headers: headers, params: follow_tag_payload + + expect(response).to have_http_status(:ok) + expect(response.parsed_body["outcome"]).to eq("followed") + follow = Follow.find_by(followable_id: tag.id, followable_type: "ActsAsTaggableOn::Tag") + expect(follow.explicit_points).to eq(-1.0) + end end it "unfollows" do diff --git a/spec/support/seeds/seeds_e2e.rb b/spec/support/seeds/seeds_e2e.rb index 389e2b82b..8c90f8e20 100644 --- a/spec/support/seeds/seeds_e2e.rb +++ b/spec/support/seeds/seeds_e2e.rb @@ -941,17 +941,24 @@ end ############################################################################## seeder.create_if_none(Tag) do - tags = %w[tag1 tag2] - - tags.each do |tagname| + 10.times do |i| tag = Tag.create!( - name: tagname, + name: "tag#{i}", + short_summary: Faker::Hipster.paragraph(sentence_count: 2), bg_color_hex: "#672c99", text_color_hex: Faker::Color.hex_color, supported: true, ) admin_user.add_role(:tag_moderator, tag) + + Follow.create( + followable_type: "ActsAsTaggableOn::Tag", + followable_id: tag.id, + follower_type: "User", + follower_id: admin_user.id, + explicit_points: i < 5 ? 1 : -1, + ) end end diff --git a/spec/system/dashboards/user_scrolls_down_dashboard_follows_spec.rb b/spec/system/dashboards/user_scrolls_down_dashboard_follows_spec.rb index eba17c82f..48b287be9 100644 --- a/spec/system/dashboards/user_scrolls_down_dashboard_follows_spec.rb +++ b/spec/system/dashboards/user_scrolls_down_dashboard_follows_spec.rb @@ -41,19 +41,6 @@ RSpec.describe "Infinite scroll on dashboard", js: true do it "scrolls through all tags" do page.assert_selector('div[id^="follows"]', count: total_records) end - - it "updates two tag point values" do - last_divs = page.all('div[id^="follows"]').last(2) - - within(last_divs[0]) { fill_in with: 5.0, class: "crayons-textfield" } - within(last_divs[1]) { fill_in with: 10.0, class: "crayons-textfield" } - - click_button "commit" - - first_divs = page.all('div[id^="follows"]').first(2) - within(first_divs[0]) { expect(page).to have_field(with: 10.0, class: "crayons-textfield") } - within(first_divs[1]) { expect(page).to have_field(with: 5.0, class: "crayons-textfield") } - end end context "when /dashboard/following_users is visited" do