Skip to content

Commit

Permalink
Setup jest testing framework for react
Browse files Browse the repository at this point in the history
Setup Github CI job for Jest, update node version in workflow

Move to react-testing-library, add test for StudentDropper
  • Loading branch information
smartspot2 committed Dec 31, 2022
1 parent 8716c11 commit da4c74e
Show file tree
Hide file tree
Showing 14 changed files with 19,122 additions and 7,117 deletions.
2 changes: 1 addition & 1 deletion .babelrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"presets": ["@babel/preset-react", "@babel/preset-typescript"],
"plugins": ["transform-class-properties", "lodash", "@babel/plugin-transform-runtime"]
"plugins": ["transform-class-properties", "lodash", "@babel/plugin-transform-runtime", "dynamic-import-node"]
}
14 changes: 14 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,17 @@ jobs:
eslint_extensions: js,jsx,ts,tsx
prettier: true
prettier_dir: csm_web/frontend/src
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm run test
4 changes: 4 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// babel config for jest
module.exports = {
presets: ["@babel/preset-env", ["@babel/preset-react", { runtime: "automatic" }]]
};
4 changes: 2 additions & 2 deletions csm_web/frontend/src/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export default function Modal({ children, closeModal, className = "" }: ModalPro
<div className={`modal ${className}`}>
<div className="modal-contents">
<div className="modal-close-x">
<button className="inline-plus-sign" onClick={closeModal}>
<span>×</span>
<button className="inline-plus-sign" aria-label="close" onClick={closeModal}>
<span>&times;</span>
</button>
</div>
{children}
Expand Down
2 changes: 1 addition & 1 deletion csm_web/frontend/src/components/section/StudentDropper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function StudentDropper({ id, sectionId, name }: StudentDropperPr
return (
<span className={`student-dropper ${showDropPrompt ? "ban-prompt-visible" : ""}`}>
<span title="Drop student from section" className="inline-plus-sign" onClick={() => setShowDropPrompt(true)}>
×
&times;
</span>
{showDropPrompt && (
<Modal closeModal={() => setShowDropPrompt(false)}>
Expand Down
10 changes: 10 additions & 0 deletions csm_web/frontend/src/tests/LoadingSpinner.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import { render } from "@testing-library/react";
import LoadingSpinner from "../components/LoadingSpinner";

describe("LoadingSpinner", () => {
it("should render correctly", () => {
const component = render(<LoadingSpinner />);
expect(component.asFragment()).toMatchSnapshot();
});
});
85 changes: 85 additions & 0 deletions csm_web/frontend/src/tests/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import Modal, { ModalCloser } from "../components/Modal";
import { act } from "react-dom/test-utils";

/**
* Returns a test Modal component.
*/
const getTestModal = (handleCloseModal: React.MouseEventHandler<Element>, className = ""): React.ReactElement => {
if (className === "") {
return (
<Modal closeModal={handleCloseModal}>
<div>Hello World</div>
</Modal>
);
} else {
return (
<Modal closeModal={handleCloseModal} className={className}>
<div>Hello World</div>
</Modal>
);
}
};

describe("Modal", () => {
it("should render correctly", () => {
const handleCloseModal = jest.fn();
const component = render(getTestModal(handleCloseModal));
expect(component.asFragment()).toMatchSnapshot();
});

it("should render correctly with className", () => {
const handleCloseModal = jest.fn();
const component = render(getTestModal(handleCloseModal, "test-modal"));
expect(component.asFragment()).toMatchSnapshot();
});

describe("should close correctly", () => {
test("when the close button is clicked", () => {
const handleCloseModal = jest.fn();
const component = render(getTestModal(handleCloseModal));

// find and click the close button
const closeButton = component.getByRole("button", { name: /close/i });
act(() => {
fireEvent.click(closeButton);
});

expect(handleCloseModal).toHaveBeenCalled();
});

test("when the overlay is clicked", () => {
const handleCloseModal = jest.fn();
const component = render(getTestModal(handleCloseModal));

// find and click the overlay
const overlay = component.container.querySelector(".modal-overlay")!;
act(() => {
fireEvent.click(overlay);
});

expect(handleCloseModal).toHaveBeenCalled();
});

test("when an external modal closer is clicked", () => {
// create a modal
const handleCloseModal = jest.fn();
const component = render(
<Modal closeModal={handleCloseModal} className="test-modal">
<div>Hello World</div>
<ModalCloser>Close</ModalCloser>
</Modal>
);
expect(component.asFragment()).toMatchSnapshot();

// find and click the external modal closer
const closer = component.container.querySelector(".modal-close")!;
act(() => {
fireEvent.click(closer);
});

expect(handleCloseModal).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`LoadingSpinner should render correctly 1`] = `
<DocumentFragment>
<div
class="sk-fading-circle "
>
<div
class="sk-circle1 sk-circle"
/>
<div
class="sk-circle2 sk-circle"
/>
<div
class="sk-circle3 sk-circle"
/>
<div
class="sk-circle4 sk-circle"
/>
<div
class="sk-circle5 sk-circle"
/>
<div
class="sk-circle6 sk-circle"
/>
<div
class="sk-circle7 sk-circle"
/>
<div
class="sk-circle8 sk-circle"
/>
<div
class="sk-circle9 sk-circle"
/>
<div
class="sk-circle10 sk-circle"
/>
<div
class="sk-circle11 sk-circle"
/>
<div
class="sk-circle12 sk-circle"
/>
</div>
</DocumentFragment>
`;
99 changes: 99 additions & 0 deletions csm_web/frontend/src/tests/__snapshots__/Modal.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Modal should close correctly when an external modal closer is clicked 1`] = `
<DocumentFragment>
<div
class="modal-overlay"
/>
<div
class="modal test-modal"
>
<div
class="modal-contents"
>
<div
class="modal-close-x"
>
<button
aria-label="close"
class="inline-plus-sign"
>
<span>
×
</span>
</button>
</div>
<div>
Hello World
</div>
<div
class="modal-close"
>
Close
</div>
</div>
</div>
</DocumentFragment>
`;

exports[`Modal should render correctly 1`] = `
<DocumentFragment>
<div
class="modal-overlay"
/>
<div
class="modal "
>
<div
class="modal-contents"
>
<div
class="modal-close-x"
>
<button
aria-label="close"
class="inline-plus-sign"
>
<span>
×
</span>
</button>
</div>
<div>
Hello World
</div>
</div>
</div>
</DocumentFragment>
`;

exports[`Modal should render correctly with className 1`] = `
<DocumentFragment>
<div
class="modal-overlay"
/>
<div
class="modal test-modal"
>
<div
class="modal-contents"
>
<div
class="modal-close-x"
>
<button
aria-label="close"
class="inline-plus-sign"
>
<span>
×
</span>
</button>
</div>
<div>
Hello World
</div>
</div>
</div>
</DocumentFragment>
`;
Loading

0 comments on commit da4c74e

Please sign in to comment.