From 5933f294e94948c5bb44c5ba549432f4207a24da Mon Sep 17 00:00:00 2001 From: PJ Date: Tue, 9 May 2023 17:04:10 +0100 Subject: [PATCH] Follow all suggested users by default when onboarding (#19435) --- .../onboarding/components/FollowUsers.jsx | 5 +- .../components/__tests__/FollowUsers.test.jsx | 93 ++++++++++--------- testSetup.js | 29 +++++- 3 files changed, 83 insertions(+), 44 deletions(-) diff --git a/app/javascript/onboarding/components/FollowUsers.jsx b/app/javascript/onboarding/components/FollowUsers.jsx index b74cf4e54..ee0294aad 100644 --- a/app/javascript/onboarding/components/FollowUsers.jsx +++ b/app/javascript/onboarding/components/FollowUsers.jsx @@ -27,7 +27,10 @@ export class FollowUsers extends Component { }) .then((response) => response.json()) .then((data) => { - this.setState({ users: data }); + this.setState({ + selectedUsers: data, + users: data, + }); }); const csrfToken = getContentOfToken('csrf-token'); diff --git a/app/javascript/onboarding/components/__tests__/FollowUsers.test.jsx b/app/javascript/onboarding/components/__tests__/FollowUsers.test.jsx index 213365647..a019fbc98 100644 --- a/app/javascript/onboarding/components/__tests__/FollowUsers.test.jsx +++ b/app/javascript/onboarding/components/__tests__/FollowUsers.test.jsx @@ -1,5 +1,5 @@ import { h } from 'preact'; -import { render } from '@testing-library/preact'; +import { render, fireEvent } from '@testing-library/preact'; import fetch from 'jest-fetch-mock'; import '@testing-library/jest-dom'; @@ -80,83 +80,92 @@ describe('FollowUsers', () => { expect(user3).toBeInTheDocument(); }); - it('should render the correct navigation button on first load', () => { + it('should follow all suggested users by default', async () => { fetch.mockResponseOnce(fakeUsersResponse); - const { queryByText } = renderFollowUsers(); + const { queryByText, findAllByLabelText } = renderFollowUsers(); - expect(queryByText(/skip for now/i)).toBeDefined(); + const selectedUsers = await findAllByLabelText('Following'); + expect(selectedUsers).toHaveLength(3); + expect(queryByText(/Continue/i)).toExist(); }); - it('should update the navigation button text and follow status when you follow users', async () => { + it('should update the navigation button text and follow status when you follow/unfollow users', async () => { fetch.mockResponse(fakeUsersResponse); - const { queryByText, findByText, findAllByTestId } = renderFollowUsers(); + const { queryByText, queryAllByLabelText, findAllByTestId } = + renderFollowUsers(); const userButtons = await findAllByTestId( 'onboarding-user-following-status', ); - expect(queryByText(/skip for now/i)).toBeDefined(); - expect(queryByText(/You're not following anyone/i)).toBeDefined(); + expect(queryAllByLabelText('Following')).toHaveLength(3); + expect(queryByText(/You're following 3 people \(everyone\)/i)).toExist(); + expect(queryByText(/Continue/i)).toExist(); - // follow the first user - const firstUser = userButtons[0]; - firstUser.click(); + // Unfollow the first user + fireEvent.click(userButtons[0]); - await findByText('Following'); + expect(queryAllByLabelText('Following')).toHaveLength(2); + expect(queryByText(/You're following 2 people/i)).toExist(); + expect(queryByText(/continue/i)).toExist(); - expect(queryByText(/You're following 1 person/i)).toBeDefined(); - expect(queryByText(/continue/i)).toBeDefined(); + // Unfollow the second user + fireEvent.click(userButtons[1]); - // follow the second user - const secondUser = userButtons[1]; - secondUser.click(); + expect(queryAllByLabelText('Following')).toHaveLength(1); + expect(queryByText(/You're following 1 person/i)).toExist(); + expect(queryByText(/continue/i)).toExist(); - await findByText('Following'); + // Unfollow the third user + fireEvent.click(userButtons[2]); - expect(queryByText(/You're following 2 people/i)).toBeDefined(); - expect(queryByText(/continue/i)).toBeDefined(); + expect(queryByText('Following')).not.toExist(); + expect(queryByText(/You're not following anyone/i)).toExist(); + expect(queryByText(/skip for now/i)).toExist(); + + // Follow the third user again + fireEvent.click(userButtons[2]); + + expect(queryAllByLabelText('Following')).toHaveLength(1); + expect(queryByText(/You're following 1 person/i)).toExist(); + expect(queryByText(/continue/i)).toExist(); }); it('should have a functioning de/select all toggle', async () => { fetch.mockResponse(fakeUsersResponse); - const { - getByText, - queryByText, - findByText, - findAllByText, - } = renderFollowUsers(); + const { queryByText, findByText, queryAllByLabelText } = + renderFollowUsers(); + + // deselect all then test following count + const deselectAllSelector = await findByText(/Deselect all/i); + + fireEvent.click(deselectAllSelector); + + expect(queryAllByLabelText('Follow')).toHaveLength(3); + expect(queryByText('Following')).not.toExist(); + expect(queryByText(/You're not following anyone/i)).toExist(); // select all then test following count const followAllSelector = await findByText(/Select all 3 people/i); - followAllSelector.click(); + fireEvent.click(followAllSelector); - await findAllByText('Following'); - - expect(queryByText('Follow')).toBeNull(); - queryByText(/You're following 3 people (everyone)/i); - - // deselect all then test following count - const deselecAllSelector = await findByText(/Deselect all/i); - - deselecAllSelector.click(); - await findAllByText('Follow'); - - expect(queryByText('Following')).toBeNull(); - getByText(/You're not following anyone/i); + expect(queryByText('Follow')).not.toExist(); + expect(queryAllByLabelText('Following')).toHaveLength(3); + expect(queryByText(/You're following 3 people \(everyone\)/i)).toExist(); }); it('should render a stepper', () => { const { queryByTestId } = renderFollowUsers(); - expect(queryByTestId('stepper')).toBeDefined(); + expect(queryByTestId('stepper')).toExist(); }); it('should render a back button', () => { const { queryByTestId } = renderFollowUsers(); - expect(queryByTestId('back-button')).toBeDefined(); + expect(queryByTestId('back-button')).toExist(); }); }); diff --git a/testSetup.js b/testSetup.js index fe8c9dab0..72f98042b 100644 --- a/testSetup.js +++ b/testSetup.js @@ -1,4 +1,4 @@ -/* eslint-env node */ +/* eslint-env jest, node */ import 'jest-axe/extend-expect'; import './app/assets/javascripts/lib/xss'; @@ -18,3 +18,30 @@ process.on('unhandledRejection', (error) => { // Errors thrown here are typically fetch responses that have not been mocked. throw error; }); + +expect.extend({ + /** + * This matcher tests if its subject is neither null nor undefined. + * + * Jest's `toBeDefined` only tests if its subject is *strictly* not the value + * `undefined`, which makes it unsuitable for testing if a value exists as the + * value might be `null` (which would pass a `toBeDefined` check). + * + * @param {any} subject The subject of the matcher + * @returns + */ + toExist(subject) { + if (subject === null || subject === undefined) { + return { + pass: false, + message: () => `Expected ${this.utils.printReceived(subject)} to exist`, + }; + } + + return { + pass: true, + message: () => + `Expected ${this.utils.printReceived(subject)} to not exist`, + }; + }, +});