Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 0 additions & 168 deletions __tests__/components/__snapshots__/modal.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -19,171 +19,3 @@ exports[`Modal Component renders header correctly 1`] = `
</div>
</div>
`;

exports[`Modal Component renders whole form after header clicked 1`] = `
<div>
<div>
<div
className="Toastify"
/>
</div>
<div
className="flex justify-center"
>
<div
className="flex cursor-pointer justify-center p-4 m-6 rounded-md hover:bg-fcc-primary-yellow shadedow-lg border-solid border-color: inherit; border-2 pl-4 pr-4 bg-[#feac32] text-black"
onClick={[Function]}
>
Create Class
</div>
</div>
<div
className="bg-zinc-200 opacity-100 fixed inset-0 z-50"
>
<div
className="flex h-screen justify-center items-center"
>
<div
className="flex-col justify-center bg-fcc-gray-90 py-12 px-24 border-4 border-sky-500 rounded-xl overflow-auto max-h-screen"
>
<div
className="flex text-lg text-white justify-center items-center"
>
Create Class
</div>
<form
className="mt-8 space-y-6"
onSubmit={[Function]}
>
<input
name="remember"
type="hidden"
value="true"
/>
<div
className="rounded-md shadow-sm -space-y-px"
>
<div>
<h1
className="text-white"
>
Class Name:
</h1>
<label
className="sr-only"
htmlFor="class-name"
>
Class Name
</label>
<input
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
id="class-name"
name="classname"
onChange={[Function]}
placeholder="Class Name"
required={true}
/>
</div>
</div>
<div
className="rounded-md shadow-sm -space-y-px"
>
<div>
<h1
className="text-white"
>
Description:
</h1>
<label
className="sr-only"
htmlFor="description-text"
>
Description
</label>
<textarea
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
id="description-text"
name="description"
onChange={[Function]}
placeholder="Description"
required={true}
/>
</div>
</div>
<div
className="rounded-md shadow-sm -space-y-px w-60 lg:w-72 2xl:w-96"
>
<div>
<h1
className="text-white"
>
Select Certifications:
</h1>
<div
className="rmsc multi-select"
>
<div
aria-labelledby="Select"
aria-readonly={true}
className="dropdown-container"
onBlur={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
tabIndex={0}
>
<div
className="dropdown-heading"
onClick={[Function]}
>
<div
className="dropdown-heading-value"
>
<span
className="gray"
>
Select...
</span>
</div>
<svg
className="dropdown-heading-dropdown-arrow gray"
fill="none"
height="24"
stroke="currentColor"
strokeWidth="2"
width="24"
>
<path
d="M6 9L12 15 18 9"
/>
</svg>
</div>
</div>
</div>
</div>
</div>
<div
className="flex items-center justify-between"
/>
<div
className="flex items-center justify-center"
>
<button
className=" rounded px-4 py-2 text-white bg-green-700"
type="submit"
>
Create
</button>
<button
className="rounded px-5 py-2 ml-10 text-white bg-[#e3342f]"
onClick={[Function]}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
</div>
`;
56 changes: 56 additions & 0 deletions __tests__/components/classInviteTable.test.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ClassInviteTable from '../../components/ClassInviteTable';
import React from 'react';
import renderer from 'react-test-renderer';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import {
certifications,
classroomId,
Expand Down Expand Up @@ -58,4 +60,58 @@ describe('ClassInviteTable', () => {
.toJSON();
expect(tree).toMatchSnapshot();
});

// Regression test for the Edit Class modal pre-fill bug: the current name
// and description used to only be set as `placeholder`, so the fields
// looked pre-filled but any keystroke replaced them outright. They should
// now be bound as the controlled `value`.
it('pre-fills the Edit Class form with the current name and description', () => {
render(
<ClassInviteTable
currentClass={sampleClassroom}
certificationNames={certifications}
currentClassrooms={sampleCurrentClassrooms}
handleDelete={() => {}}
handleEdit={() => {}}
userId={userId}
/>
);

fireEvent.click(document.getElementById('menu-button'));
fireEvent.click(screen.getByText('Edit'));

expect(screen.getByLabelText('Class Name')).toHaveValue(
sampleClassroom.classroomName
);
expect(screen.getByLabelText('Description')).toHaveValue(
sampleClassroom.description
);

// Editing should append to the pre-filled value, not replace a blank field.
fireEvent.change(screen.getByLabelText('Class Name'), {
target: { value: `${sampleClassroom.classroomName} (updated)` }
});
expect(screen.getByLabelText('Class Name')).toHaveValue(
`${sampleClassroom.classroomName} (updated)`
);
});

it('renders the Edit Class modal into document.body via a portal', () => {
render(
<ClassInviteTable
currentClass={sampleClassroom}
certificationNames={certifications}
currentClassrooms={sampleCurrentClassrooms}
handleDelete={() => {}}
handleEdit={() => {}}
userId={userId}
/>
);

fireEvent.click(document.getElementById('menu-button'));
fireEvent.click(screen.getByText('Edit'));

expect(screen.getByText('Edit Class')).toBeVisible();
expect(screen.getByRole('button', { name: 'Update' })).toBeVisible();
});
});
43 changes: 32 additions & 11 deletions __tests__/components/modal.test.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Modal from '../../components/modal';
import React from 'react';
import renderer, { act } from 'react-test-renderer';
import renderer from 'react-test-renderer';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

const sampleData = [
{
Expand Down Expand Up @@ -41,16 +43,35 @@ describe('Modal Component', () => {
.toJSON();
expect(tree).toMatchSnapshot();
});

// The Create Class form renders through a React portal straight to
// document.body (see components/ClassModal.js), so it's verified with
// Testing Library against the real jsdom document instead of
// react-test-renderer's toJSON(), which can't reconcile a portal target
// that isn't one of its own fake instances.
it('renders whole form after header clicked', () => {
const testRenderer = renderer.create(
<Modal userId={sampleUser} certificationNames={sampleData} />
);
const testInstance = testRenderer.root;
const header = testInstance.findByProps({ className });
act(() => {
header.props.onClick();
});
const tree = testRenderer.toJSON();
expect(tree).toMatchSnapshot();
render(<Modal userId={sampleUser} certificationNames={sampleData} />);

fireEvent.click(screen.getByText('Create Class'));

expect(
screen.getByText('Create Class', { selector: '.text-lg' })
).toBeVisible();
expect(screen.getByLabelText('Class Name')).toBeVisible();
expect(screen.getByLabelText('Description')).toBeVisible();
expect(screen.getByRole('button', { name: 'Create' })).toBeVisible();
expect(screen.getByRole('button', { name: 'Cancel' })).toBeVisible();
});

it('closes the form when Cancel is clicked', () => {
render(<Modal userId={sampleUser} certificationNames={sampleData} />);

fireEvent.click(screen.getByText('Create Class'));
expect(screen.getByRole('button', { name: 'Create' })).toBeVisible();

fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
expect(
screen.queryByRole('button', { name: 'Create' })
).not.toBeInTheDocument();
});
});
Loading