mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-22 20:51:29 +10:00
285 lines
9.0 KiB
JavaScript
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.',
|
|
);
|
|
});
|
|
});
|
|
});
|