diff --git a/__mocks__/@reach/router.js b/__mocks__/@reach/router.js new file mode 100644 index 00000000..75fb2af6 --- /dev/null +++ b/__mocks__/@reach/router.js @@ -0,0 +1,17 @@ +import { delay } from '../../src/utils/index'; + +const ReachRouter = jest.requireActual('@reach/router'); + +const defaultDelayInMilliseconds = 100; + +// eslint-disable-next-line no-unused-vars +const navigate = async (to, options) => { + await delay(defaultDelayInMilliseconds); + + return Promise.resolve(); +}; + +module.exports = { + ...ReachRouter, + navigate: jest.fn(navigate), +}; diff --git a/__mocks__/gatsby-plugin-firebase/auth/auth.js b/__mocks__/gatsby-plugin-firebase/auth/auth.js index cc5eeb0a..edb718c9 100644 --- a/__mocks__/gatsby-plugin-firebase/auth/auth.js +++ b/__mocks__/gatsby-plugin-firebase/auth/auth.js @@ -57,7 +57,7 @@ class Auth { user.email, user.isAnonymous, user.uid, - async () => {}, + this.signOut, ); await delay(Constants.defaultDelayInMilliseconds); @@ -68,6 +68,20 @@ class Auth { return this._currentUser; } + + async signOut() { + if (this._currentUser === null) { + return; + } + + this._currentUser = null; + + await delay(Constants.defaultDelayInMilliseconds); + + this.onAuthStateChangedObservers.forEach((observer) => + observer(this._currentUser), + ); + } } export default Auth; diff --git a/__mocks__/gatsby-plugin-firebase/constants/functions.js b/__mocks__/gatsby-plugin-firebase/constants/functions.js index 6ab0c54b..6e238cdc 100644 --- a/__mocks__/gatsby-plugin-firebase/constants/functions.js +++ b/__mocks__/gatsby-plugin-firebase/constants/functions.js @@ -1,6 +1,6 @@ const deleteUserFunctionName = 'deleteUser'; -const defaultDelayInMilliseconds = 2000; +const defaultDelayInMilliseconds = 100; class Functions { static get deleteUserFunctionName() { diff --git a/src/pages/app/__tests__/builder.settings.deleteAccount.test.js b/src/pages/app/__tests__/builder.settings.deleteAccount.test.js index 39302e86..44706d81 100644 --- a/src/pages/app/__tests__/builder.settings.deleteAccount.test.js +++ b/src/pages/app/__tests__/builder.settings.deleteAccount.test.js @@ -1,8 +1,14 @@ -import { fireEvent, screen } from '@testing-library/react'; +import { navigate as mockNavigateFunction } from '@reach/router'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; -import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase'; +import FirebaseStub, { + DatabaseConstants, + FunctionsConstants, +} from 'gatsby-plugin-firebase'; -import { setupAndWait } from './helpers/builder'; +import { delay } from '../../../utils/index'; + +import { setupAndWait, findAndDismissNotification } from './helpers/builder'; const testTimeoutInMilliseconds = 20000; jest.setTimeout(testTimeoutInMilliseconds); @@ -11,37 +17,75 @@ async function setup() { const resumeId = DatabaseConstants.demoStateResume1Id; await setupAndWait(resumeId, true, true); - const button = screen.getByRole('button', { - name: /Delete Account/i, + const mockFirebaseDeleteUserCloudFunction = jest.fn(async () => { + await delay(FunctionsConstants.defaultDelayInMilliseconds); }); + const mockFirebaseFunctionsHttpsCallable = jest.fn((name) => + name === FunctionsConstants.deleteUserFunctionName + ? mockFirebaseDeleteUserCloudFunction + : undefined, + ); + FirebaseStub.functions().httpsCallable = mockFirebaseFunctionsHttpsCallable; - const mockFirebaseUserDelete = jest.spyOn( + const mockFirebaseCurrentUserDelete = jest.spyOn( FirebaseStub.auth().currentUser, 'delete', ); + const button = screen.getByRole('button', { + name: /Delete Account/i, + }); + return { button, - mockFirebaseUserDelete, + mockFirebaseCurrentUserDelete, + mockFirebaseDeleteUserCloudFunction, }; } test('prompts for confirmation', async () => { - const { button, mockFirebaseUserDelete } = await setup(); + const { + button, + mockFirebaseDeleteUserCloudFunction, + mockFirebaseCurrentUserDelete, + } = await setup(); fireEvent.click(button); expect(button).toHaveTextContent('Are you sure?'); - expect(mockFirebaseUserDelete).not.toHaveBeenCalled(); + + await waitFor(() => + expect(mockFirebaseDeleteUserCloudFunction).not.toHaveBeenCalledTimes(1), + ); + await waitFor(() => + expect(mockFirebaseCurrentUserDelete).not.toHaveBeenCalled(), + ); }); /* -test('calls Firebase user delete', async () => { - const { button, mockFirebaseUserDelete } = await setup(); +test('calls Firebase delete user cloud function', async () => { + const { button, mockFirebaseDeleteUserCloudFunction } = await setup(); fireEvent.click(button); fireEvent.click(button); - expect(mockFirebaseUserDelete).toHaveBeenCalledTimes(1); + await waitFor(() => expect(mockNavigateFunction).toHaveBeenCalledTimes(1)); + await findAndDismissNotification(); + await waitFor(() => + expect(mockFirebaseDeleteUserCloudFunction).toHaveBeenCalledTimes(1), + ); +}); + +test('calls Firebase current user delete', async () => { + const { button, mockFirebaseCurrentUserDelete } = await setup(); + + fireEvent.click(button); + fireEvent.click(button); + + await waitFor(() => expect(mockNavigateFunction).toHaveBeenCalledTimes(1)); + await findAndDismissNotification(); + await waitFor(() => + expect(mockFirebaseCurrentUserDelete).toHaveBeenCalledTimes(1), + ); }); */ diff --git a/src/pages/app/__tests__/helpers/builder.js b/src/pages/app/__tests__/helpers/builder.js index e63c9346..8f5f30de 100644 --- a/src/pages/app/__tests__/helpers/builder.js +++ b/src/pages/app/__tests__/helpers/builder.js @@ -47,6 +47,15 @@ const expectDatabaseUpdateToHaveCompleted = async ( ); }; +const dismissNotification = (notification) => { + fireEvent.click(notification); +}; + +const findAndDismissNotification = async () => { + const notification = await screen.findByRole('alert'); + dismissNotification(notification); +}; + const dragAndDropDirectionUp = 'DND_DIRECTION_UP'; const dragAndDropDirectionDown = 'DND_DIRECTION_DOWN'; @@ -158,4 +167,6 @@ export { dragAndDropDirectionUp, dragAndDropDirectionDown, dragAndDropListItem, + dismissNotification, + findAndDismissNotification, };