Dashboard page: unit tests separated in different files

This commit is contained in:
gianantoniopini
2021-02-01 18:00:52 +01:00
parent 5ee077dac5
commit e39026c8b4
6 changed files with 583 additions and 483 deletions

View File

@ -0,0 +1,151 @@
import {
fireEvent,
getByText,
screen,
waitFor,
waitForElementToBeRemoved,
} from '@testing-library/react';
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import { createResumeButtonDataTestId } from '../../../components/dashboard/CreateResume';
import {
waitForResumeToBeRenderedInPreview,
expectResumeToBeRenderedInPreview,
waitForModalWindowToHaveBeenClosed,
dismissNotification,
unsplashPhotoResponseUrl,
setupWithFetchMockAndWaitForLoadingScreenToDisappear,
} from './helpers/dashboard';
const tooShortResumeName = 'CV 1';
const validResumeName = 'Resume for SW development roles';
async function setup() {
const user = DatabaseConstants.user1;
await setupWithFetchMockAndWaitForLoadingScreenToDisappear(user);
const dashboardCreateResumeButton = await screen.findByTestId(
createResumeButtonDataTestId,
);
fireEvent.click(dashboardCreateResumeButton);
const nameTextBox = screen.getByRole('textbox', { name: /name/i });
return { user, nameTextBox };
}
async function setupAndSubmit(resumeName) {
const { user, nameTextBox } = await setup();
fireEvent.change(nameTextBox, {
target: { value: resumeName },
});
const modalCreateResumeButton = screen.getByRole('button', {
name: /create resume/i,
});
fireEvent.click(modalCreateResumeButton);
return { user };
}
describe('with invalid name', () => {
it('displays validation error', async () => {
const { nameTextBox } = await setup();
fireEvent.change(nameTextBox, { target: { value: tooShortResumeName } });
fireEvent.blur(nameTextBox);
await waitFor(() =>
expect(
screen.getByText(/Please enter at least 5 characters/i),
).toBeInTheDocument(),
);
});
it('displays notification', async () => {
await setupAndSubmit(tooShortResumeName);
const notification = await screen.findByRole('alert');
expect(
getByText(
notification,
/You might need to fill up all the required fields/i,
),
).toBeInTheDocument();
dismissNotification(notification);
});
});
describe('with valid name', () => {
it('renders loading message', async () => {
await setupAndSubmit(validResumeName);
await waitFor(() =>
expect(
screen.getByRole('button', {
name: /loading/i,
}),
).toBeInTheDocument(),
);
await waitForElementToBeRemoved(() =>
screen.getByRole('button', {
name: /loading/i,
}),
);
await waitForModalWindowToHaveBeenClosed();
await waitForResumeToBeRenderedInPreview(validResumeName);
});
it('closes modal window', async () => {
await setupAndSubmit(validResumeName);
await waitFor(() =>
expect(waitForModalWindowToHaveBeenClosed()).resolves.toBeUndefined(),
);
await waitForResumeToBeRenderedInPreview(validResumeName);
});
it('renders created resume in preview', async () => {
await setupAndSubmit(validResumeName);
await waitForModalWindowToHaveBeenClosed();
await waitFor(() =>
expect(
expectResumeToBeRenderedInPreview(validResumeName),
).resolves.toBeUndefined(),
);
});
it('adds resume in initial state to database', async () => {
const now = new Date().getTime();
const { user } = await setupAndSubmit(validResumeName);
await waitForModalWindowToHaveBeenClosed();
await waitForResumeToBeRenderedInPreview(validResumeName);
const actualUserResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
expect(Object.values(actualUserResumes)).toHaveLength(3);
const actualUserResumesFiltered = Object.values(actualUserResumes).filter(
(resume) => resume.name === validResumeName,
);
expect(actualUserResumesFiltered).toHaveLength(1);
const createdResume = actualUserResumesFiltered[0];
expect(createdResume.id).toBeTruthy();
expect(createdResume.preview).toBeTruthy();
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
expect(createdResume.createdAt).toBeTruthy();
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
});
});

View File

