Files
Reactive-Resume/src/pages/app/__tests__/builder.settings.deleteAccount.test.js

285 lines
9.0 KiB
JavaScript

import { navigate as mockNavigateFunction } from '@reach/router';
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 = 60000;
jest.setTimeout(testTimeoutInMilliseconds);
async function setup(signInWithGoogle, failReauthentication) {
const resumeId = signInWithGoogle
? DatabaseConstants.demoStateResume3Id
: DatabaseConstants.demoStateResume1Id;
await setupAndWait(resumeId, signInWithGoogle, true, true);
let mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage;
let mockFirebaseCurrentUserReauthenticateWithPopup;
if (failReauthentication) {
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage =
'Error occurred while reauthenticating.';
mockFirebaseCurrentUserReauthenticateWithPopup = jest.fn(async () => {
await delay(AuthConstants.defaultDelayInMilliseconds);
throw new Error(
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage,
);
});
FirebaseStub.auth().currentUser.reauthenticateWithPopup = mockFirebaseCurrentUserReauthenticateWithPopup;
} else {
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage = null;
mockFirebaseCurrentUserReauthenticateWithPopup = jest.spyOn(
FirebaseStub.auth().currentUser,
'reauthenticateWithPopup',
);
}
const mockFirebaseDeleteUserCloudFunction = jest.fn(async () => {
await delay(FunctionsConstants.defaultDelayInMilliseconds);
});
const mockFirebaseFunctionsHttpsCallable = jest.fn((name) =>
name === FunctionsConstants.deleteUserFunctionName
? mockFirebaseDeleteUserCloudFunction
: undefined,
);
FirebaseStub.functions().httpsCallable = mockFirebaseFunctionsHttpsCallable;
const mockFirebaseCurrentUserDelete = jest.spyOn(
FirebaseStub.auth().currentUser,
'delete',
);
const mockFirebaseAuthSignOutErrorMessage =
'Error occurred while signing out.';
const mockFirebaseAuthSignOut = jest.fn(async () => {
await delay(AuthConstants.defaultDelayInMilliseconds);
throw new Error(mockFirebaseAuthSignOutErrorMessage);
});
FirebaseStub.auth().signOut = mockFirebaseAuthSignOut;
// eslint-disable-next-line no-unused-vars
const mockToastError = jest.fn((content, options) => {});
toast.error = mockToastError;
const deleteAccountButtonText = /Delete Account/i;
const areYouSureButtonText = /Are you sure?/i;
const deleteAccountButton = screen.getByRole('button', {
name: deleteAccountButtonText,
});
const waitForDeleteAccountButtonTextToChangeTo = async (text) => {
await waitFor(() => expect(deleteAccountButton).toHaveTextContent(text), {
timeout: 30000,
});
};
return {
deleteAccountButton,
areYouSureButtonText,
deleteAccountButtonText,
waitForDeleteAccountButtonTextToChangeTo,
mockFirebaseCurrentUserReauthenticateWithPopup,
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage,
mockFirebaseDeleteUserCloudFunction,
mockFirebaseCurrentUserDelete,
mockFirebaseAuthSignOut,
mockFirebaseAuthSignOutErrorMessage,
mockToastError,
};
}
test('prompts for confirmation', async () => {
const {
deleteAccountButton,
areYouSureButtonText,
waitForDeleteAccountButtonTextToChangeTo,
mockFirebaseDeleteUserCloudFunction,
mockFirebaseCurrentUserDelete,
mockFirebaseAuthSignOut,
mockToastError,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
await expect(
waitForDeleteAccountButtonTextToChangeTo(areYouSureButtonText),
).resolves.toBeUndefined();
expect(mockFirebaseDeleteUserCloudFunction).not.toHaveBeenCalled();
expect(mockFirebaseCurrentUserDelete).not.toHaveBeenCalled();
expect(mockFirebaseAuthSignOut).not.toHaveBeenCalled();
expect(mockNavigateFunction).not.toHaveBeenCalled();
expect(mockToastError).not.toHaveBeenCalled();
});
test('calls Firebase delete user cloud function', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
mockFirebaseDeleteUserCloudFunction,
waitForDeleteAccountButtonTextToChangeTo,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
await waitFor(() =>
expect(mockFirebaseDeleteUserCloudFunction).toHaveBeenCalledTimes(1),
);
});
test('calls Firebase current user delete', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
mockFirebaseCurrentUserDelete,
waitForDeleteAccountButtonTextToChangeTo,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
await waitFor(() =>
expect(mockFirebaseCurrentUserDelete).toHaveBeenCalledTimes(1),
);
});
test('calls Firebase auth sign out', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
mockFirebaseAuthSignOut,
waitForDeleteAccountButtonTextToChangeTo,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
await waitFor(() => expect(mockFirebaseAuthSignOut).toHaveBeenCalledTimes(1));
});
describe('if an error occurs while signing out the current user', () => {
test('does not navigate away', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
waitForDeleteAccountButtonTextToChangeTo,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
expect(mockNavigateFunction).not.toHaveBeenCalled();
});
test('displays error notifications', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
mockFirebaseAuthSignOutErrorMessage,
waitForDeleteAccountButtonTextToChangeTo,
mockToastError,
} = await setup(false, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
expect(mockToastError).toHaveBeenCalledTimes(2);
expect(mockToastError).toHaveBeenNthCalledWith(
1,
mockFirebaseAuthSignOutErrorMessage,
);
expect(mockToastError).toHaveBeenNthCalledWith(
2,
'An error occurred deleting your account.',
);
});
});
describe('if the current user is signed in with Google', () => {
test('reauthenticates the user', async () => {
const googleAuthProvider = new FirebaseStub.auth.GoogleAuthProvider();
const {
deleteAccountButton,
deleteAccountButtonText,
mockFirebaseCurrentUserReauthenticateWithPopup,
waitForDeleteAccountButtonTextToChangeTo,
} = await setup(true, false);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
expect(
mockFirebaseCurrentUserReauthenticateWithPopup,
).toHaveBeenCalledTimes(1);
expect(mockFirebaseCurrentUserReauthenticateWithPopup).toHaveBeenCalledWith(
googleAuthProvider,
);
});
describe('and reauthentication fails', () => {
test('does not proceed further', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
waitForDeleteAccountButtonTextToChangeTo,
mockFirebaseDeleteUserCloudFunction,
mockFirebaseCurrentUserDelete,
mockFirebaseAuthSignOut,
} = await setup(true, true);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
expect(mockFirebaseDeleteUserCloudFunction).not.toHaveBeenCalled();
expect(mockFirebaseCurrentUserDelete).not.toHaveBeenCalled();
expect(mockFirebaseAuthSignOut).not.toHaveBeenCalled();
expect(mockNavigateFunction).not.toHaveBeenCalled();
});
test('displays error notifications', async () => {
const {
deleteAccountButton,
deleteAccountButtonText,
waitForDeleteAccountButtonTextToChangeTo,
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage,
mockToastError,
} = await setup(true, true);
fireEvent.click(deleteAccountButton);
fireEvent.click(deleteAccountButton);
await waitForDeleteAccountButtonTextToChangeTo(deleteAccountButtonText);
expect(mockToastError).toHaveBeenCalledTimes(2);
expect(mockToastError).toHaveBeenNthCalledWith(
1,
mockFirebaseCurrentUserReauthenticateWithPopupErrorMessage,
);
expect(mockToastError).toHaveBeenNthCalledWith(
2,
'An error occurred deleting your account.',
);
});
});
});