diff --git a/app/screens/forgot_password/__snapshots__/forgot_password.test.js.snap b/app/screens/forgot_password/__snapshots__/forgot_password.test.js.snap
new file mode 100644
index 000000000..9e4f5e487
--- /dev/null
+++ b/app/screens/forgot_password/__snapshots__/forgot_password.test.js.snap
@@ -0,0 +1,3367 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ForgotPassword match snapshot after success of sendPasswordResetEmail 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": false,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": false,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ "context": Object {
+ "intl": Object {
+ "formatMessage": [MockFunction] {
+ "calls": Array [
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ ],
+ },
+ },
+ },
+ },
+}
+`;
+
+exports[`ForgotPassword should match snapshot 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": true,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": true,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ "context": Object {
+ "intl": Object {
+ "formatMessage": [MockFunction] {
+ "calls": Array [
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ ],
+ },
+ },
+ },
+ },
+}
+`;
+
+exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": false,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "backgroundColor": "#FFFFFF",
+ "flex": 1,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {},
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children":
+
+
+
+
+
+
+ ,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ undefined,
+
+
+
+
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "paddingHorizontal": 15,
+ "paddingVertical": 50,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "source": Object {
+ "testUri": "../../../dist/assets/images/logo.png",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ undefined,
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+ ,
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "To reset your password, enter the email address you used to sign up",
+ "id": "password_send.description",
+ "style": Array [
+ Object {
+ "color": "#777",
+ "fontSize": 16,
+ "fontWeight": "300",
+ "lineHeight": 22,
+ "marginBottom": 15,
+ "textAlign": "center",
+ },
+ Object {
+ "paddingTop": 15,
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "allowFontScaling": true,
+ "autoCapitalize": "none",
+ "autoCorrect": false,
+ "blurOnSubmit": false,
+ "disableFullscreenUI": true,
+ "keyboardType": "email-address",
+ "onChangeText": [Function],
+ "placeholder": undefined,
+ "style": Object {
+ "alignSelf": "stretch",
+ "borderColor": "gainsboro",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "fontSize": 16,
+ "height": 45,
+ "marginBottom": 5,
+ "marginTop": 5,
+ "paddingLeft": 10,
+ },
+ "underlineColorAndroid": "transparent",
+ },
+ "ref": [Function],
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "containerStyle": Object {
+ "alignItems": "center",
+ "alignSelf": "stretch",
+ "borderColor": "#2389D7",
+ "borderRadius": 3,
+ "borderWidth": 1,
+ "marginTop": 10,
+ "padding": 15,
+ },
+ "disabled": false,
+ "onPress": [Function],
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "function",
+ "props": Object {
+ "defaultMessage": "Reset my password",
+ "id": "password_send.reset",
+ "style": Array [
+ Object {
+ "color": "#2389D7",
+ "fontSize": 17,
+ "textAlign": "center",
+ },
+ ],
+ },
+ "ref": null,
+ "rendered": null,
+ "type": undefined,
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ "context": Object {
+ "intl": Object {
+ "formatMessage": [MockFunction] {
+ "calls": Array [
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ Array [
+ Object {
+ "defaultMessage": "Please enter a valid email address.",
+ "id": "password_send.error",
+ },
+ ],
+ Array [
+ Object {
+ "defaultMessage": "Email",
+ "id": "login.email",
+ },
+ ],
+ ],
+ },
+ },
+ },
+ },
+}
+`;
diff --git a/app/screens/forgot_password/forgot_password.js b/app/screens/forgot_password/forgot_password.js
new file mode 100644
index 000000000..4684b2bf6
--- /dev/null
+++ b/app/screens/forgot_password/forgot_password.js
@@ -0,0 +1,198 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {PureComponent} from 'react';
+import PropTypes from 'prop-types';
+import Button from 'react-native-button';
+import {intlShape} from 'react-intl';
+
+import {
+ Image,
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+
+import {isEmail} from 'mattermost-redux/utils/helpers';
+
+import {GlobalStyles} from 'app/styles';
+
+import ErrorText from 'app/components/error_text';
+import FormattedText from 'app/components/formatted_text';
+import StatusBar from 'app/components/status_bar';
+
+export default class ForgotPassword extends PureComponent {
+ static propTypes = {
+ actions: PropTypes.shape({
+ sendPasswordResetEmail: PropTypes.func.isRequired,
+ }),
+ }
+
+ static contextTypes = {
+ intl: intlShape.isRequired,
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ error: null,
+ email: '',
+ sentPasswordLink: false,
+ };
+ }
+
+ changeEmail = (email) => {
+ this.setState({
+ email,
+ });
+ }
+
+ submitResetPassword = async () => {
+ if (!this.state.email || !isEmail(this.state.email)) {
+ const {formatMessage} = this.context.intl;
+ this.setState({
+ error: formatMessage({id: 'password_send.error', defaultMessage: 'Please enter a valid email address.'}),
+ });
+ return;
+ }
+
+ const {data, error} = await this.props.actions.sendPasswordResetEmail(this.state.email);
+ if (error) {
+ this.setState({error});
+ } else if (this.state.error) {
+ this.setState({error: ''});
+ }
+ if (data) {
+ this.setState({sentPasswordLink: true});
+ }
+ }
+
+ emailIdRef = (ref) => {
+ this.emailId = ref;
+ };
+
+ blur = () => {
+ if (this.emailId) {
+ this.emailId.blur();
+ }
+ }
+
+ render() {
+ const {formatMessage} = this.context.intl;
+ let displayError;
+ if (this.state.error) {
+ displayError = (
+
+ );
+ }
+
+ let passwordFormView;
+ if (this.state.sentPasswordLink) {
+ passwordFormView = (
+
+
+
+ {this.state.email}
+
+
+
+ );
+ } else {
+ passwordFormView = (
+
+
+
+
+
+ );
+ }
+ return (
+
+
+
+
+
+ {displayError}
+ {passwordFormView}
+
+
+
+ );
+ }
+}
+
+const style = StyleSheet.create({
+ container: {
+ backgroundColor: '#FFFFFF',
+ flex: 1,
+ },
+ innerContainer: {
+ alignItems: 'center',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ paddingHorizontal: 15,
+ paddingVertical: 50,
+ },
+ forgotPasswordBtn: {
+ borderColor: 'transparent',
+ marginTop: 15,
+ },
+ resetSuccessContainer: {
+ marginTop: 15,
+ padding: 10,
+ backgroundColor: '#dff0d8',
+ borderColor: '#d6e9c6',
+ },
+ emailId: {
+ fontWeight: 'bold',
+ },
+ successTxtColor: {
+ color: '#3c763d',
+ },
+ defaultTopPadding: {
+ paddingTop: 15,
+ },
+});
diff --git a/app/screens/forgot_password/forgot_password.test.js b/app/screens/forgot_password/forgot_password.test.js
new file mode 100644
index 000000000..da58dc1c6
--- /dev/null
+++ b/app/screens/forgot_password/forgot_password.test.js
@@ -0,0 +1,78 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {configure, shallow} from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+configure({adapter: new Adapter()});
+
+import ForgotPassword from './forgot_password.js';
+
+jest.mock('react-intl');
+
+describe('ForgotPassword', () => {
+ const actions = {
+ sendPasswordResetEmail: jest.fn(),
+ };
+
+ const baseProps = {
+ actions,
+ };
+
+ const formatMessage = jest.fn();
+
+ test('should match snapshot', () => {
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage}}},
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('snapshot for error on failure of email regex', () => {
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage}}},
+ );
+
+ wrapper.setState({email: 'bar'});
+ wrapper.instance().submitResetPassword();
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('Should call sendPasswordResetEmail', () => {
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage}}},
+ );
+
+ wrapper.setState({email: 'test@test.com'});
+ wrapper.instance().submitResetPassword();
+ expect(actions.sendPasswordResetEmail).toBeCalledWith('test@test.com');
+ });
+
+ test('match snapshot after success of sendPasswordResetEmail', async () => {
+ const sendPasswordResetEmail = async () => {
+ return {
+ data: {},
+ };
+ };
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage}}},
+ );
+
+ wrapper.setState({email: 'test@test.com'});
+ wrapper.instance().submitResetPassword();
+ await sendPasswordResetEmail();
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/app/screens/forgot_password/index.js b/app/screens/forgot_password/index.js
new file mode 100644
index 000000000..612e7c00f
--- /dev/null
+++ b/app/screens/forgot_password/index.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {bindActionCreators} from 'redux';
+import {connect} from 'react-redux';
+
+import {sendPasswordResetEmail} from 'mattermost-redux/actions/users';
+import ForgotPassword from './forgot_password';
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ sendPasswordResetEmail,
+ }, dispatch),
+ };
+}
+
+export default connect(null, mapDispatchToProps)(ForgotPassword);
diff --git a/app/screens/index.js b/app/screens/index.js
index eef346b2d..958bc1b77 100644
--- a/app/screens/index.js
+++ b/app/screens/index.js
@@ -28,6 +28,7 @@ export function registerScreens(store, Provider) {
Navigation.registerComponent('Entry', () => Entry, store, Provider);
Navigation.registerComponent('ExpandedAnnouncementBanner', () => wrapWithContextProvider(require('app/screens/expanded_announcement_banner').default), store, Provider);
Navigation.registerComponent('FlaggedPosts', () => wrapWithContextProvider(require('app/screens/flagged_posts').default), store, Provider);
+ Navigation.registerComponent('ForgotPassword', () => wrapWithContextProvider(require('app/screens/forgot_password').default), store, Provider);
Navigation.registerComponent('ImagePreview', () => wrapWithContextProvider(require('app/screens/image_preview').default), store, Provider);
Navigation.registerComponent('Login', () => wrapWithContextProvider(require('app/screens/login').default), store, Provider);
Navigation.registerComponent('LoginOptions', () => wrapWithContextProvider(require('app/screens/login_options').default), store, Provider);
diff --git a/app/screens/login/login.js b/app/screens/login/login.js
index dd3621611..f3cd29e8e 100644
--- a/app/screens/login/login.js
+++ b/app/screens/login/login.js
@@ -300,6 +300,23 @@ export default class Login extends PureComponent {
this.scroll = ref;
};
+ forgotPassword = () => {
+ const {intl} = this.context;
+ const {navigator, theme} = this.props;
+ navigator.push({
+ screen: 'ForgotPassword',
+ title: intl.formatMessage({id: 'password_form.title', defaultMessage: 'Password Reset'}),
+ animated: true,
+ backButtonTitle: '',
+ navigatorStyle: {
+ navBarTextColor: theme.sidebarHeaderTextColor,
+ navBarBackgroundColor: theme.sidebarHeaderBg,
+ navBarButtonColor: theme.sidebarHeaderTextColor,
+ screenBackgroundColor: theme.centerChannelBg,
+ },
+ });
+ }
+
render() {
const isLoading = this.props.loginRequest.status === RequestStatus.STARTED || this.state.isLoading;
@@ -394,6 +411,16 @@ export default class Login extends PureComponent {
disableFullscreenUI={true}
/>
{proceed}
+
@@ -413,4 +440,11 @@ const style = StyleSheet.create({
paddingHorizontal: 15,
paddingVertical: 50,
},
+ forgotPasswordBtn: {
+ borderColor: 'transparent',
+ marginTop: 15,
+ },
+ forgotPasswordTxt: {
+ color: '#2389D7',
+ },
});
diff --git a/package-lock.json b/package-lock.json
index cb253f765..f6d260081 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10100,8 +10100,8 @@
}
},
"mattermost-redux": {
- "version": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
- "from": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
+ "version": "github:mattermost/mattermost-redux#1bc11c578b1dc2e5a508a00de65e4e9a549d72b1",
+ "from": "github:mattermost/mattermost-redux#1bc11c578b1dc2e5a508a00de65e4e9a549d72b1",
"requires": {
"deep-equal": "1.0.1",
"eslint-plugin-header": "1.2.0",
diff --git a/package.json b/package.json
index 59daed94f..a4793c2a1 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"intl": "1.2.5",
"jail-monkey": "1.0.0",
"jsc-android": "216113.0.3",
- "mattermost-redux": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
+ "mattermost-redux": "github:mattermost/mattermost-redux#1bc11c578b1dc2e5a508a00de65e4e9a549d72b1",
"mime-db": "1.33.0",
"prop-types": "15.6.1",
"react": "16.3.2",