@@ -17,3 +19,4 @@ const LoadingScreen = () => (
);
export default memo(LoadingScreen);
+export { dataTestId };
diff --git a/src/contexts/SettingsContext.js b/src/contexts/SettingsContext.js
index e17e6b1d3..a3277a53f 100644
--- a/src/contexts/SettingsContext.js
+++ b/src/contexts/SettingsContext.js
@@ -2,6 +2,8 @@ import i18next from 'i18next';
import React, { createContext, memo, useEffect, useState } from 'react';
import themeConfig from '../data/themeConfig';
+const languageStorageItemKey = 'language';
+
const defaultState = {
theme: 'Dark',
setTheme: () => {},
@@ -18,7 +20,7 @@ const SettingsProvider = ({ children }) => {
useEffect(() => {
const prefTheme = localStorage.getItem('theme') || defaultState.theme;
const prefLanguage =
- localStorage.getItem('language') || defaultState.language;
+ localStorage.getItem(languageStorageItemKey) || defaultState.language;
setTheme(prefTheme);
setLanguage(prefLanguage);
}, []);
@@ -32,7 +34,7 @@ const SettingsProvider = ({ children }) => {
}, [theme]);
useEffect(() => {
- localStorage.setItem('language', language);
+ localStorage.setItem(languageStorageItemKey, language);
i18next.changeLanguage(language);
}, [language]);
@@ -54,4 +56,4 @@ export default SettingsContext;
const memoizedProvider = memo(SettingsProvider);
-export { memoizedProvider as SettingsProvider };
+export { memoizedProvider as SettingsProvider, languageStorageItemKey };
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index d1551e62a..c6f0ebd54 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -10,7 +10,11 @@ import {
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
-import { SettingsProvider } from '../../../contexts/SettingsContext';
+import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
+import {
+ SettingsProvider,
+ languageStorageItemKey,
+} from '../../../contexts/SettingsContext';
import { ModalProvider } from '../../../contexts/ModalContext';
import { UserProvider } from '../../../contexts/UserContext';
import {
@@ -25,7 +29,6 @@ describe('Builder', () => {
let resumeId = null;
let resume = null;
let mockDatabaseUpdateFunction = null;
- const loadingScreenTestId = 'loading-screen';
async function setup(
resumeIdParameter,
@@ -118,8 +121,6 @@ describe('Builder', () => {
});
describe('settings', () => {
- const languageStorageItemKey = 'language';
-
beforeEach(async () => {
await setup(DatabaseConstants.demoStateResume1Id);
});
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index a2ff6adf6..a8e65ae5c 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -9,6 +9,7 @@ import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import '../../../i18n/index';
import '../../../utils/dayjs';
+import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
import { SettingsProvider } from '../../../contexts/SettingsContext';
import { ModalProvider } from '../../../contexts/ModalContext';
import { UserProvider } from '../../../contexts/UserContext';
@@ -20,7 +21,6 @@ import Dashboard from '../dashboard';
describe('Dashboard', () => {
let resumes = null;
const user = DatabaseConstants.user1;
- const loadingScreenTestId = 'loading-screen';
async function setup(waitForLoadingScreenToDisappear = true) {
FirebaseStub.database().initializeData();
From cb2aeec70a4d34f5f758fc40920269d8222b88bb Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Fri, 22 Jan 2021 10:43:06 +0100
Subject: [PATCH 09/14] Dashboard: added unit tests for Delete resume
---
src/components/dashboard/ResumePreview.js | 5 ++
src/pages/app/__tests__/dashboard.test.js | 66 +++++++++++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/src/components/dashboard/ResumePreview.js b/src/components/dashboard/ResumePreview.js
index d0a794e80..52fca4681 100644
--- a/src/components/dashboard/ResumePreview.js
+++ b/src/components/dashboard/ResumePreview.js
@@ -9,6 +9,8 @@ import DatabaseContext from '../../contexts/DatabaseContext';
import ModalContext from '../../contexts/ModalContext';
import styles from './ResumePreview.module.css';
+const menuToggleDataTestIdPrefix = 'resume-preview-menu-toggle-';
+
const ResumePreview = ({ resume }) => {
const { t, i18n } = useTranslation();
const [anchorEl, setAnchorEl] = useState(null);
@@ -54,6 +56,7 @@ const ResumePreview = ({ resume }) => {
onClick={handleOpen}
/>
{
};
export default ResumePreview;
+
+export { menuToggleDataTestIdPrefix };
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index a8e65ae5c..f65cfbb5a 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -1,7 +1,10 @@
import React from 'react';
import {
+ fireEvent,
+ queryByText,
render,
screen,
+ waitFor,
waitForElementToBeRemoved,
} from '@testing-library/react';
@@ -10,6 +13,7 @@ import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import '../../../i18n/index';
import '../../../utils/dayjs';
import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
+import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
import { SettingsProvider } from '../../../contexts/SettingsContext';
import { ModalProvider } from '../../../contexts/ModalContext';
import { UserProvider } from '../../../contexts/UserContext';
@@ -85,6 +89,68 @@ describe('Dashboard', () => {
});
});
+ describe('when resume is deleted', () => {
+ let mockDatabaseRemoveFunction = null;
+ let resumeToDelete = null;
+ let undeletedResume = null;
+ let resumeToDeleteId = null;
+
+ beforeEach(async () => {
+ await setup();
+
+ [resumeToDelete, undeletedResume] = Object.values(resumes);
+ resumeToDeleteId = resumeToDelete.id;
+
+ mockDatabaseRemoveFunction = jest.spyOn(
+ FirebaseStub.database().ref(
+ `${DatabaseConstants.resumesPath}/${resumeToDeleteId}`,
+ ),
+ 'remove',
+ );
+
+ const resumeToDeleteMenuToggle = screen.getByTestId(
+ `${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
+ );
+ fireEvent.click(resumeToDeleteMenuToggle);
+
+ const menuItems = screen.getAllByRole('menuitem');
+ let deleteMenuItem = null;
+ for (let index = 0; index < menuItems.length; index++) {
+ if (queryByText(menuItems[index], /delete/i)) {
+ deleteMenuItem = menuItems[index];
+ break;
+ }
+ }
+ fireEvent.click(deleteMenuItem);
+ });
+
+ it('removes it from database and preview', async () => {
+ await waitFor(() =>
+ expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
+ );
+
+ await waitFor(() =>
+ expect(screen.queryByText(resumeToDelete.name)).toBeNull(),
+ );
+ expect(screen.getByText(undeletedResume.name)).toBeInTheDocument();
+ });
+
+ /*
+ it('displays notification', async () => {
+ await waitFor(() =>
+ expect(
+ screen.getByText(`${resumeToDelete.name} was deleted successfully`),
+ ).toBeInTheDocument(),
+ );
+ });
+ */
+
+ it('closes menu', () => {
+ const menuItems = screen.queryAllByRole('menuitem');
+ expect(menuItems).toHaveLength(0);
+ });
+ });
+
describe('while loading', () => {
beforeEach(async () => {
await setup(false);
From dc18e84bc2cbfabcbde6594f6c1ba6d5b2971cc6 Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Fri, 22 Jan 2021 16:42:21 +0100
Subject: [PATCH 10/14] Dashboard: updated unit tests for Delete resume
---
.../database/reference.js | 11 ++-
src/pages/app/__tests__/builder.test.js | 11 ++-
src/pages/app/__tests__/dashboard.test.js | 71 +++++++++++++------
3 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/__mocks__/gatsby-plugin-firebase/database/reference.js b/__mocks__/gatsby-plugin-firebase/database/reference.js
index ea04ee405..305c82b78 100644
--- a/__mocks__/gatsby-plugin-firebase/database/reference.js
+++ b/__mocks__/gatsby-plugin-firebase/database/reference.js
@@ -1,6 +1,5 @@
/* eslint-disable no-underscore-dangle */
import { v4 as uuidv4 } from 'uuid';
-import { debounce } from 'lodash';
import DatabaseConstants from '../constants/database';
import DataSnapshot from './dataSnapshot';
@@ -148,11 +147,7 @@ class Reference {
? this._dataSnapshot
: new DataSnapshot(() => this._getData(), snapshotValue);
- const debouncedEventCallback = debounce(
- this.eventCallbacks[eventType],
- DatabaseConstants.defaultDelayInMilliseconds,
- );
- debouncedEventCallback(snapshot);
+ this.eventCallbacks[eventType](snapshot);
}
equalTo(value) {
@@ -173,7 +168,9 @@ class Reference {
this.eventCallbacks[eventType] = callback;
if (eventType === DatabaseConstants.valueEventType) {
- this.triggerEventCallback(eventType);
+ setTimeout(() => {
+ this.triggerEventCallback(eventType);
+ }, DatabaseConstants.defaultDelayInMilliseconds);
}
return callback;
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index c6f0ebd54..558609357 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -23,6 +23,7 @@ import {
} from '../../../contexts/DatabaseContext';
import { ResumeProvider } from '../../../contexts/ResumeContext';
import { StorageProvider } from '../../../contexts/StorageContext';
+import Wrapper from '../../../components/shared/Wrapper';
import Builder from '../builder';
describe('Builder', () => {
@@ -60,7 +61,9 @@ describe('Builder', () => {
-
+
+
+
@@ -212,6 +215,12 @@ describe('Builder', () => {
await setup(DatabaseConstants.demoStateResume1Id, false, false);
});
+ afterEach(async () => {
+ await waitForElementToBeRemoved(() =>
+ screen.getByTestId(loadingScreenTestId),
+ );
+ });
+
it('renders loading screen', () => {
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
});
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index f65cfbb5a..385493b92 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -20,6 +20,7 @@ import { UserProvider } from '../../../contexts/UserContext';
import { DatabaseProvider } from '../../../contexts/DatabaseContext';
import { ResumeProvider } from '../../../contexts/ResumeContext';
import { StorageProvider } from '../../../contexts/StorageContext';
+import Wrapper from '../../../components/shared/Wrapper';
import Dashboard from '../dashboard';
describe('Dashboard', () => {
@@ -46,7 +47,9 @@ describe('Dashboard', () => {
-
+
+
+
@@ -67,25 +70,33 @@ describe('Dashboard', () => {
await setup();
});
- it('document title', () => {
- expect(document.title).toEqual('Dashboard | Reactive Resume');
+ it('document title', async () => {
+ await waitFor(() => {
+ expect(document.title).toEqual('Dashboard | Reactive Resume');
+ });
});
- it('create resume', () => {
- expect(screen.getByText(/create resume/i)).toBeInTheDocument();
+ it('create resume', async () => {
+ await waitFor(() => {
+ expect(screen.getByText(/create resume/i)).toBeInTheDocument();
+ });
});
- it('preview of user resumes', () => {
+ it('preview of user resumes', async () => {
expect(Object.keys(resumes)).toHaveLength(2);
expect(Object.values(resumes)[0].user).toEqual(user.uid);
- expect(
- screen.getByText(Object.values(resumes)[0].name),
- ).toBeInTheDocument();
+ await waitFor(() => {
+ expect(
+ screen.getByText(Object.values(resumes)[0].name),
+ ).toBeInTheDocument();
+ });
expect(Object.values(resumes)[1].user).toEqual(user.uid);
- expect(
- screen.getByText(Object.values(resumes)[1].name),
- ).toBeInTheDocument();
+ await waitFor(() => {
+ expect(
+ screen.getByText(Object.values(resumes)[1].name),
+ ).toBeInTheDocument();
+ });
});
});
@@ -95,6 +106,10 @@ describe('Dashboard', () => {
let undeletedResume = null;
let resumeToDeleteId = null;
+ const waitForDatabaseRemoveFunctionToHaveCompleted = async () => {
+ await waitFor(() => mockDatabaseRemoveFunction.mock.results[0].value);
+ };
+
beforeEach(async () => {
await setup();
@@ -108,9 +123,13 @@ describe('Dashboard', () => {
'remove',
);
- const resumeToDeleteMenuToggle = screen.getByTestId(
- `${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
- );
+ let resumeToDeleteMenuToggle = null;
+ await waitFor(() => {
+ resumeToDeleteMenuToggle = screen.queryByTestId(
+ `${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
+ );
+ return resumeToDeleteMenuToggle ? Promise.resolve() : Promise.reject();
+ });
fireEvent.click(resumeToDeleteMenuToggle);
const menuItems = screen.getAllByRole('menuitem');
@@ -124,26 +143,28 @@ describe('Dashboard', () => {
fireEvent.click(deleteMenuItem);
});
+ afterEach(async () => {
+ await waitForDatabaseRemoveFunctionToHaveCompleted();
+ });
+
it('removes it from database and preview', async () => {
await waitFor(() =>
expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
);
+ await waitForDatabaseRemoveFunctionToHaveCompleted();
+
await waitFor(() =>
expect(screen.queryByText(resumeToDelete.name)).toBeNull(),
);
expect(screen.getByText(undeletedResume.name)).toBeInTheDocument();
});
- /*
it('displays notification', async () => {
- await waitFor(() =>
- expect(
- screen.getByText(`${resumeToDelete.name} was deleted successfully`),
- ).toBeInTheDocument(),
- );
+ await waitFor(() => {
+ expect(screen.getByRole('alert')).toBeInTheDocument();
+ });
});
- */
it('closes menu', () => {
const menuItems = screen.queryAllByRole('menuitem');
@@ -156,6 +177,12 @@ describe('Dashboard', () => {
await setup(false);
});
+ afterEach(async () => {
+ await waitForElementToBeRemoved(() =>
+ screen.getByTestId(loadingScreenTestId),
+ );
+ });
+
it('renders loading screen', () => {
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
});
From 9a7bdb188b015ec133eee8171dd1276426d06b76 Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Fri, 22 Jan 2021 17:25:04 +0100
Subject: [PATCH 11/14] Builder: updated unit test handling non-existent resume
---
__mocks__/gatsby-plugin-firebase/auth/auth.js | 2 +-
.../gatsby-plugin-firebase/database/reference.js | 2 +-
__mocks__/gatsby.js | 12 +++++++++++-
.../{gatsby-plugin-firebase => }/utils/index.js | 0
src/pages/app/__tests__/builder.test.js | 14 +++++++++++++-
5 files changed, 26 insertions(+), 4 deletions(-)
rename __mocks__/{gatsby-plugin-firebase => }/utils/index.js (100%)
diff --git a/__mocks__/gatsby-plugin-firebase/auth/auth.js b/__mocks__/gatsby-plugin-firebase/auth/auth.js
index b27aaf102..fc5eb043b 100644
--- a/__mocks__/gatsby-plugin-firebase/auth/auth.js
+++ b/__mocks__/gatsby-plugin-firebase/auth/auth.js
@@ -2,7 +2,7 @@
import { v4 as uuidv4 } from 'uuid';
import Constants from '../constants/auth';
-import delay from '../utils/index';
+import delay from '../../utils/index';
const singleton = Symbol('');
const singletonEnforcer = Symbol('');
diff --git a/__mocks__/gatsby-plugin-firebase/database/reference.js b/__mocks__/gatsby-plugin-firebase/database/reference.js
index 305c82b78..08e345fdb 100644
--- a/__mocks__/gatsby-plugin-firebase/database/reference.js
+++ b/__mocks__/gatsby-plugin-firebase/database/reference.js
@@ -3,7 +3,7 @@ import { v4 as uuidv4 } from 'uuid';
import DatabaseConstants from '../constants/database';
import DataSnapshot from './dataSnapshot';
-import delay from '../utils/index';
+import delay from '../../utils/index';
const parsePath = (path) => {
if (!path) {
diff --git a/__mocks__/gatsby.js b/__mocks__/gatsby.js
index e9339f5d9..09ea71c73 100644
--- a/__mocks__/gatsby.js
+++ b/__mocks__/gatsby.js
@@ -1,5 +1,7 @@
import React from 'react';
+import delay from './utils/index';
+
const Gatsby = jest.requireActual('gatsby');
const fluidImageShapes = [
@@ -67,6 +69,14 @@ const useStaticQuery = () => ({
},
});
+const defaultDelayInMilliseconds = 100;
+
+const navigate = async () => {
+ await delay(defaultDelayInMilliseconds);
+
+ return Promise.resolve();
+};
+
module.exports = {
...Gatsby,
graphql: jest.fn(),
@@ -76,6 +86,6 @@ module.exports = {
href: to,
}),
),
- navigate: jest.fn(),
+ navigate: jest.fn(navigate),
useStaticQuery,
};
diff --git a/__mocks__/gatsby-plugin-firebase/utils/index.js b/__mocks__/utils/index.js
similarity index 100%
rename from __mocks__/gatsby-plugin-firebase/utils/index.js
rename to __mocks__/utils/index.js
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index 558609357..cc9b80ef0 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -89,15 +89,27 @@ describe('Builder', () => {
describe('handles errors', () => {
describe('if resume does not exist', () => {
+ const waitForNavigateFunctionToHaveCompleted = async () => {
+ await waitFor(() => mockNavigateFunction.mock.results[0].value);
+ };
+
beforeEach(async () => {
await setup('xxxxxx', false, false);
});
- it('navigates to Dashboard', async () => {
+ afterEach(async () => {
+ await waitForNavigateFunctionToHaveCompleted();
+ });
+
+ it('navigates to Dashboard and displays notification', async () => {
await waitFor(() =>
expect(mockNavigateFunction).toHaveBeenCalledTimes(1),
);
expect(mockNavigateFunction).toHaveBeenCalledWith('/app/dashboard');
+
+ await waitFor(() => {
+ expect(screen.getByRole('alert')).toBeInTheDocument();
+ });
});
});
});
From 5317f5e525e78843301e918178ba418e7ff8a9d1 Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Sat, 23 Jan 2021 11:45:06 +0100
Subject: [PATCH 12/14] Builder and Dashboard unit tests refactoring/cleanup
---
.../__tests__/gatsby-plugin-firebase.test.js | 17 ++--
__mocks__/gatsby-plugin-firebase/auth/auth.js | 4 -
src/pages/app/__tests__/builder.test.js | 76 ++++++++---------
src/pages/app/__tests__/dashboard.test.js | 82 ++++++++++---------
4 files changed, 86 insertions(+), 93 deletions(-)
diff --git a/__mocks__/__tests__/gatsby-plugin-firebase.test.js b/__mocks__/__tests__/gatsby-plugin-firebase.test.js
index 84e0a9ca3..f80e06c08 100644
--- a/__mocks__/__tests__/gatsby-plugin-firebase.test.js
+++ b/__mocks__/__tests__/gatsby-plugin-firebase.test.js
@@ -6,10 +6,6 @@ import FirebaseStub, {
describe('FirebaseStub', () => {
describe('auth', () => {
- afterEach(() => {
- FirebaseStub.auth().dispose();
- });
-
it('reuses existing Auth instance', () => {
const auth1 = FirebaseStub.auth();
const auth2 = FirebaseStub.auth();
@@ -49,14 +45,15 @@ describe('FirebaseStub', () => {
const observer = () => {};
const unsubscribe = FirebaseStub.auth().onAuthStateChanged(observer);
expect(unsubscribe).toBeTruthy();
- expect(FirebaseStub.auth().onAuthStateChangedObservers).toHaveLength(1);
- expect(FirebaseStub.auth().onAuthStateChangedObservers[0]).toEqual(
- observer,
- );
+ expect(
+ FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
+ ).toBeGreaterThanOrEqual(0);
unsubscribe();
- expect(FirebaseStub.auth().onAuthStateChangedObservers).toHaveLength(0);
+ expect(
+ FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
+ ).not.toBeGreaterThanOrEqual(0);
});
});
@@ -258,7 +255,7 @@ describe('FirebaseStub', () => {
);
});
- it('previously set query parameters are not kept when retrieving reference again', async () => {
+ it('previously set query parameters are not kept when retrieving reference again', () => {
let reference = null;
reference = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
diff --git a/__mocks__/gatsby-plugin-firebase/auth/auth.js b/__mocks__/gatsby-plugin-firebase/auth/auth.js
index fc5eb043b..853bb1334 100644
--- a/__mocks__/gatsby-plugin-firebase/auth/auth.js
+++ b/__mocks__/gatsby-plugin-firebase/auth/auth.js
@@ -33,10 +33,6 @@ class Auth {
return this._onAuthStateChangedObservers;
}
- dispose() {
- this._onAuthStateChangedObservers = [];
- }
-
onAuthStateChanged(observer) {
this.onAuthStateChangedObservers.push(observer);
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index cc9b80ef0..4615e5aa5 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -31,10 +31,31 @@ describe('Builder', () => {
let resume = null;
let mockDatabaseUpdateFunction = null;
+ const fnWaitForDatabaseUpdateToHaveCompleted = async () => {
+ await waitFor(() => mockDatabaseUpdateFunction.mock.calls[0][0], {
+ timeout: DebounceWaitTime,
+ });
+ await waitFor(() => mockDatabaseUpdateFunction.mock.results[0].value);
+ };
+
+ const expectDatabaseUpdateToHaveCompleted = async () => {
+ await waitFor(
+ () => expect(mockDatabaseUpdateFunction).toHaveBeenCalledTimes(1),
+ {
+ timeout: DebounceWaitTime,
+ },
+ );
+ await waitFor(() =>
+ expect(
+ mockDatabaseUpdateFunction.mock.results[0].value,
+ ).resolves.toBeUndefined(),
+ );
+ };
+
async function setup(
resumeIdParameter,
waitForLoadingScreenToDisappear = true,
- waitForDatabaseUpdateFunctionToHaveCompleted = true,
+ waitForDatabaseUpdateToHaveCompleted = true,
) {
FirebaseStub.database().initializeData();
@@ -78,29 +99,18 @@ describe('Builder', () => {
);
}
- if (waitForDatabaseUpdateFunctionToHaveCompleted) {
- await waitFor(() => mockDatabaseUpdateFunction.mock.calls[0][0], {
- timeout: DebounceWaitTime,
- });
- await waitFor(() => mockDatabaseUpdateFunction.mock.results[0].value);
+ if (waitForDatabaseUpdateToHaveCompleted) {
+ await fnWaitForDatabaseUpdateToHaveCompleted();
mockDatabaseUpdateFunction.mockClear();
}
}
describe('handles errors', () => {
describe('if resume does not exist', () => {
- const waitForNavigateFunctionToHaveCompleted = async () => {
- await waitFor(() => mockNavigateFunction.mock.results[0].value);
- };
-
beforeEach(async () => {
await setup('xxxxxx', false, false);
});
- afterEach(async () => {
- await waitForNavigateFunctionToHaveCompleted();
- });
-
it('navigates to Dashboard and displays notification', async () => {
await waitFor(() =>
expect(mockNavigateFunction).toHaveBeenCalledTimes(1),
@@ -110,6 +120,12 @@ describe('Builder', () => {
await waitFor(() => {
expect(screen.getByRole('alert')).toBeInTheDocument();
});
+
+ await waitFor(() =>
+ expect(
+ mockNavigateFunction.mock.results[0].value,
+ ).resolves.toBeUndefined(),
+ );
});
});
});
@@ -157,12 +173,7 @@ describe('Builder', () => {
const languageStorageItem = localStorage.getItem(languageStorageItemKey);
expect(languageStorageItem).toBe(italianLanguageCode);
- await waitFor(
- () => expect(mockDatabaseUpdateFunction).toHaveBeenCalledTimes(1),
- {
- timeout: DebounceWaitTime,
- },
- );
+ await expectDatabaseUpdateToHaveCompleted();
const mockDatabaseUpdateFunctionCallArgument =
mockDatabaseUpdateFunction.mock.calls[0][0];
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
@@ -172,11 +183,6 @@ describe('Builder', () => {
expect(
mockDatabaseUpdateFunctionCallArgument.updatedAt,
).toBeGreaterThanOrEqual(now);
- await waitFor(() =>
- expect(
- mockDatabaseUpdateFunction.mock.results[0].value,
- ).resolves.toBeUndefined(),
- );
});
afterEach(() => {
@@ -199,12 +205,7 @@ describe('Builder', () => {
expect(input.value).toBe(newInputValue);
- await waitFor(
- () => expect(mockDatabaseUpdateFunction).toHaveBeenCalledTimes(1),
- {
- timeout: DebounceWaitTime,
- },
- );
+ await expectDatabaseUpdateToHaveCompleted();
const mockDatabaseUpdateFunctionCallArgument =
mockDatabaseUpdateFunction.mock.calls[0][0];
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
@@ -214,11 +215,6 @@ describe('Builder', () => {
expect(
mockDatabaseUpdateFunctionCallArgument.updatedAt,
).toBeGreaterThanOrEqual(now);
- await waitFor(() =>
- expect(
- mockDatabaseUpdateFunction.mock.results[0].value,
- ).resolves.toBeUndefined(),
- );
});
});
@@ -227,14 +223,14 @@ describe('Builder', () => {
await setup(DatabaseConstants.demoStateResume1Id, false, false);
});
- afterEach(async () => {
+ it('renders loading screen', async () => {
+ expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
+
await waitForElementToBeRemoved(() =>
screen.getByTestId(loadingScreenTestId),
);
- });
- it('renders loading screen', () => {
- expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
+ await fnWaitForDatabaseUpdateToHaveCompleted();
});
});
});
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index 385493b92..26b8bccc1 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -24,13 +24,23 @@ import Wrapper from '../../../components/shared/Wrapper';
import Dashboard from '../dashboard';
describe('Dashboard', () => {
- let resumes = null;
+ let userResumes = null;
const user = DatabaseConstants.user1;
+ const waitForResumeToBeRenderedInPreview = async (resume) => {
+ await screen.findByText(resume.name);
+ };
+
+ const expectResumeToBeRenderedInPreview = async (resume) => {
+ await waitFor(() => {
+ expect(screen.getByText(resume.name)).toBeInTheDocument();
+ });
+ };
+
async function setup(waitForLoadingScreenToDisappear = true) {
FirebaseStub.database().initializeData();
- resumes = (
+ userResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
@@ -83,20 +93,10 @@ describe('Dashboard', () => {
});
it('preview of user resumes', async () => {
- expect(Object.keys(resumes)).toHaveLength(2);
+ expect(Object.keys(userResumes)).toHaveLength(2);
- expect(Object.values(resumes)[0].user).toEqual(user.uid);
- await waitFor(() => {
- expect(
- screen.getByText(Object.values(resumes)[0].name),
- ).toBeInTheDocument();
- });
- expect(Object.values(resumes)[1].user).toEqual(user.uid);
- await waitFor(() => {
- expect(
- screen.getByText(Object.values(resumes)[1].name),
- ).toBeInTheDocument();
- });
+ await expectResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
+ await expectResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
});
});
@@ -106,14 +106,25 @@ describe('Dashboard', () => {
let undeletedResume = null;
let resumeToDeleteId = null;
- const waitForDatabaseRemoveFunctionToHaveCompleted = async () => {
+ const waitForDatabaseRemoveToHaveCompleted = async () => {
await waitFor(() => mockDatabaseRemoveFunction.mock.results[0].value);
};
+ const expectDatabaseRemoveToHaveCompleted = async () => {
+ await waitFor(() =>
+ expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
+ );
+ await waitFor(() =>
+ expect(
+ mockDatabaseRemoveFunction.mock.results[0].value,
+ ).resolves.toBeUndefined(),
+ );
+ };
+
beforeEach(async () => {
await setup();
- [resumeToDelete, undeletedResume] = Object.values(resumes);
+ [resumeToDelete, undeletedResume] = Object.values(userResumes);
resumeToDeleteId = resumeToDelete.id;
mockDatabaseRemoveFunction = jest.spyOn(
@@ -123,13 +134,9 @@ describe('Dashboard', () => {
'remove',
);
- let resumeToDeleteMenuToggle = null;
- await waitFor(() => {
- resumeToDeleteMenuToggle = screen.queryByTestId(
- `${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
- );
- return resumeToDeleteMenuToggle ? Promise.resolve() : Promise.reject();
- });
+ const resumeToDeleteMenuToggle = await screen.findByTestId(
+ `${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
+ );
fireEvent.click(resumeToDeleteMenuToggle);
const menuItems = screen.getAllByRole('menuitem');
@@ -143,32 +150,28 @@ describe('Dashboard', () => {
fireEvent.click(deleteMenuItem);
});
- afterEach(async () => {
- await waitForDatabaseRemoveFunctionToHaveCompleted();
- });
-
it('removes it from database and preview', async () => {
- await waitFor(() =>
- expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
- );
-
- await waitForDatabaseRemoveFunctionToHaveCompleted();
+ await expectDatabaseRemoveToHaveCompleted();
await waitFor(() =>
expect(screen.queryByText(resumeToDelete.name)).toBeNull(),
);
- expect(screen.getByText(undeletedResume.name)).toBeInTheDocument();
+ await expectResumeToBeRenderedInPreview(undeletedResume);
});
it('displays notification', async () => {
await waitFor(() => {
expect(screen.getByRole('alert')).toBeInTheDocument();
});
+
+ await waitForDatabaseRemoveToHaveCompleted();
});
- it('closes menu', () => {
+ it('closes menu', async () => {
const menuItems = screen.queryAllByRole('menuitem');
expect(menuItems).toHaveLength(0);
+
+ await waitForDatabaseRemoveToHaveCompleted();
});
});
@@ -177,14 +180,15 @@ describe('Dashboard', () => {
await setup(false);
});
- afterEach(async () => {
+ it('renders loading screen', async () => {
+ expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
+
await waitForElementToBeRemoved(() =>
screen.getByTestId(loadingScreenTestId),
);
- });
- it('renders loading screen', () => {
- expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
+ await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
+ await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
});
});
});
From 74335a177193c0222ffdf69edcebfbf926a2a546 Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Sat, 23 Jan 2021 12:21:02 +0100
Subject: [PATCH 13/14] Builder and Dashboard unit tests: fine tuning of
assertions related to toast/notification
---
src/pages/app/__tests__/builder.test.js | 11 ++++++++---
src/pages/app/__tests__/dashboard.test.js | 11 ++++++++---
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index 4615e5aa5..dea1dfc4d 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -2,6 +2,7 @@ import { navigate as mockNavigateFunction } from 'gatsby';
import React from 'react';
import {
fireEvent,
+ getByText,
render,
screen,
waitFor,
@@ -117,9 +118,13 @@ describe('Builder', () => {
);
expect(mockNavigateFunction).toHaveBeenCalledWith('/app/dashboard');
- await waitFor(() => {
- expect(screen.getByRole('alert')).toBeInTheDocument();
- });
+ const notification = await screen.findByRole('alert');
+ expect(
+ getByText(
+ notification,
+ /The resume you were looking for does not exist anymore/i,
+ ),
+ ).toBeInTheDocument();
await waitFor(() =>
expect(
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index 26b8bccc1..9a6b25231 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -1,6 +1,7 @@
import React from 'react';
import {
fireEvent,
+ getByText,
queryByText,
render,
screen,
@@ -160,9 +161,13 @@ describe('Dashboard', () => {
});
it('displays notification', async () => {
- await waitFor(() => {
- expect(screen.getByRole('alert')).toBeInTheDocument();
- });
+ const notification = await screen.findByRole('alert');
+ expect(
+ getByText(
+ notification,
+ new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
+ ),
+ ).toBeInTheDocument();
await waitForDatabaseRemoveToHaveCompleted();
});
From c01be98cfcc6e097f1ed814567696fad54c6732d Mon Sep 17 00:00:00 2001
From: gianantoniopini <63844628+gianantoniopini@users.noreply.github.com>
Date: Sat, 23 Jan 2021 14:05:37 +0100
Subject: [PATCH 14/14] Builder: added unit test for resume in initial state
---
src/pages/app/__tests__/builder.test.js | 18 ++++++++++++++++++
src/pages/app/__tests__/dashboard.test.js | 1 +
2 files changed, 19 insertions(+)
diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js
index dea1dfc4d..f6ad40f8a 100644
--- a/src/pages/app/__tests__/builder.test.js
+++ b/src/pages/app/__tests__/builder.test.js
@@ -125,6 +125,7 @@ describe('Builder', () => {
/The resume you were looking for does not exist anymore/i,
),
).toBeInTheDocument();
+ fireEvent.click(notification);
await waitFor(() =>
expect(
@@ -238,4 +239,21 @@ describe('Builder', () => {
await fnWaitForDatabaseUpdateToHaveCompleted();
});
});
+
+ describe('with resume in initial state', () => {
+ beforeEach(async () => {
+ await setup(DatabaseConstants.initialStateResumeId, false, false);
+ });
+
+ it('displays load demo data notification', async () => {
+ const notification = await screen.findByRole('alert');
+ expect(
+ getByText(
+ notification,
+ /Not sure where to begin\? Try loading demo data/i,
+ ),
+ ).toBeInTheDocument();
+ fireEvent.click(notification);
+ });
+ });
});
diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js
index 9a6b25231..eede7d67a 100644
--- a/src/pages/app/__tests__/dashboard.test.js
+++ b/src/pages/app/__tests__/dashboard.test.js
@@ -168,6 +168,7 @@ describe('Dashboard', () => {
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
),
).toBeInTheDocument();
+ fireEvent.click(notification);
await waitForDatabaseRemoveToHaveCompleted();
});