@ -0,0 +1,121 @@
import {
fireEvent,
getByText,
queryByText,
screen,
waitFor,
} from '@testing-library/react';
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
import {
setupAndWaitForLoadingScreenToDisappear,
waitForResumeToDisappearFromPreview,
expectResumeToBeRenderedInPreview,
dismissNotification,
findAndDismissNotification,
} from './helpers/dashboard';
const waitForDatabaseRemoveToHaveCompleted = async (
mockDatabaseRemoveFunction,
) => {
await waitFor(() => mockDatabaseRemoveFunction.mock.results[0].value);
};
const expectDatabaseRemoveToHaveCompleted = async (
mockDatabaseRemoveFunction,
) => {
await waitFor(() =>
expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
);
await waitFor(() =>
expect(
mockDatabaseRemoveFunction.mock.results[0].value,
).resolves.toBeUndefined(),
);
};
async function setup() {
const userResumes = await setupAndWaitForLoadingScreenToDisappear(
DatabaseConstants.user1,
);
const [resumeToDelete] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
);
const resumeToDeleteId = resumeToDelete.id;
const [undeletedResume] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.initialStateResumeId,
);
const mockDatabaseRemoveFunction = jest.spyOn(
FirebaseStub.database().ref(
`${DatabaseConstants.resumesPath}/${resumeToDeleteId}`,
),
'remove',
);
const resumeToDeleteMenuToggle = await screen.findByTestId(
`${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);
return { resumeToDelete, undeletedResume, mockDatabaseRemoveFunction };
}
it('removes resume from database and preview', async () => {
const {
resumeToDelete,
undeletedResume,
mockDatabaseRemoveFunction,
} = await setup();
await findAndDismissNotification();
await expectDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
await waitFor(() =>
expect(
waitForResumeToDisappearFromPreview(resumeToDelete.name),
).resolves.toBeUndefined(),
);
await expectResumeToBeRenderedInPreview(undeletedResume.name);
});
it('displays notification', async () => {
const { resumeToDelete, mockDatabaseRemoveFunction } = await setup();
const notification = await screen.findByRole('alert');
expect(
getByText(
notification,
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
),
).toBeInTheDocument();
dismissNotification(notification);
await waitForDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
});
it('closes menu', async () => {
const { resumeToDelete, mockDatabaseRemoveFunction } = await setup();
const menuItems = screen.queryAllByRole('menuitem');
expect(menuItems).toHaveLength(0);
await findAndDismissNotification();
await waitForDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
});

View File

@ -0,0 +1,103 @@
import {
fireEvent,
queryByText,
screen,
waitFor,
} from '@testing-library/react';
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
import {
setupWithFetchMockAndWaitForLoadingScreenToDisappear,
waitForResumeToBeRenderedInPreview,
expectResumeToBeRenderedInPreview,
unsplashPhotoResponseUrl,
} from './helpers/dashboard';
async function setup() {
const user = DatabaseConstants.user1;
const userResumes = await setupWithFetchMockAndWaitForLoadingScreenToDisappear(
user,
);
const [resumeToDuplicate] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
);
const resumeToDuplicateId = resumeToDuplicate.id;
const duplicateResumeName = `${resumeToDuplicate.name} Copy`;
const resumeToDuplicateMenuToggle = await screen.findByTestId(
`${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDuplicateId}`,
);
fireEvent.click(resumeToDuplicateMenuToggle);
const menuItems = screen.getAllByRole('menuitem');
let duplicateMenuItem = null;
for (let index = 0; index < menuItems.length; index++) {
if (queryByText(menuItems[index], /duplicate/i)) {
duplicateMenuItem = menuItems[index];
break;
}
}
fireEvent.click(duplicateMenuItem);
return { user, resumeToDuplicate, duplicateResumeName };
}
it('renders duplicate resume in preview', async () => {
const { duplicateResumeName } = await setup();
await waitFor(() =>
expect(
expectResumeToBeRenderedInPreview(duplicateResumeName),
).resolves.toBeUndefined(),
);
});
it('adds duplicate resume to database', async () => {
const now = new Date().getTime();
const { user, resumeToDuplicate, duplicateResumeName } = await setup();
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
const actualUserResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
expect(Object.values(actualUserResumes)).toHaveLength(3);
const actualUserResumesFiltered = Object.values(actualUserResumes).filter(
(resume) =>
resume.name === duplicateResumeName && resume.id !== resumeToDuplicate.id,
);
expect(actualUserResumesFiltered).toHaveLength(1);
const createdResume = actualUserResumesFiltered[0];
expect(createdResume.id).toBeTruthy();
expect(createdResume.preview).toBeTruthy();
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
expect(createdResume.createdAt).toBeTruthy();
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
const expectedResume = {
...resumeToDuplicate,
id: createdResume.id,
name: createdResume.name,
preview: createdResume.preview,
createdAt: createdResume.createdAt,
updatedAt: createdResume.updatedAt,
};
expect(createdResume).toEqual(expectedResume);
});
it('closes menu', async () => {
const { duplicateResumeName } = await setup();
const menuItems = screen.queryAllByRole('menuitem');
expect(menuItems).toHaveLength(0);
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
});

View File

@ -0,0 +1,50 @@
import { screen, waitFor } from '@testing-library/react';
import { DatabaseConstants } from 'gatsby-plugin-firebase';
import { createResumeButtonDataTestId } from '../../../components/dashboard/CreateResume';
import setup, {
setupAndWaitForLoadingScreenToDisappear,
expectResumeToBeRenderedInPreview,
expectLoadingScreenToBeRendered,
waitForLoadingScreenToDisappear,
} from './helpers/dashboard';
const user = DatabaseConstants.user1;
it('renders loading screen', async () => {
await setup(user);
expect(expectLoadingScreenToBeRendered()).toBeUndefined();
await waitForLoadingScreenToDisappear();
});
it('renders document title', async () => {
await setupAndWaitForLoadingScreenToDisappear(user);
await waitFor(() => {
expect(document.title).toEqual('Dashboard | Reactive Resume');
});
});
it('renders create resume', async () => {
await setupAndWaitForLoadingScreenToDisappear(user);
await waitFor(() => {
expect(screen.getByText(/create resume/i)).toBeInTheDocument();
});
await waitFor(() => {
expect(
screen.getByTestId(createResumeButtonDataTestId),
).toBeInTheDocument();
});
});
it('renders preview of user resumes', async () => {
const userResumes = await setupAndWaitForLoadingScreenToDisappear(user);
expect(Object.keys(userResumes)).toHaveLength(2);
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[0].name);
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[1].name);
});

View File

@ -1,483 +0,0 @@
import React from 'react';
import {
fireEvent,
getByText,
queryByText,
render,
screen,
waitFor,
waitForElementToBeRemoved,
} from '@testing-library/react';
import fetchMock from 'jest-fetch-mock';
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import '../../../i18n/index';
import '../../../utils/dayjs';
import { unsplashPhotoRequestUrl, delay } from '../../../utils/index';
import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
import { createResumeButtonDataTestId } from '../../../components/dashboard/CreateResume';
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
import { SettingsProvider } from '../../../contexts/SettingsContext';
import { ModalProvider } from '../../../contexts/ModalContext';
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', () => {
let userResumes = null;
const user = DatabaseConstants.user1;
const unsplashPhotoResponseUrl = 'https://test-url-123456789.com';
const waitForResumeToBeRenderedInPreview = async (resumeName) => {
await screen.findByText(resumeName);
};
const expectResumeToBeRenderedInPreview = async (resumeName) => {
await waitFor(() => {
expect(screen.getByText(resumeName)).toBeInTheDocument();
});
};
const waitForModalWindowToHaveBeenClosed = async () => {
await waitForElementToBeRemoved(() =>
screen.getByRole('textbox', { name: /name/i }),
);
};
const dismissNotification = (notification) => {
fireEvent.click(notification);
};
const findAndDismissNotification = async () => {
const notification = await screen.findByRole('alert');
dismissNotification(notification);
};
const waitForLoadingScreenToDisappearFn = async () => {
await waitForElementToBeRemoved(() =>
screen.getByTestId(loadingScreenTestId),
);
};
const setupFetchMockFn = () => {
fetchMock.resetMocks();
fetchMock.mockImplementationOnce(async (input) => {
await delay(100);
if (input === unsplashPhotoRequestUrl) {
return {
url: unsplashPhotoResponseUrl,
};
}
throw new Error('Unsupported input.');
});
};
async function setup(
waitForLoadingScreenToDisappear = true,
setupFetchMock = false,
) {
if (setupFetchMock) {
setupFetchMockFn();
}
FirebaseStub.database().initializeData();
userResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
FirebaseStub.auth().signInAnonymously();
render(
<SettingsProvider>
<ModalProvider>
<UserProvider>
<DatabaseProvider>
<ResumeProvider>
<StorageProvider>
<Wrapper>
<Dashboard user={user} />
</Wrapper>
</StorageProvider>
</ResumeProvider>
</DatabaseProvider>
</UserProvider>
</ModalProvider>
</SettingsProvider>,
);
if (waitForLoadingScreenToDisappear) {
await waitForLoadingScreenToDisappearFn();
}
}
describe('renders', () => {
beforeEach(async () => {
await setup();
});
it('document title', async () => {
await waitFor(() => {
expect(document.title).toEqual('Dashboard | Reactive Resume');
});
});
it('create resume', async () => {
await waitFor(() => {
expect(screen.getByText(/create resume/i)).toBeInTheDocument();
});
await waitFor(() => {
expect(
screen.getByTestId(createResumeButtonDataTestId),
).toBeInTheDocument();
});
});
it('preview of user resumes', async () => {
expect(Object.keys(userResumes)).toHaveLength(2);
await expectResumeToBeRenderedInPreview(
Object.values(userResumes)[0].name,
);
await expectResumeToBeRenderedInPreview(
Object.values(userResumes)[1].name,
);
});
});
describe('when resume is created', () => {
let nameTextBox = null;
beforeEach(async () => {
await setup(true, true);
const dashboardCreateResumeButton = await screen.findByTestId(
createResumeButtonDataTestId,
);
fireEvent.click(dashboardCreateResumeButton);
nameTextBox = screen.getByRole('textbox', { name: /name/i });
});
describe('with name shorter than 5 characters', () => {
it('displays validation error and notification', async () => {
fireEvent.change(nameTextBox, { target: { value: 'CV 1' } });
fireEvent.blur(nameTextBox);
await waitFor(() =>
expect(
screen.getByText(/Please enter at least 5 characters/i),
).toBeInTheDocument(),
);
const modalCreateResumeButton = screen.getByRole('button', {
name: /create resume/i,
});
fireEvent.click(modalCreateResumeButton);
const notification = await screen.findByRole('alert');
expect(
getByText(
notification,
/You might need to fill up all the required fields/i,
),
).toBeInTheDocument();
dismissNotification(notification);
});
});
describe('with valid name', () => {
const resumeName = 'Resume for SW development roles';
let now = 0;
beforeEach(() => {
now = new Date().getTime();
fireEvent.change(nameTextBox, {
target: { value: resumeName },
});
const modalCreateResumeButton = screen.getByRole('button', {
name: /create resume/i,
});
fireEvent.click(modalCreateResumeButton);
});
it('renders loading message', async () => {
await waitFor(() =>
expect(
screen.getByRole('button', {
name: /loading/i,
}),
).toBeInTheDocument(),
);
await waitForElementToBeRemoved(() =>
screen.getByRole('button', {
name: /loading/i,
}),
);
await waitForModalWindowToHaveBeenClosed();
await waitForResumeToBeRenderedInPreview(resumeName);
});
it('closes modal window', async () => {
await waitFor(() =>
expect(waitForModalWindowToHaveBeenClosed()).resolves.toBeUndefined(),
);
await waitForResumeToBeRenderedInPreview(resumeName);
});
it('renders created resume in preview', async () => {
await waitForModalWindowToHaveBeenClosed();
await waitFor(() =>
expect(
expectResumeToBeRenderedInPreview(resumeName),
).resolves.toBeUndefined(),
);
});
it('adds resume in initial state to database', async () => {
await waitForModalWindowToHaveBeenClosed();
await waitForResumeToBeRenderedInPreview(resumeName);
const actualUserResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
expect(Object.values(actualUserResumes)).toHaveLength(3);
const actualUserResumesFiltered = Object.values(
actualUserResumes,
).filter((resume) => resume.name === resumeName);
expect(actualUserResumesFiltered).toHaveLength(1);
const createdResume = actualUserResumesFiltered[0];
expect(createdResume.id).toBeTruthy();
expect(createdResume.preview).toBeTruthy();
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
expect(createdResume.createdAt).toBeTruthy();
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
});
});
});
describe('when resume is deleted', () => {
let mockDatabaseRemoveFunction = null;
let resumeToDelete = null;
let undeletedResume = null;
let resumeToDeleteId = null;
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(),
);
};
const waitForResumeToDisappearFromPreview = async (resumeName) => {
await waitFor(() =>
screen.queryByText(resumeName) ? Promise.reject() : Promise.resolve(),
);
};
beforeEach(async () => {
await setup();
[resumeToDelete] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
);
resumeToDeleteId = resumeToDelete.id;
[undeletedResume] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.initialStateResumeId,
);
mockDatabaseRemoveFunction = jest.spyOn(
FirebaseStub.database().ref(
`${DatabaseConstants.resumesPath}/${resumeToDeleteId}`,
),
'remove',
);
const resumeToDeleteMenuToggle = await screen.findByTestId(
`${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 findAndDismissNotification();
await expectDatabaseRemoveToHaveCompleted();
await waitFor(() =>
expect(
waitForResumeToDisappearFromPreview(resumeToDelete.name),
).resolves.toBeUndefined(),
);
await expectResumeToBeRenderedInPreview(undeletedResume.name);
});
it('displays notification', async () => {
const notification = await screen.findByRole('alert');
expect(
getByText(
notification,
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
),
).toBeInTheDocument();
dismissNotification(notification);
await waitForDatabaseRemoveToHaveCompleted();
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
});
it('closes menu', async () => {
const menuItems = screen.queryAllByRole('menuitem');
expect(menuItems).toHaveLength(0);
await findAndDismissNotification();
await waitForDatabaseRemoveToHaveCompleted();
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
});
});
describe('when resume is duplicated', () => {
let resumeToDuplicate = null;
let resumeToDuplicateId = null;
let duplicateResumeName = null;
let now = 0;
beforeEach(async () => {
await setup(true, true);
now = new Date().getTime();
[resumeToDuplicate] = Object.values(userResumes).filter(
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
);
resumeToDuplicateId = resumeToDuplicate.id;
duplicateResumeName = `${resumeToDuplicate.name} Copy`;
const resumeToDuplicateMenuToggle = await screen.findByTestId(
`${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDuplicateId}`,
);
fireEvent.click(resumeToDuplicateMenuToggle);
const menuItems = screen.getAllByRole('menuitem');
let duplicateMenuItem = null;
for (let index = 0; index < menuItems.length; index++) {
if (queryByText(menuItems[index], /duplicate/i)) {
duplicateMenuItem = menuItems[index];
break;
}
}
fireEvent.click(duplicateMenuItem);
});
it('renders duplicate resume in preview', async () => {
await waitFor(() =>
expect(
expectResumeToBeRenderedInPreview(duplicateResumeName),
).resolves.toBeUndefined(),
);
});
it('adds duplicate resume to database', async () => {
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
const actualUserResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
expect(Object.values(actualUserResumes)).toHaveLength(3);
const actualUserResumesFiltered = Object.values(actualUserResumes).filter(
(resume) =>
resume.name === duplicateResumeName &&
resume.id !== resumeToDuplicateId,
);
expect(actualUserResumesFiltered).toHaveLength(1);
const createdResume = actualUserResumesFiltered[0];
expect(createdResume.id).toBeTruthy();
expect(createdResume.preview).toBeTruthy();
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
expect(createdResume.createdAt).toBeTruthy();
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
const expectedResume = {
...resumeToDuplicate,
id: createdResume.id,
name: createdResume.name,
preview: createdResume.preview,
createdAt: createdResume.createdAt,
updatedAt: createdResume.updatedAt,
};
expect(createdResume).toEqual(expectedResume);
});
it('closes menu', async () => {
const menuItems = screen.queryAllByRole('menuitem');
expect(menuItems).toHaveLength(0);
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
});
});
describe('while loading', () => {
beforeEach(async () => {
await setup(false);
});
it('renders loading screen', async () => {
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
await waitForLoadingScreenToDisappearFn();
await waitForResumeToBeRenderedInPreview(
Object.values(userResumes)[0].name,
);
await waitForResumeToBeRenderedInPreview(
Object.values(userResumes)[1].name,
);
});
});
});

