Testing Redux
parent
9416e917f8
commit
f9ff64efd4
|
@ -5,7 +5,7 @@ import AboutPage from "./about/AboutPage";
|
|||
import Header from "./common/Header";
|
||||
import PageNotFound from "./PageNotFound";
|
||||
import CoursesPage from "./courses/CoursesPage";
|
||||
import ManageCoursePage from "./courses/ManageCoursePage";
|
||||
import ManageCoursePage from "./courses/ManageCoursePage"; // eslint-disable-line import/no-named-as-default
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
|
||||
|
|
|
@ -9,7 +9,13 @@ import { newCourse } from "../../../tools/mockData";
|
|||
import Spinner from "../common/Spinner";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
function ManageCoursePage({ courses, authors, actions, history, ...props }) {
|
||||
export function ManageCoursePage({
|
||||
courses,
|
||||
authors,
|
||||
actions,
|
||||
history,
|
||||
...props
|
||||
}) {
|
||||
const [course, setCourse] = useState({ ...props.course });
|
||||
const [errors, setErrors] = useState({});
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { authors, newCourse, courses } from "../../../tools/mockData";
|
||||
import { ManageCoursePage } from "./ManageCoursePage";
|
||||
|
||||
function render(args) {
|
||||
const defaultProps = {
|
||||
authors,
|
||||
courses,
|
||||
// Passed from React Router in real app, so just stubbing in for test.
|
||||
// Could also choose to use MemoryRouter as shown in Header.test.js,
|
||||
// or even wrap with React Router, depending on whether I
|
||||
// need to test React Router related behavior.
|
||||
history: {},
|
||||
actions: {
|
||||
saveCourse: jest.fn(),
|
||||
loadAuthors: jest.fn(),
|
||||
loadCourses: jest.fn()
|
||||
},
|
||||
course: newCourse,
|
||||
match: {}
|
||||
};
|
||||
|
||||
const props = { ...defaultProps, ...args };
|
||||
|
||||
return mount(<ManageCoursePage {...props} />);
|
||||
}
|
||||
|
||||
it("sets error when attempting to save an empty title field", () => {
|
||||
const wrapper = render();
|
||||
wrapper.find("form").simulate("submit");
|
||||
const error = wrapper.find(".alert").first();
|
||||
expect(error.text()).toBe("Title is required.");
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
import * as courseActions from "./courseActions";
|
||||
import * as types from "./actionTypes";
|
||||
import { courses } from "../../../tools/mockData";
|
||||
import thunk from "redux-thunk";
|
||||
import fetchMock from "fetch-mock";
|
||||
import configureMockStore from "redux-mock-store";
|
||||
|
||||
// Test an async action
|
||||
const middleware = [thunk];
|
||||
const mockStore = configureMockStore(middleware);
|
||||
|
||||
describe("Async Actions", () => {
|
||||
afterEach(() => {
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
describe("Load Courses Thunk", () => {
|
||||
it("should create BEGIN_API_CALL and LOAD_COURSES_SUCCESS when loading courses", () => {
|
||||
fetchMock.mock("*", {
|
||||
body: courses,
|
||||
headers: { "content-type": "application/json" }
|
||||
});
|
||||
|
||||
const expectedActions = [
|
||||
{ type: types.BEGIN_API_CALL },
|
||||
{ type: types.LOAD_COURSES_SUCCESS, courses }
|
||||
];
|
||||
|
||||
const store = mockStore({ courses: [] });
|
||||
return store.dispatch(courseActions.loadCourses()).then(() => {
|
||||
expect(store.getActions()).toEqual(expectedActions);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("createCourseSuccess", () => {
|
||||
it("should create a CREATE_COURSE_SUCCESS action", () => {
|
||||
//arrange
|
||||
const course = courses[0];
|
||||
const expectedAction = {
|
||||
type: types.CREATE_COURSE_SUCCESS,
|
||||
course
|
||||
};
|
||||
|
||||
//act
|
||||
const action = courseActions.createCourseSuccess(course);
|
||||
|
||||
//assert
|
||||
expect(action).toEqual(expectedAction);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
import courseReducer from "./courseReducer";
|
||||
import * as actions from "../actions/courseActions";
|
||||
|
||||
it("should add course when passed CREATE_COURSE_SUCCESS", () => {
|
||||
// arrange
|
||||
const initialState = [
|
||||
{
|
||||
title: "A"
|
||||
},
|
||||
{
|
||||
title: "B"
|
||||
}
|
||||
];
|
||||
|
||||
const newCourse = {
|
||||
title: "C"
|
||||
};
|
||||
|
||||
const action = actions.createCourseSuccess(newCourse);
|
||||
|
||||
// act
|
||||
const newState = courseReducer(initialState, action);
|
||||
|
||||
// assert
|
||||
expect(newState.length).toEqual(3);
|
||||
expect(newState[0].title).toEqual("A");
|
||||
expect(newState[1].title).toEqual("B");
|
||||
expect(newState[2].title).toEqual("C");
|
||||
});
|
||||
|
||||
it("should update course when passed UPDATE_COURSE_SUCCESS", () => {
|
||||
// arrange
|
||||
const initialState = [
|
||||
{ id: 1, title: "A" },
|
||||
{ id: 2, title: "B" },
|
||||
{ id: 3, title: "C" }
|
||||
];
|
||||
|
||||
const course = { id: 2, title: "New Title" };
|
||||
const action = actions.updateCourseSuccess(course);
|
||||
|
||||
// act
|
||||
const newState = courseReducer(initialState, action);
|
||||
const updatedCourse = newState.find((a) => a.id == course.id);
|
||||
const untouchedCourse = newState.find((a) => a.id == 1);
|
||||
|
||||
// assert
|
||||
expect(updatedCourse.title).toEqual("New Title");
|
||||
expect(untouchedCourse.title).toEqual("A");
|
||||
expect(newState.length).toEqual(3);
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
import { createStore } from "redux";
|
||||
import rootReducer from "./reducers";
|
||||
import initialState from "./reducers/initialState";
|
||||
import * as courseActions from "./actions/courseActions";
|
||||
|
||||
it("Should handle creating courses", function () {
|
||||
// arrange
|
||||
const store = createStore(rootReducer, initialState);
|
||||
const course = {
|
||||
title: "Clean Code"
|
||||
};
|
||||
|
||||
// act
|
||||
const action = courseActions.createCourseSuccess(course);
|
||||
store.dispatch(action);
|
||||
|
||||
// assert
|
||||
const createdCourse = store.getState().courses[0];
|
||||
expect(createdCourse).toEqual(course);
|
||||
});
|
Loading…
Reference in New Issue