diff --git a/client/components/organization-wrapper/organization-wrapper.js b/client/components/organization-wrapper/organization-wrapper.js index c8aa31b1..dba16282 100644 --- a/client/components/organization-wrapper/organization-wrapper.js +++ b/client/components/organization-wrapper/organization-wrapper.js @@ -96,6 +96,7 @@ OrganizationWrapper.propTypes = { params: PropTypes.shape({ organization: PropTypes.string.isRequired, }), + path: PropTypes.string, }).isRequired, setOrganization: PropTypes.func.isRequired, organization: PropTypes.shape({ diff --git a/client/components/password-confirm/__snapshots__/password-confirm.test.js.snap b/client/components/password-confirm/__snapshots__/password-confirm.test.js.snap new file mode 100644 index 00000000..02bfa401 --- /dev/null +++ b/client/components/password-confirm/__snapshots__/password-confirm.test.js.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` rendering should render correctly 1`] = ` +
+
+
+
+ reset your password +
+
+ please enter your new password +
+
+
+ + +
+ +
+
+`; diff --git a/client/components/password-confirm/password-confirm.js b/client/components/password-confirm/password-confirm.js index 0d59b256..c7ca959b 100644 --- a/client/components/password-confirm/password-confirm.js +++ b/client/components/password-confirm/password-confirm.js @@ -38,13 +38,13 @@ export default class PasswordConfirm extends React.Component { newPassword2: passwordConfirmError, }, }); - return; + return false; } } this.setState({errors: {...errors, newPassword2: ""}}); const url = confirmApiUrl.replace("{orgSlug}", orgSlug); const {uid, token} = match.params; - axios({ + return axios({ method: "post", headers: { "content-type": "application/x-www-form-urlencoded", diff --git a/client/components/password-confirm/password-confirm.test.js b/client/components/password-confirm/password-confirm.test.js new file mode 100644 index 00000000..90f3b0bd --- /dev/null +++ b/client/components/password-confirm/password-confirm.test.js @@ -0,0 +1,202 @@ +/* eslint-disable prefer-promise-reject-errors */ +/* eslint-disable camelcase */ +import axios from "axios"; +import {shallow} from "enzyme"; +import React from "react"; +import {BrowserRouter as Router} from "react-router-dom"; +import renderer from "react-test-renderer"; + +import PasswordConfirm from "./password-confirm"; + +jest.mock("axios"); + +const createTestProps = props => { + return { + language: "en", + orgSlug: "default", + passwordConfirm: { + heading: { + en: "reset your password", + }, + additional_text: { + en: "please enter your new password", + }, + input_fields: { + password: { + type: "password", + pattern: ".{6,}", + pattern_description: { + en: "password must be a minimum of 6 characters", + }, + placeholder: { + en: "password", + }, + label: { + en: "password", + }, + }, + password_confirm: { + type: "password", + pattern: null, + pattern_description: { + en: null, + }, + placeholder: { + en: "confirm password", + }, + label: { + en: "confirm", + }, + }, + }, + buttons: { + submit: { + en: "change password", + }, + }, + }, + match: { + params: { + uid: "testUid", + token: "testToken", + }, + }, + ...props, + }; +}; + +describe(" rendering", () => { + let props; + let wrapper; + beforeEach(() => { + props = createTestProps(); + wrapper = shallow(); + }); + it("should render correctly", () => { + props = createTestProps(); + const component = renderer + .create( + + + , + ) + .toJSON(); + expect(component).toMatchSnapshot(); + }); + it("should render 2 input fields", () => { + expect(wrapper.find(".owisp-password-confirm-input")).toHaveLength(2); + }); + + it("should render password field correctly", () => { + const {password} = props.passwordConfirm.input_fields; + expect(wrapper.find(".owisp-password-confirm-label-password").text()).toBe( + password.label.en, + ); + expect( + wrapper + .find(".owisp-password-confirm-input-password") + .prop("placeholder"), + ).toBe(password.placeholder.en); + expect( + wrapper.find(".owisp-password-confirm-input-password").prop("title"), + ).toBe(password.pattern_description.en); + expect( + wrapper.find(".owisp-password-confirm-input-password").prop("type"), + ).toBe(password.type); + }); + it("should render password confirm field correctly", () => { + const {password_confirm} = props.passwordConfirm.input_fields; + expect(wrapper.find(".owisp-password-confirm-label-confirm").text()).toBe( + password_confirm.label.en, + ); + expect( + wrapper.find(".owisp-password-confirm-input-confirm").prop("placeholder"), + ).toBe(password_confirm.placeholder.en); + expect( + wrapper.find(".owisp-password-confirm-input-confirm").prop("title"), + ).toBe(password_confirm.pattern_description.en); + expect( + wrapper.find(".owisp-password-confirm-input-confirm").prop("type"), + ).toBe(password_confirm.type); + }); +}); + +describe(" interactions", () => { + let props; + let wrapper; + beforeEach(() => { + props = createTestProps(); + wrapper = shallow(); + }); + it("should change state values when handleChange function is invoked", () => { + wrapper + .find("#owisp-password-confirm-password") + .simulate("change", {target: {value: "123456", name: "newPassword1"}}); + expect(wrapper.state("newPassword1")).toEqual("123456"); + wrapper + .find("#owisp-password-confirm-password-confirm") + .simulate("change", {target: {value: "123456", name: "newPassword2"}}); + expect(wrapper.state("newPassword2")).toEqual("123456"); + }); + + it("should execute handleSubmit correctly when form is submitted", () => { + axios + .mockImplementationOnce(() => { + return Promise.reject({response: {data: {detail: "errors"}}}); + }) + .mockImplementationOnce(() => { + return Promise.reject({ + response: {data: {non_field_errors: ["non field errors"]}}, + }); + }) + .mockImplementationOnce(() => { + return Promise.resolve({data: {detail: true}}); + }); + wrapper.setState({ + newPassword1: "wrong password", + newPassword2: "wrong password1", + }); + wrapper.instance().handleSubmit({preventDefault: () => {}}); + expect( + wrapper.update().find(".owisp-password-confirm-error-confirm"), + ).toHaveLength(1); + wrapper.setState({ + newPassword1: "password", + newPassword2: "password", + }); + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors.nonField).toEqual("errors"); + expect( + wrapper.find(".owisp-password-confirm-error-non-field"), + ).toHaveLength(1); + }) + .then(() => { + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors.nonField).toEqual( + "non field errors", + ); + }); + }) + .then(() => { + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors).toEqual({}); + expect(wrapper.instance().state.success).toBe(true); + expect( + wrapper.find(".owisp-password-confirm-input.error"), + ).toHaveLength(0); + expect( + wrapper.find(".owisp-password-confirm-success"), + ).toHaveLength(1); + }); + }); + }); +}); diff --git a/client/components/password-reset/__snapshots__/password-reset.test.js.snap b/client/components/password-reset/__snapshots__/password-reset.test.js.snap new file mode 100644 index 00000000..46eb99f7 --- /dev/null +++ b/client/components/password-reset/__snapshots__/password-reset.test.js.snap @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` rendering should render correctly 1`] = ` +
+
+
+
+ reset your password +
+
+ enter your email and we'll send you the instructions to reset your password +
+
+
+ +
+ + + Take me Back to Sign In + +
+
+`; diff --git a/client/components/password-reset/password-reset.js b/client/components/password-reset/password-reset.js index 7f85c217..e6c040b4 100644 --- a/client/components/password-reset/password-reset.js +++ b/client/components/password-reset/password-reset.js @@ -30,7 +30,7 @@ export default class PasswordReset extends React.Component { const {orgSlug} = this.props; const {email, errors} = this.state; const url = resetApiUrl.replace("{orgSlug}", orgSlug); - axios({ + return axios({ method: "post", headers: { "content-type": "application/x-www-form-urlencoded", @@ -55,11 +55,9 @@ export default class PasswordReset extends React.Component { : data.non_field_errors ? data.non_field_errors[0] : ""; - this.setState({ errors: { ...errors, - success: false, ...(errorText ? {email: errorText} : {email: ""}), }, }); @@ -79,7 +77,7 @@ export default class PasswordReset extends React.Component {
{success}
{getText(loginPageLink.text, language)} diff --git a/client/components/password-reset/password-reset.test.js b/client/components/password-reset/password-reset.test.js new file mode 100644 index 00000000..5f576f5e --- /dev/null +++ b/client/components/password-reset/password-reset.test.js @@ -0,0 +1,156 @@ +/* eslint-disable prefer-promise-reject-errors */ +import axios from "axios"; +import {shallow} from "enzyme"; +import React from "react"; +import {BrowserRouter as Router} from "react-router-dom"; +import renderer from "react-test-renderer"; + +import PasswordReset from "./password-reset"; + +jest.mock("axios"); + +const createTestProps = props => { + return { + language: "en", + orgSlug: "default", + passwordReset: { + heading: { + en: "reset your password", + }, + additional_text: { + en: + "enter your email and we'll send you the instructions to reset your password", + }, + input_fields: { + email: { + type: "email", + pattern: null, + pattern_description: { + en: null, + }, + placeholder: { + en: "email address", + }, + label: { + en: "email", + }, + }, + }, + buttons: { + send: { + en: "send", + }, + }, + login_page_link: { + text: { + en: "Take me Back to Sign In", + }, + }, + }, + ...props, + }; +}; + +describe(" rendering", () => { + let props; + let wrapper; + beforeEach(() => { + props = createTestProps(); + wrapper = shallow(); + }); + it("should render correctly", () => { + props = createTestProps(); + const component = renderer + .create( + + + , + ) + .toJSON(); + expect(component).toMatchSnapshot(); + }); + it("should render 1 input field", () => { + expect(wrapper.find(".owisp-password-reset-input")).toHaveLength(1); + }); + + it("should render email field correctly", () => { + const {email} = props.passwordReset.input_fields; + expect(wrapper.find(".owisp-password-reset-label-email").text()).toBe( + email.label.en, + ); + expect( + wrapper.find(".owisp-password-reset-input-email").prop("placeholder"), + ).toBe(email.placeholder.en); + expect( + wrapper.find(".owisp-password-reset-input-email").prop("title"), + ).toBe(email.pattern_description.en); + expect(wrapper.find(".owisp-password-reset-input-email").prop("type")).toBe( + email.type, + ); + }); +}); + +describe(" interactions", () => { + let props; + let wrapper; + beforeEach(() => { + props = createTestProps(); + wrapper = shallow(); + }); + it("should change state values when handleChange function is invoked", () => { + wrapper + .find("#owisp-password-reset-email") + .simulate("change", {target: {value: "test@test.com", name: "email"}}); + expect(wrapper.state("email")).toEqual("test@test.com"); + }); + + it("should execute handleSubmit correctly when form is submitted", () => { + axios + .mockImplementationOnce(() => { + return Promise.reject({response: {data: {detail: "errors"}}}); + }) + .mockImplementationOnce(() => { + return Promise.reject({ + response: {data: {non_field_errors: ["non field errors"]}}, + }); + }) + .mockImplementationOnce(() => { + return Promise.resolve({data: {detail: true}}); + }); + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors.email).toEqual("errors"); + expect(wrapper.find(".owisp-password-reset-input.error")).toHaveLength( + 1, + ); + expect(wrapper.find(".owisp-password-reset-error")).toHaveLength(1); + }) + .then(() => { + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors.email).toEqual( + "non field errors", + ); + }); + }) + .then(() => { + return wrapper + .instance() + .handleSubmit({preventDefault: () => {}}) + .then(() => { + expect(wrapper.instance().state.errors).toEqual({}); + expect(wrapper.instance().state.success).toBe(true); + expect( + wrapper.find(".owisp-password-reset-input.error"), + ).toHaveLength(0); + expect(wrapper.find(".owisp-password-reset-success")).toHaveLength( + 1, + ); + }); + }); + }); +});