View File

@ -0,0 +1,158 @@
import React from 'react';
import {
fireEvent,
render,
screen,
waitFor,
waitForElementToBeRemoved,
} from '@testing-library/react';
import fetchMock from 'jest-fetch-mock';
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
import '../../../../i18n/index';
import '../../../../utils/dayjs';
import { dataTestId as loadingScreenTestId } from '../../../../components/router/LoadingScreen';
import { unsplashPhotoRequestUrl, delay } from '../../../../utils/index';
import { SettingsProvider } from '../../../../contexts/SettingsContext';
import { ModalProvider } from '../../../../contexts/ModalContext';
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';
const waitForResumeToBeRenderedInPreview = async (resumeName) => {
await screen.findByText(resumeName);
};
const waitForResumeToDisappearFromPreview = async (resumeName) => {
await waitFor(() =>
screen.queryByText(resumeName) ? Promise.reject() : Promise.resolve(),
);
};
const expectResumeToBeRenderedInPreview = async (resumeName) => {
await waitFor(() => {
expect(screen.getByText(resumeName)).toBeInTheDocument();
});
};
const waitForModalWindowToHaveBeenClosed = async () => {
await waitForElementToBeRemoved(() =>
screen.getByRole('textbox', { name: /name/i }),
);
};
const dismissNotification = (notification) => {
fireEvent.click(notification);
};
const findAndDismissNotification = async () => {
const notification = await screen.findByRole('alert');
dismissNotification(notification);
};
const expectLoadingScreenToBeRendered = () => {
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
};
const waitForLoadingScreenToDisappearFn = async () => {
await waitForElementToBeRemoved(() =>
screen.getByTestId(loadingScreenTestId),
);
};
const unsplashPhotoResponseUrl = 'https://test-url-123456789.com';
const setupFetchMockFn = () => {
fetchMock.resetMocks();
fetchMock.mockImplementationOnce(async (input) => {
await delay(100);
if (input === unsplashPhotoRequestUrl) {
return {
url: unsplashPhotoResponseUrl,
};
}
throw new Error('Unsupported input.');
});
};
// eslint-disable-next-line no-underscore-dangle
async function _setup(user, waitForLoadingScreenToDisappear, setupFetchMock) {
if (setupFetchMock) {
setupFetchMockFn();
}
FirebaseStub.database().initializeData();
const userResumes = (
await FirebaseStub.database()
.ref(DatabaseConstants.resumesPath)
.orderByChild('user')
.equalTo(user.uid)
.once('value')
).val();
FirebaseStub.auth().signInAnonymously();
render(
<SettingsProvider>
<ModalProvider>
<UserProvider>
<DatabaseProvider>
<ResumeProvider>
<StorageProvider>
<Wrapper>
<Dashboard user={user} />
</Wrapper>
</StorageProvider>
</ResumeProvider>
</DatabaseProvider>
</UserProvider>
</ModalProvider>
</SettingsProvider>,
);
if (waitForLoadingScreenToDisappear) {
await waitForLoadingScreenToDisappearFn();
}
return userResumes;
}
async function setup(user) {
const userResumes = await _setup(user, false, false);
return userResumes;
}
async function setupAndWaitForLoadingScreenToDisappear(user) {
const userResumes = await _setup(user, true, false);
return userResumes;
}
async function setupWithFetchMockAndWaitForLoadingScreenToDisappear(user) {
const userResumes = await _setup(user, true, true);
return userResumes;
}
export default setup;
export {
setupAndWaitForLoadingScreenToDisappear,
setupWithFetchMockAndWaitForLoadingScreenToDisappear,
waitForResumeToBeRenderedInPreview,
waitForResumeToDisappearFromPreview,
expectResumeToBeRenderedInPreview,
waitForModalWindowToHaveBeenClosed,
dismissNotification,
findAndDismissNotification,
expectLoadingScreenToBeRendered,
waitForLoadingScreenToDisappearFn as waitForLoadingScreenToDisappear,
unsplashPhotoResponseUrl,
};