From 53d0e178652b98e9d2a8d13949a943cc47d4068e Mon Sep 17 00:00:00 2001 From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com> Date: Tue, 18 May 2021 13:41:38 +0200 Subject: [PATCH] Delete Account unit tests: fixed warnings, added test for error notifications --- .../builder.settings.deleteAccount.test.js | 126 +++++++++++------- src/utils/index.js | 5 +- 2 files changed, 80 insertions(+), 51 deletions(-) diff --git a/src/pages/app/__tests__/builder.settings.deleteAccount.test.js b/src/pages/app/__tests__/builder.settings.deleteAccount.test.js index 3c304462..7c5f8f1d 100644 --- a/src/pages/app/__tests__/builder.settings.deleteAccount.test.js +++ b/src/pages/app/__tests__/builder.settings.deleteAccount.test.js @@ -3,20 +3,24 @@ import { toast } from 'react-toastify'; import { fireEvent, screen, waitFor } from '@testing-library/react'; import FirebaseStub, { + AuthConstants, DatabaseConstants, FunctionsConstants, } from 'gatsby-plugin-firebase'; import { setupAndWait } from './helpers/builder'; +import { delay } from '../../../utils/index'; -const testTimeoutInMilliseconds = 20000; +const testTimeoutInMilliseconds = 60000; jest.setTimeout(testTimeoutInMilliseconds); async function setup() { const resumeId = DatabaseConstants.demoStateResume1Id; await setupAndWait(resumeId, true, true); - const mockFirebaseDeleteUserCloudFunction = jest.fn(async () => {}); + const mockFirebaseDeleteUserCloudFunction = jest.fn(async () => { + await delay(FunctionsConstants.defaultDelayInMilliseconds); + }); const mockFirebaseFunctionsHttpsCallable = jest.fn((name) => name === FunctionsConstants.deleteUserFunctionName ? mockFirebaseDeleteUserCloudFunction @@ -24,13 +28,16 @@ async function setup() { ); FirebaseStub.functions().httpsCallable = mockFirebaseFunctionsHttpsCallable; - const mockFirebaseCurrentUserDelete = jest.fn(async () => { - throw new Error('Error occurred while deleting user.'); - }); - FirebaseStub.auth().currentUser.delete = mockFirebaseCurrentUserDelete; + const mockFirebaseCurrentUserDelete = jest.spyOn( + FirebaseStub.auth().currentUser, + 'delete', + ); + const mockFirebaseAuthSignOutErrorMessage = + 'Error occurred while signing out.'; const mockFirebaseAuthSignOut = jest.fn(async () => { - throw new Error('Error occurred while signing out.'); + await delay(AuthConstants.defaultDelayInMilliseconds); + throw new Error(mockFirebaseAuthSignOutErrorMessage); }); FirebaseStub.auth().signOut = mockFirebaseAuthSignOut; @@ -38,40 +45,46 @@ async function setup() { const mockToastError = jest.fn((content, options) => {}); toast.error = mockToastError; - const deleteAccountRegExp = /Delete Account/i; - const button = screen.getByRole('button', { - name: deleteAccountRegExp, + const deleteAccountButtonText = /Delete Account/i; + const areYouSureButtonText = /Are you sure?/i; + const deleteAccountButton = screen.getByRole('button', { + name: deleteAccountButtonText, }); - - const waitForButtonNameToBeSetToDeleteAccount = async () => { - waitFor(() => { - expect(button).toHaveTextContent(deleteAccountRegExp); + const waitForDeleteAccountButtonTextToChangeTo = async (text) => { + await waitFor(() => expect(deleteAccountButton).toHaveTextContent(text), { + timeout: 30000, }); }; return { - button, + deleteAccountButton, + areYouSureButtonText, + deleteAccountButtonText, + waitForDeleteAccountButtonTextToChangeTo, mockFirebaseDeleteUserCloudFunction, mockFirebaseCurrentUserDelete, mockFirebaseAuthSignOut, + mockFirebaseAuthSignOutErrorMessage, mockToastError, - waitForButtonNameToBeSetToDeleteAccount, }; } test('prompts for confirmation', async () => { const { - button, + deleteAccountButton, + areYouSureButtonText, + waitForDeleteAccountButtonTextToChangeTo, mockFirebaseDeleteUserCloudFunction, mockFirebaseCurrentUserDelete, mockFirebaseAuthSignOut, mockToastError, } = await setup(); - fireEvent.click(button); - - expect(button).toHaveTextContent(/Are you sure?/i); + fireEvent.click(deleteAccountButton); + await expect( + waitForDeleteAccountButtonTextToChangeTo(areYouSureButtonText), + ).resolves.toBeUndefined(); expect(mockFirebaseDeleteUserCloudFunction).not.toHaveBeenCalled(); expect(mockFirebaseCurrentUserDelete).not.toHaveBeenCalled(); expect(mockFirebaseAuthSignOut).not.toHaveBeenCalled(); @@ -81,15 +94,17 @@ test('prompts for confirmation', async () => { test('calls Firebase delete user cloud function', async () => { const { - button, + deleteAccountButton, + deleteAccountButtonText, mockFirebaseDeleteUserCloudFunction, - waitForButtonNameToBeSetToDeleteAccount, + waitForDeleteAccountButtonTextToChangeTo, } = await setup(); - fireEvent.click(button); - fireEvent.click(button); + fireEvent.click(deleteAccountButton); + fireEvent.click(deleteAccountButton); + + await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText); - await waitForButtonNameToBeSetToDeleteAccount(); await waitFor(() => expect(mockFirebaseDeleteUserCloudFunction).toHaveBeenCalledTimes(1), ); @@ -97,15 +112,17 @@ test('calls Firebase delete user cloud function', async () => { test('calls Firebase current user delete', async () => { const { - button, + deleteAccountButton, + deleteAccountButtonText, mockFirebaseCurrentUserDelete, - waitForButtonNameToBeSetToDeleteAccount, + waitForDeleteAccountButtonTextToChangeTo, } = await setup(); - fireEvent.click(button); - fireEvent.click(button); + fireEvent.click(deleteAccountButton); + fireEvent.click(deleteAccountButton); + + await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText); - await waitForButtonNameToBeSetToDeleteAccount(); await waitFor(() => expect(mockFirebaseCurrentUserDelete).toHaveBeenCalledTimes(1), ); @@ -113,45 +130,58 @@ test('calls Firebase current user delete', async () => { test('calls Firebase auth sign out', async () => { const { - button, + deleteAccountButton, + deleteAccountButtonText, mockFirebaseAuthSignOut, - waitForButtonNameToBeSetToDeleteAccount, + waitForDeleteAccountButtonTextToChangeTo, } = await setup(); - fireEvent.click(button); - fireEvent.click(button); + fireEvent.click(deleteAccountButton); + fireEvent.click(deleteAccountButton); + + await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText); - await waitForButtonNameToBeSetToDeleteAccount(); await waitFor(() => expect(mockFirebaseAuthSignOut).toHaveBeenCalledTimes(1)); }); describe('if an error occurs while signing out the current user', () => { test('does not navigate away', async () => { - const { button, waitForButtonNameToBeSetToDeleteAccount } = await setup(); + const { + deleteAccountButton, + deleteAccountButtonText, + waitForDeleteAccountButtonTextToChangeTo, + } = await setup(); - fireEvent.click(button); - fireEvent.click(button); + fireEvent.click(deleteAccountButton); + fireEvent.click(deleteAccountButton); + + await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText); - await waitForButtonNameToBeSetToDeleteAccount(); expect(mockNavigateFunction).not.toHaveBeenCalled(); }); - /* - test('displays toast', async () => { + test('displays error notifications', async () => { const { - button, - waitForButtonNameToBeSetToDeleteAccount, + deleteAccountButton, + deleteAccountButtonText, + mockFirebaseAuthSignOutErrorMessage, + waitForDeleteAccountButtonTextToChangeTo, mockToastError, } = await setup(); - fireEvent.click(button); - fireEvent.click(button); + fireEvent.click(deleteAccountButton); + fireEvent.click(deleteAccountButton); + + await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText); - await waitForButtonNameToBeSetToDeleteAccount(); expect(mockToastError).toHaveBeenCalledTimes(2); - expect(mockToastError).toHaveBeenLastCalledWith( + expect(mockToastError).toHaveBeenNthCalledWith( + 1, + mockFirebaseAuthSignOutErrorMessage, + ); + expect(mockToastError).toHaveBeenNthCalledWith( + 2, 'An error occurred deleting your account.', ); }); - */ }); diff --git a/src/utils/index.js b/src/utils/index.js index 843d1454..6e657583 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -137,6 +137,5 @@ export const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { return blob; }; -export const delay = async (milliseconds) => { - await new Promise((resolve) => setTimeout(resolve, milliseconds)); -}; +export const delay = (milliseconds) => + new Promise((resolve) => setTimeout(resolve, milliseconds));