mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 08:13:49 +10:00
284 lines
8.2 KiB
JavaScript
284 lines
8.2 KiB
JavaScript
import React from 'react';
|
|
import {
|
|
fireEvent,
|
|
getByText,
|
|
queryByText,
|
|
render,
|
|
screen,
|
|
waitFor,
|
|
waitForElementToBeRemoved,
|
|
} from '@testing-library/react';
|
|
|
|
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
|
|
|
import '../../../i18n/index';
|
|
import '../../../utils/dayjs';
|
|
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 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();
|
|
|
|
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 waitForElementToBeRemoved(() =>
|
|
screen.getByTestId(loadingScreenTestId),
|
|
);
|
|
}
|
|
}
|
|
|
|
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();
|
|
});
|
|
});
|
|
|
|
it('preview of user resumes', async () => {
|
|
expect(Object.keys(userResumes)).toHaveLength(2);
|
|
|
|
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
|
|
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
|
|
});
|
|
});
|
|
|
|
describe('when resume is created', () => {
|
|
let nameTextBox = null;
|
|
|
|
const waitForModalToHaveBeenClosed = async () => {
|
|
await waitFor(() =>
|
|
screen.queryByRole('textbox', { name: /name/i })
|
|
? Promise.reject()
|
|
: Promise.resolve(),
|
|
);
|
|
};
|
|
|
|
beforeEach(async () => {
|
|
await setup();
|
|
|
|
fetch.resetMocks();
|
|
fetch.mockReturnValueOnce({ url: 'https://test-url-123456789.com' });
|
|
|
|
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.focusOut(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();
|
|
fireEvent.click(notification);
|
|
});
|
|
});
|
|
|
|
describe('with valid name', () => {
|
|
it('renders loading message', async () => {
|
|
fireEvent.change(nameTextBox, {
|
|
target: { value: 'Resume for SW development roles' },
|
|
});
|
|
|
|
const modalCreateResumeButton = screen.getByRole('button', {
|
|
name: /create resume/i,
|
|
});
|
|
fireEvent.click(modalCreateResumeButton);
|
|
|
|
expect(
|
|
screen.getByRole('button', {
|
|
name: /loading/i,
|
|
}),
|
|
).toBeInTheDocument();
|
|
await waitFor(() =>
|
|
expect(
|
|
screen.queryByRole('button', {
|
|
name: /loading/i,
|
|
}),
|
|
).toBeNull(),
|
|
);
|
|
|
|
await waitForModalToHaveBeenClosed();
|
|
});
|
|
});
|
|
});
|
|
|
|
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(),
|
|
);
|
|
};
|
|
|
|
beforeEach(async () => {
|
|
await setup();
|
|
|
|
[resumeToDelete, undeletedResume] = Object.values(userResumes);
|
|
resumeToDeleteId = resumeToDelete.id;
|
|
|
|
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 expectDatabaseRemoveToHaveCompleted();
|
|
|
|
await waitFor(() =>
|
|
expect(screen.queryByText(resumeToDelete.name)).toBeNull(),
|
|
);
|
|
await expectResumeToBeRenderedInPreview(undeletedResume);
|
|
});
|
|
|
|
it('displays notification', async () => {
|
|
const notification = await screen.findByRole('alert');
|
|
expect(
|
|
getByText(
|
|
notification,
|
|
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
|
|
),
|
|
).toBeInTheDocument();
|
|
fireEvent.click(notification);
|
|
|
|
await waitForDatabaseRemoveToHaveCompleted();
|
|
});
|
|
|
|
it('closes menu', async () => {
|
|
const menuItems = screen.queryAllByRole('menuitem');
|
|
expect(menuItems).toHaveLength(0);
|
|
|
|
await waitForDatabaseRemoveToHaveCompleted();
|
|
});
|
|
});
|
|
|
|
describe('while loading', () => {
|
|
beforeEach(async () => {
|
|
await setup(false);
|
|
});
|
|
|
|
it('renders loading screen', async () => {
|
|
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
|
|
|
|
await waitForElementToBeRemoved(() =>
|
|
screen.getByTestId(loadingScreenTestId),
|
|
);
|
|
|
|
await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
|
|
await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
|
|
});
|
|
});
|
|
});
|