diff --git a/package.json b/package.json index 2f816b6..b0b27e0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,17 @@ "start": "run-p start:dev start:api", "start:dev": "webpack-dev-server --config webpack.config.dev.js --port 3000", "prestart:api": "node tools/createMockDb.js", - "start:api": "node tools/apiServer.js" + "start:api": "node tools/apiServer.js", + "test": "jest --watch" + }, + "jest": { + "setupFiles": [ + "./tools/testSetup.js" + ], + "moduleNameMapper": { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/tools/fileMock.js", + "\\.(css|less)$": "/tools/styleMock.js" + } }, "dependencies": { "bootstrap": "4.3.1", diff --git a/src/components/common/Header.test.js b/src/components/common/Header.test.js new file mode 100644 index 0000000..87ebd04 --- /dev/null +++ b/src/components/common/Header.test.js @@ -0,0 +1,22 @@ +import React from "react"; +import Header from "./Header"; +import { mount, shallow } from "enzyme"; +import { MemoryRouter } from "react-router-dom"; + +// Note how with shallow render you search for the React component tag +it("contains 3 NavLinks via shallow", () => { + const numLinks = shallow(
).find("NavLink").length; + expect(numLinks).toEqual(3); +}); + +// Note how with mount you search for the final rendered HTML since it generates the final DOM. +// We also need to pull in React Router's memoryRouter for testing since the Header expects to have React Router's props passed in. +it("contains 3 anchors via mount", () => { + const numAnchors = mount( + +
+ + ).find("a").length; + + expect(numAnchors).toEqual(3); +}); diff --git a/src/components/courses/CourseForm.Enzyme.test.js b/src/components/courses/CourseForm.Enzyme.test.js new file mode 100644 index 0000000..0a0a9ee --- /dev/null +++ b/src/components/courses/CourseForm.Enzyme.test.js @@ -0,0 +1,34 @@ +import React from "react"; +import CourseForm from "./CourseForm"; +import { shallow } from "enzyme"; + +function renderCourseForm(args) { + const defaultProps = { + authors: [], + course: {}, + saving: false, + errors: {}, + onSave: () => {}, + onChange: () => {} + }; + + const props = { ...defaultProps, ...args }; + return shallow(); +} + +it("renders form and header", () => { + const wrapper = renderCourseForm(); + // console.log(wrapper.debug()); + expect(wrapper.find("form").length).toBe(1); + expect(wrapper.find("h2").text()).toEqual("Add Course"); +}); + +it('labels save buttons as "Save" when not saving', () => { + const wrapper = renderCourseForm(); + expect(wrapper.find("button").text()).toBe("Save"); +}); + +it('labels save button as "Saving..." when saving', () => { + const wrapper = renderCourseForm({ saving: true }); + expect(wrapper.find("button").text()).toBe("Saving..."); +}); diff --git a/src/components/courses/CourseForm.ReactTestingLibrary.test.js b/src/components/courses/CourseForm.ReactTestingLibrary.test.js new file mode 100644 index 0000000..e0bbf72 --- /dev/null +++ b/src/components/courses/CourseForm.ReactTestingLibrary.test.js @@ -0,0 +1,35 @@ +import React from "react"; +import { cleanup, render } from "react-testing-library"; +import CourseForm from "./CourseForm"; + +afterEach(cleanup); + +function renderCourseForm(args) { + let defaultProps = { + authors: [], + course: {}, + saving: false, + errors: {}, + onSave: () => {}, + onChange: () => {} + }; + + const props = { ...defaultProps, ...args }; + return render(); +} + +it("should render Add Course header", () => { + const { getByText } = renderCourseForm(); + getByText("Add Course"); +}); + +it('should label save button as "Save" when not saving', () => { + const { getByText } = renderCourseForm(); + getByText("Save"); +}); + +it('should label save button as "Saving..." when saving', () => { + const { getByText, debug } = renderCourseForm({ saving: true }); + // debug(); + getByText("Saving..."); +}); diff --git a/src/components/courses/CourseForm.Snapshots.test.js b/src/components/courses/CourseForm.Snapshots.test.js new file mode 100644 index 0000000..a61cf52 --- /dev/null +++ b/src/components/courses/CourseForm.Snapshots.test.js @@ -0,0 +1,32 @@ +import React from "react"; +import CourseForm from "./CourseForm"; +import renderer from "react-test-renderer"; +import { courses, authors } from "../../../tools/mockData"; + +it("sets submit button label 'Saving...' when saving is true", () => { + const tree = renderer.create( + + ); + + expect(tree).toMatchSnapshot(); +}); + +it("sets submit button label 'Save' when saving is false", () => { + const tree = renderer.create( + + ); + + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/courses/__snapshots__/CourseForm.Snapshots.test.js.snap b/src/components/courses/__snapshots__/CourseForm.Snapshots.test.js.snap new file mode 100644 index 0000000..7dec255 --- /dev/null +++ b/src/components/courses/__snapshots__/CourseForm.Snapshots.test.js.snap @@ -0,0 +1,197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`sets submit button label 'Save' when saving is false 1`] = ` +
+

+ Edit + Course +

+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+`; + +exports[`sets submit button label 'Saving...' when saving is true 1`] = ` +
+

+ Edit + Course +

+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+`; diff --git a/src/index.test.js b/src/index.test.js new file mode 100644 index 0000000..8e78e57 --- /dev/null +++ b/src/index.test.js @@ -0,0 +1,3 @@ +it("should pass", () => { + expect(true).toEqual(true); +}); diff --git a/tools/fileMock.js b/tools/fileMock.js new file mode 100644 index 0000000..d9694f3 --- /dev/null +++ b/tools/fileMock.js @@ -0,0 +1,2 @@ +// Mocks file imports for Jest. As suggested by https://jestjs.io/docs/en/webpack +module.exports = "test-file-stub"; diff --git a/tools/styleMock.js b/tools/styleMock.js new file mode 100644 index 0000000..9cd445d --- /dev/null +++ b/tools/styleMock.js @@ -0,0 +1,2 @@ +// Mocks CSS imports for Jest. As suggested by https://jestjs.io/docs/en/webpack +module.exports = {}; diff --git a/tools/testSetup.js b/tools/testSetup.js new file mode 100644 index 0000000..a7fc090 --- /dev/null +++ b/tools/testSetup.js @@ -0,0 +1,3 @@ +import { configure } from "enzyme"; +import Adapter from "enzyme-adapter-react-16"; +configure({ adapter: new Adapter() });