| @@ -0,0 +1,75 @@ | ||
| 'use strict'; | ||
|
|
||
| /** | ||
| * Copyright (c) 2013-present, Facebook, Inc. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| * | ||
| * @typechecks | ||
| */ | ||
|
|
||
| /** | ||
| * The CSSCore module specifies the API (and implements most of the methods) | ||
| * that should be used when dealing with the display of elements (via their | ||
| * CSS classes and visibility on screen. It is an API focused on mutating the | ||
| * display and not reading it as no logical state should be encoded in the | ||
| * display of elements. | ||
| */ | ||
|
|
||
| var CSSCore = { | ||
| /** | ||
| * Adds the class passed in to the element if it doesn't already have it. | ||
| * | ||
| * @param {DOMElement} element the element to set the class on | ||
| * @param {string} className the CSS className | ||
| * @return {DOMElement} the element passed in | ||
| */ | ||
| addClass: function addClass(element, className) { | ||
| if (className) { | ||
| if (element.classList) { | ||
| element.classList.add(className); | ||
| } else if (!CSSCore.hasClass(element, className)) { | ||
| element.className = element.className + ' ' + className; | ||
| } | ||
| } | ||
| return element; | ||
| }, | ||
|
|
||
| /** | ||
| * Removes the class passed in from the element | ||
| * | ||
| * @param {DOMElement} element the element to set the class on | ||
| * @param {string} className the CSS className | ||
| * @return {DOMElement} the element passed in | ||
| */ | ||
| removeClass: function removeClass(element, className) { | ||
| if (className) { | ||
| if (element.classList) { | ||
| element.classList.remove(className); | ||
| } else if (CSSCore.hasClass(element, className)) { | ||
| element.className = element.className | ||
| .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1') | ||
| .replace(/\s+/g, ' ') // multiple spaces to one | ||
| .replace(/^\s*|\s*$/g, ''); // trim the ends | ||
| } | ||
| } | ||
| return element; | ||
| }, | ||
|
|
||
| /** | ||
| * Tests whether the element has the class specified. | ||
| * | ||
| * @param {DOMNode|DOMWindow} element the element to check the class on | ||
| * @param {string} className the CSS className | ||
| * @return {boolean} true if the element has the class, false if not | ||
| */ | ||
| hasClass: function hasClass(element, className) { | ||
| if (element.classList) { | ||
| return !!className && element.classList.contains(className); | ||
| } | ||
| return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1; | ||
| } | ||
| }; | ||
|
|
||
| module.exports = CSSCore; |
| @@ -0,0 +1,20 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`PasswordResetConfirmation renders correctly 1`] = ` | ||
| <div | ||
| className="auth0-lock-confirmation" | ||
| > | ||
| <div | ||
| className="auth0-lock-confirmation-content" | ||
| > | ||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg focusable=\\"false\\" width=\\"56px\\" height=\\"56px\\" viewBox=\\"0 0 52 52\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" class=\\"checkmark\\"> <circle cx=\\"26\\" cy=\\"26\\" r=\\"25\\" fill=\\"none\\" class=\\"checkmark__circle\\"></circle> <path fill=\\"none\\" d=\\"M14.1 27.2l7.1 7.2 16.7-16.8\\" class=\\"checkmark__check\\"></path> </svg>", | ||
| } | ||
| } | ||
| /> | ||
| <p /> | ||
| </div> | ||
| </div> | ||
| `; |
| @@ -0,0 +1,20 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`ResetPasswordScreen isSubmitDisabled returns false when \`isEnterpriseDomain\` is false 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| "clearGlobalError", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`ResetPasswordScreen isSubmitDisabled returns true when \`isEnterpriseDomain\` is true 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| "setGlobalError", | ||
| "error,forgotPassword,enterprise_email", | ||
| ] | ||
| `; |
| @@ -0,0 +1,20 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`SignedUpConfirmation renders correctly 1`] = ` | ||
| <div | ||
| className="auth0-lock-confirmation" | ||
| > | ||
| <div | ||
| className="auth0-lock-confirmation-content" | ||
| > | ||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg focusable=\\"false\\" width=\\"56px\\" height=\\"56px\\" viewBox=\\"0 0 52 52\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" class=\\"checkmark\\"> <circle cx=\\"26\\" cy=\\"26\\" r=\\"25\\" fill=\\"none\\" class=\\"checkmark__circle\\"></circle> <path fill=\\"none\\" d=\\"M14.1 27.2l7.1 7.2 16.7-16.8\\" class=\\"checkmark__check\\"></path> </svg>", | ||
| } | ||
| } | ||
| /> | ||
| <p /> | ||
| </div> | ||
| </div> | ||
| `; |
| @@ -0,0 +1,84 @@ | ||
| import Immutable, { List, Map } from 'immutable'; | ||
| import { signUp } from '../../../connection/database/actions'; | ||
| import { swap, setEntity } from '../../../store'; | ||
|
|
||
| const webApiMock = () => require('core/web_api'); | ||
| const coreActionsMock = () => require('core/actions'); | ||
| jest.mock('core/actions', () => ({ | ||
| validateAndSubmit: jest.fn() | ||
| })); | ||
|
|
||
| jest.mock('core/web_api', () => ({ | ||
| signUp: jest.fn() | ||
| })); | ||
|
|
||
| describe('database/actions.js', () => { | ||
| it('signUp splits root attributes correctly', () => { | ||
| const id = 1; | ||
| require('connection/database/index').databaseConnectionName = () => 'test-connection'; | ||
| require('connection/database/index').shouldAutoLogin = () => true; | ||
| const m = Immutable.fromJS({ | ||
| field: { | ||
| email: { | ||
| value: 'test@email.com' | ||
| }, | ||
| password: { | ||
| value: 'testpass' | ||
| }, | ||
| family_name: { | ||
| value: 'test-family-name' | ||
| }, | ||
| given_name: { | ||
| value: 'test-given-name' | ||
| }, | ||
| name: { | ||
| value: 'test-name' | ||
| }, | ||
| nickname: { | ||
| value: 'test-nickname' | ||
| }, | ||
| picture: { | ||
| value: 'test-pic' | ||
| }, | ||
| other_prop: { | ||
| value: 'test-other' | ||
| } | ||
| }, | ||
| database: { | ||
| additionalSignUpFields: [ | ||
| { name: 'family_name', storage: 'root' }, | ||
| { name: 'given_name', storage: 'root' }, | ||
| { name: 'name', storage: 'root' }, | ||
| { name: 'nickname', storage: 'root' }, | ||
| { name: 'picture', storage: 'root' }, | ||
| { name: 'other_prop' } | ||
| ] | ||
| } | ||
| }); | ||
| swap(setEntity, 'lock', id, m); | ||
| signUp(id); | ||
| const { validateAndSubmit: { mock: validateAndSubmitMock } } = coreActionsMock(); | ||
| expect(validateAndSubmitMock.calls.length).toBe(1); | ||
| expect(validateAndSubmitMock.calls[0][0]).toBe(id); | ||
| expect(validateAndSubmitMock.calls[0][1]).toContain('email'); | ||
| expect(validateAndSubmitMock.calls[0][1]).toContain('password'); | ||
| validateAndSubmitMock.calls[0][2](m); | ||
| const { signUp: { mock: signUpMock } } = webApiMock(); | ||
| expect(signUpMock.calls.length).toBe(1); | ||
| expect(signUpMock.calls[0][0]).toBe(id); | ||
| expect(signUpMock.calls[0][1]).toMatchObject({ | ||
| connection: 'test-connection', | ||
| email: 'test@email.com', | ||
| password: 'testpass', | ||
| autoLogin: true, | ||
| family_name: 'test-family-name', | ||
| given_name: 'test-given-name', | ||
| name: 'test-name', | ||
| nickname: 'test-nickname', | ||
| picture: 'test-pic', | ||
| user_metadata: { | ||
| other_prop: 'test-other' | ||
| } | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,124 @@ | ||
| import Immutable, { List, Map } from 'immutable'; | ||
| import { databaseUsernameValue, initDatabase } from '../../../connection/database'; | ||
|
|
||
| describe('database/index.js', () => { | ||
| describe('databaseUsernameValue', () => { | ||
| const getModel = (email, username, usernameRequired) => | ||
| Immutable.fromJS({ | ||
| field: { | ||
| email: { | ||
| value: email | ||
| }, | ||
| username: { | ||
| value: username | ||
| } | ||
| }, | ||
| core: { | ||
| transient: { | ||
| connections: { | ||
| database: [ | ||
| { | ||
| requireUsername: usernameRequired | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| beforeEach(() => { | ||
| jest.resetAllMocks(); | ||
| }); | ||
|
|
||
| describe('for database connection without username required', () => { | ||
| const model = getModel('user@auth0.com', null, false); | ||
|
|
||
| it('should get the email', () => { | ||
| expect(databaseUsernameValue(model)).toEqual('user@auth0.com'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('for database connection with username required', () => { | ||
| const model = getModel('user@auth0.com', 'user', true); | ||
|
|
||
| it('should get the username when `emailFirst` is not set', () => { | ||
| expect(databaseUsernameValue(model)).toEqual('user'); | ||
| }); | ||
| it('should get the username when `emailFirst` is false', () => { | ||
| expect(databaseUsernameValue(model, { emailFirst: false })).toEqual('user'); | ||
| }); | ||
| it('should get the email when `emailFirst` is true', () => { | ||
| expect(databaseUsernameValue(model, { emailFirst: true })).toEqual('user@auth0.com'); | ||
| }); | ||
|
|
||
| describe('and only email address is filled in', () => { | ||
| const model = getModel('user@auth0.com', null, true); | ||
|
|
||
| it('should get the email address', () => { | ||
| expect(databaseUsernameValue(model)).toEqual('user@auth0.com'); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('initDatabase', () => { | ||
| describe('calls initNS with the correct additionalSignUpFields', () => { | ||
| describe('uses the `storage` attribute', () => { | ||
| const model = Immutable.fromJS({}); | ||
| const modelOut = initDatabase(model, { | ||
| additionalSignUpFields: [ | ||
| { | ||
| type: 'hidden', | ||
| name: 'hidden_field', | ||
| value: 'hidden_value', | ||
| storage: 'root' | ||
| } | ||
| ] | ||
| }); | ||
| const modelOutJS = modelOut.toJS(); | ||
| expect(modelOutJS.database.additionalSignUpFields).toEqual([ | ||
| { | ||
| type: 'hidden', | ||
| name: 'hidden_field', | ||
| value: 'hidden_value', | ||
| storage: 'root' | ||
| } | ||
| ]); | ||
| }); | ||
| describe('with a valid hidden field', () => { | ||
| const model = Immutable.fromJS({}); | ||
| const modelOut = initDatabase(model, { | ||
| additionalSignUpFields: [ | ||
| { | ||
| type: 'hidden', | ||
| name: 'hidden_field', | ||
| value: 'hidden_value' | ||
| } | ||
| ] | ||
| }); | ||
| const modelOutJS = modelOut.toJS(); | ||
| expect(modelOutJS.field).toEqual({ | ||
| hidden_field: { showInvalid: false, valid: true, value: 'hidden_value' } | ||
| }); | ||
| expect(modelOutJS.database.additionalSignUpFields).toEqual([ | ||
| { | ||
| type: 'hidden', | ||
| name: 'hidden_field', | ||
| value: 'hidden_value' | ||
| } | ||
| ]); | ||
| }); | ||
| describe('with a hidden field without a value', () => { | ||
| const model = Immutable.fromJS({}); | ||
| const modelOut = initDatabase(model, { | ||
| additionalSignUpFields: [ | ||
| { | ||
| type: 'hidden', | ||
| name: 'hidden_field' | ||
| } | ||
| ] | ||
| }); | ||
| expect(modelOut.toJS().database.additionalSignUpFields.length).toBe(0); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,14 @@ | ||
| import React from 'react'; | ||
| import I from 'immutable'; | ||
|
|
||
| import { expectComponent } from 'testUtils'; | ||
|
|
||
| import PasswordResetConfirmation from '../../../connection/database/password_reset_confirmation'; | ||
|
|
||
| const lock = I.fromJS({ id: '__lock-id__' }); | ||
|
|
||
| describe('PasswordResetConfirmation', () => { | ||
| it('renders correctly', async () => { | ||
| expectComponent(<PasswordResetConfirmation lock={lock} />).toMatchSnapshot(); | ||
| }); | ||
| }); |
| @@ -0,0 +1,51 @@ | ||
| import React from 'react'; | ||
| import { mount } from 'enzyme'; | ||
|
|
||
| const getScreen = () => { | ||
| const ResetPasswordScreen = require('connection/database/reset_password').default; | ||
| return new ResetPasswordScreen(); | ||
| }; | ||
|
|
||
| describe('ResetPasswordScreen', () => { | ||
| beforeEach(() => { | ||
| jest.resetModules(); | ||
|
|
||
| jest.mock('connection/database/index', () => ({ | ||
| databaseUsernameValue: (model, options) => { | ||
| expect(options.emailFirst).toBe(true); | ||
| return 'foo@test.com'; | ||
| } | ||
| })); | ||
|
|
||
| jest.mock('connection/enterprise', () => ({ | ||
| isEnterpriseDomain: () => true | ||
| })); | ||
|
|
||
| jest.mock('i18n', () => ({ str: (_, keys) => keys.join(',') })); | ||
|
|
||
| jest.mock('core/index', () => ({ | ||
| id: () => 'id', | ||
| setGlobalError: 'setGlobalError', | ||
| clearGlobalError: 'clearGlobalError' | ||
| })); | ||
|
|
||
| jest.mock('store/index', () => ({ | ||
| swap: jest.fn(), | ||
| updateEntity: 'updateEntity' | ||
| })); | ||
| }); | ||
| it('isSubmitDisabled returns true when `isEnterpriseDomain` is true', () => { | ||
| jest.useFakeTimers(); | ||
| require('connection/enterprise').isEnterpriseDomain = () => true; | ||
| const screen = getScreen(); | ||
| expect(screen.isSubmitDisabled()).toBe(true); | ||
| jest.runTimersToTime(50); | ||
| expect(require('store/index').swap.mock.calls[0]).toMatchSnapshot(); | ||
| }); | ||
| it('isSubmitDisabled returns false when `isEnterpriseDomain` is false', () => { | ||
| require('connection/enterprise').isEnterpriseDomain = () => false; | ||
| const screen = getScreen(); | ||
| expect(screen.isSubmitDisabled()).toBe(false); | ||
| expect(require('store/index').swap.mock.calls[0]).toMatchSnapshot(); | ||
| }); | ||
| }); |
| @@ -0,0 +1,14 @@ | ||
| import React from 'react'; | ||
| import I from 'immutable'; | ||
|
|
||
| import { expectComponent } from 'testUtils'; | ||
|
|
||
| import SignedUpConfirmation from '../../../connection/database/signed_up_confirmation'; | ||
|
|
||
| const lock = I.fromJS({ id: '__lock-id__' }); | ||
|
|
||
| describe('SignedUpConfirmation', () => { | ||
| it('renders correctly', async () => { | ||
| expectComponent(<SignedUpConfirmation lock={lock} />).toMatchSnapshot(); | ||
| }); | ||
| }); |
| @@ -0,0 +1,59 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`EmailSentConfirmation renders correctly 1`] = ` | ||
| <div | ||
| className="auth0-lock-confirmation" | ||
| > | ||
| <span | ||
| aria-label="back" | ||
| className="auth0-lock-back-button" | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg aria-hidden=\\"true\\" focusable=\\"false\\" enable-background=\\"new 0 0 24 24\\" version=\\"1.0\\" viewBox=\\"0 0 24 24\\" xml:space=\\"preserve\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\"> <polyline fill=\\"none\\" points=\\"12.5,21 3.5,12 12.5,3 \\" stroke=\\"#000000\\" stroke-miterlimit=\\"10\\" stroke-width=\\"2\\"></polyline> <line fill=\\"none\\" stroke=\\"#000000\\" stroke-miterlimit=\\"10\\" stroke-width=\\"2\\" x1=\\"22\\" x2=\\"3.5\\" y1=\\"12\\" y2=\\"12\\"></line> </svg>", | ||
| } | ||
| } | ||
| id="__lock-id__-back-button" | ||
| onClick={[Function]} | ||
| onKeyPress={[Function]} | ||
| role="button" | ||
| tabIndex={0} | ||
| /> | ||
| <div | ||
| className="auth0-lock-confirmation-content" | ||
| > | ||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg focusable=\\"false\\" width=\\"56px\\" height=\\"56px\\" viewBox=\\"0 0 52 52\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" class=\\"checkmark\\"> <circle cx=\\"26\\" cy=\\"26\\" r=\\"25\\" fill=\\"none\\" class=\\"checkmark__circle\\"></circle> <path fill=\\"none\\" d=\\"M14.1 27.2l7.1 7.2 16.7-16.8\\" class=\\"checkmark__check\\"></path> </svg>", | ||
| } | ||
| } | ||
| /> | ||
| <p> | ||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": " ", | ||
| } | ||
| } | ||
| /> | ||
| </p> | ||
| <span> | ||
| <a | ||
| className="auth0-lock-resend-link" | ||
| href="javascript:void(0)" | ||
| onClick={[Function]} | ||
| > | ||
|
|
||
|
|
||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg focusable=\\"false\\" height=\\"32px\\" style=\\"enable-background:new 0 0 32 32;\\" version=\\"1.1\\" viewBox=\\"0 0 32 32\\" width=\\"32px\\" xml:space=\\"preserve\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\"> <path d=\\"M27.877,19.662c0.385-1.23,0.607-2.531,0.607-3.884c0-7.222-5.83-13.101-13.029-13.194v4.238 c4.863,0.093,8.793,4.071,8.793,8.956c0,0.678-0.088,1.332-0.232,1.966l-3.963-1.966l2.76,8.199l8.197-2.762L27.877,19.662z\\"></path> <path d=\\"M7.752,16.222c0-0.678,0.088-1.332,0.232-1.967l3.963,1.967l-2.76-8.199L0.99,10.785l3.133,1.553 c-0.384,1.23-0.607,2.531-0.607,3.885c0,7.223,5.83,13.1,13.03,13.194v-4.238C11.682,25.086,7.752,21.107,7.752,16.222z\\"></path> </svg>", | ||
| } | ||
| } | ||
| /> | ||
| </a> | ||
| </span> | ||
| </div> | ||
| </div> | ||
| `; |
| @@ -0,0 +1,302 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`passwordless actions login() calls webApi.passwordlessVerify() with email options 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Object { | ||
| "auth": "params", | ||
| "connection": "email", | ||
| "email": "email", | ||
| "verificationCode": "vcode", | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() calls webApi.passwordlessVerify() with sms options 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Object { | ||
| "auth": "params", | ||
| "connection": "sms", | ||
| "phoneNumber": "phoneNumberWithDiallingCode", | ||
| "verificationCode": "vcode", | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() on webApi.passwordlessVerify() callback calls logInSuccess on success 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Object { | ||
| "result": true, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() on webApi.passwordlessVerify() callback when there is an error emits the "authorization_error" event 1`] = ` | ||
| Array [ | ||
| "model", | ||
| [Error: foobar], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() on webApi.passwordlessVerify() callback when there is an error formats the error 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| true, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() on webApi.passwordlessVerify() callback when there is an error formats the error 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| false, | ||
| "error,passwordless,some_error_code", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() sets setSubmitting to true 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions login() sets setSubmitting to true 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| true, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() calls setPasswordlessStarted() on success 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() calls setPasswordlessStarted() on success 2`] = ` | ||
| Array [ | ||
| "model", | ||
| false, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() calls setPasswordlessStarted() on success 3`] = ` | ||
| Array [ | ||
| "model", | ||
| true, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() calls startPasswordless 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Object { | ||
| "connection": "email", | ||
| "email": "email", | ||
| "send": "send", | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() calls validateAndSubmit() 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Array [ | ||
| "email", | ||
| ], | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() normalizes the error message with a generic error 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() normalizes the error message with a generic error 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| false, | ||
| "error,passwordless,some_error_code", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions requestPasswordlessEmail() normalizes the error message with a sms_provider_error error and description includes (Code: 21211) 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| false, | ||
| "error,passwordless,bad.phone_number", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendFailed on error 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendFailed on error 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| "resend", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendFailed on error 3`] = ` | ||
| Array [ | ||
| "model", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendSuccess() on success 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendSuccess() on success 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| "resend", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions resendEmail() calls setResendSuccess() on success 3`] = ` | ||
| Array [ | ||
| "model", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions restart calls restartPasswordless 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() calls setPasswordlessStarted() on success 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() calls setPasswordlessStarted() on success 2`] = ` | ||
| Array [ | ||
| "model", | ||
| false, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() calls setPasswordlessStarted() on success 3`] = ` | ||
| Array [ | ||
| "model", | ||
| true, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() calls startPasswordless 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Object { | ||
| "connection": "sms", | ||
| "phoneNumber": "phoneNumberWithDiallingCode", | ||
| "send": "send", | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() calls validateAndSubmit() 1`] = ` | ||
| Array [ | ||
| "id", | ||
| Array [ | ||
| "phoneNumber", | ||
| ], | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() normalizes the error message with a generic error 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() normalizes the error message with a generic error 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| false, | ||
| "error,passwordless,some_error_code", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions sendSMS() normalizes the error message with a sms_provider_error error and description includes (Code: 21211) 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| false, | ||
| "error,passwordless,bad.phone_number", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions toggleTermsAcceptance() calls internalToggleTermsAcceptance() 1`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless actions toggleTermsAcceptance() calls internalToggleTermsAcceptance() 2`] = ` | ||
| Array [ | ||
| "model", | ||
| ] | ||
| `; |
| @@ -0,0 +1,108 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`passwordless connection initPasswordless() calls initNS with mustAcceptTerms:false when opts.mustAcceptTerms is false 1`] = ` | ||
| Array [ | ||
| null, | ||
| Immutable.Map { | ||
| "send": "code", | ||
| "mustAcceptTerms": false, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() calls initNS with mustAcceptTerms:true when opts.mustAcceptTerms is true 1`] = ` | ||
| Array [ | ||
| null, | ||
| Immutable.Map { | ||
| "send": "code", | ||
| "mustAcceptTerms": true, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() calls initNS with send:code when opts.passwordlessMethod is code 1`] = ` | ||
| Array [ | ||
| null, | ||
| Immutable.Map { | ||
| "send": "code", | ||
| "mustAcceptTerms": false, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() calls initNS with send:code when opts.passwordlessMethod is undefined 1`] = ` | ||
| Array [ | ||
| null, | ||
| Immutable.Map { | ||
| "send": "code", | ||
| "mustAcceptTerms": false, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() calls initNS with send:link when opts.passwordlessMethod is link 1`] = ` | ||
| Array [ | ||
| null, | ||
| Immutable.Map { | ||
| "send": "link", | ||
| "mustAcceptTerms": false, | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() should call webAPI.getUserCountry when there is no default location 1`] = ` | ||
| Array [ | ||
| undefined, | ||
| "location", | ||
| Object { | ||
| "recoverResult": "US", | ||
| "successFn": [Function], | ||
| "syncFn": [Function], | ||
| }, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() should call webAPI.getUserCountry when there is no default location 2`] = ` | ||
| Array [ | ||
| "id", | ||
| "cb", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() should call webAPI.getUserCountry when there is no default location 3`] = ` | ||
| Array [ | ||
| "model", | ||
| "en", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection initPasswordless() should load default location via options.defaultLocation 1`] = ` | ||
| Array [ | ||
| undefined, | ||
| "EN", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection mustAcceptTerms() should return \`mustAcceptTerms\` 1`] = ` | ||
| Array [ | ||
| "model", | ||
| "mustAcceptTerms", | ||
| false, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection toggleTermsAcceptance() should tset \`termsAccepted\` to false when \`termsAccepted\` is true 1`] = ` | ||
| Array [ | ||
| "model", | ||
| "termsAccepted", | ||
| true, | ||
| ] | ||
| `; | ||
|
|
||
| exports[`passwordless connection toggleTermsAcceptance() should tset \`termsAccepted\` to true when \`termsAccepted\` is false 1`] = ` | ||
| Array [ | ||
| "model", | ||
| "termsAccepted", | ||
| false, | ||
| ] | ||
| `; |
| @@ -0,0 +1,14 @@ | ||
| import React from 'react'; | ||
| import I from 'immutable'; | ||
|
|
||
| import { expectComponent } from 'testUtils'; | ||
|
|
||
| import EmailSentConfirmation from '../../../connection/passwordless/email_sent_confirmation'; | ||
|
|
||
| const lock = I.fromJS({ id: '__lock-id__' }); | ||
|
|
||
| describe('EmailSentConfirmation', () => { | ||
| it('renders correctly', async () => { | ||
| expectComponent(<EmailSentConfirmation lock={lock} />).toMatchSnapshot(); | ||
| }); | ||
| }); |
| @@ -0,0 +1,261 @@ | ||
| import passwordless from 'connection/passwordless/actions'; | ||
| import { expectMockToMatch } from 'testUtils'; | ||
|
|
||
| jest.useFakeTimers(); | ||
|
|
||
| describe('passwordless actions', () => { | ||
| let mockFns; | ||
| let actions; | ||
| beforeEach(() => { | ||
| jest.resetModules(); | ||
|
|
||
| jest.mock('connection/passwordless/index', () => ({ | ||
| isEmail: jest.fn(), | ||
| isSendLink: jest.fn(), | ||
| resend: 'resend', | ||
| restartPasswordless: jest.fn(), | ||
| send: () => 'send', | ||
| setPasswordlessStarted: jest.fn(), | ||
| setResendFailed: jest.fn(), | ||
| setResendSuccess: jest.fn(), | ||
| toggleTermsAcceptance: jest.fn() | ||
| })); | ||
| jest.mock('field/phone_number', () => ({ | ||
| phoneNumberWithDiallingCode: () => 'phoneNumberWithDiallingCode' | ||
| })); | ||
| jest.mock('field/index', () => ({ | ||
| getFieldValue: (m, field) => field | ||
| })); | ||
| jest.mock('core/web_api', () => ({ | ||
| startPasswordless: jest.fn(), | ||
| passwordlessVerify: jest.fn() | ||
| })); | ||
| jest.mock('core/actions', () => ({ | ||
| closeLock: jest.fn(), | ||
| logIn: jest.fn(), | ||
| validateAndSubmit: jest.fn(), | ||
| logInSuccess: jest.fn() | ||
| })); | ||
| jest.mock('i18n', () => ({ html: (_, keys) => keys.join(',') })); | ||
| jest.mock('core/index', () => ({ | ||
| id: () => 'id', | ||
| setSubmitting: jest.fn(m => m), | ||
| auth: { | ||
| params: () => ({ | ||
| toJS: () => ({ | ||
| auth: 'params' | ||
| }) | ||
| }) | ||
| }, | ||
| emitAuthorizationErrorEvent: jest.fn() | ||
| })); | ||
| jest.mock('store/index', () => ({ | ||
| read: jest.fn(() => 'model'), | ||
| getEntity: 'getEntity', | ||
| swap: jest.fn(), | ||
| updateEntity: 'updateEntity' | ||
| })); | ||
|
|
||
| actions = require('connection/passwordless/actions'); | ||
| }); | ||
| describe('requestPasswordlessEmail()', () => { | ||
| it('calls validateAndSubmit()', () => { | ||
| actions.requestPasswordlessEmail('id'); | ||
| expectMockToMatch(require('core/actions').validateAndSubmit, 1); | ||
| }); | ||
| it('calls startPasswordless', () => { | ||
| actions.requestPasswordlessEmail('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| expectMockToMatch(require('core/web_api').startPasswordless, 1); | ||
| }); | ||
| it('calls setPasswordlessStarted() on success', () => { | ||
| actions.requestPasswordlessEmail('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
|
|
||
| require('core/web_api').startPasswordless.mock.calls[0][2](null); | ||
|
|
||
| const { swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
|
|
||
| swap.mock.calls[0][3]('model'); | ||
| expectMockToMatch(require('core/index').setSubmitting, 1); | ||
| expectMockToMatch(require('connection/passwordless/index').setPasswordlessStarted, 1); | ||
| }); | ||
| describe('normalizes the error message', () => { | ||
| it('with a generic error', () => { | ||
| actions.requestPasswordlessEmail('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| const error = new Error('foobar'); | ||
| error.error = 'some_error_code'; | ||
| require('core/web_api').startPasswordless.mock.calls[0][2](error); | ||
|
|
||
| jest.runAllTimers(); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
| it('with a sms_provider_error error and description includes (Code: 21211)', () => { | ||
| actions.requestPasswordlessEmail('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| const error = new Error('foobar'); | ||
| error.error = 'sms_provider_error'; | ||
| error.description = 'something (Code: 21211)'; | ||
| require('core/web_api').startPasswordless.mock.calls[0][2](error); | ||
|
|
||
| jest.runAllTimers(); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('resendEmail()', () => { | ||
| it('calls setResendSuccess() on success', () => { | ||
| actions.resendEmail('id'); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
|
|
||
| require('core/web_api').startPasswordless.mock.calls[0][2](null); | ||
|
|
||
| swap.mock.calls[1][3]('model'); | ||
| expectMockToMatch(require('connection/passwordless/index').setResendSuccess, 1); | ||
| }); | ||
| it('calls setResendFailed on error', () => { | ||
| actions.resendEmail('id'); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
|
|
||
| require('core/web_api').startPasswordless.mock.calls[0][2](new Error('foobar')); | ||
| jest.runAllTimers(); | ||
| swap.mock.calls[1][3]('model'); | ||
| expectMockToMatch(require('connection/passwordless/index').setResendFailed, 1); | ||
| }); | ||
| }); | ||
| describe('sendSMS()', () => { | ||
| it('calls validateAndSubmit()', () => { | ||
| actions.sendSMS('id'); | ||
| expectMockToMatch(require('core/actions').validateAndSubmit, 1); | ||
| }); | ||
| it('calls startPasswordless', () => { | ||
| actions.sendSMS('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| expectMockToMatch(require('core/web_api').startPasswordless, 1); | ||
| }); | ||
| it('calls setPasswordlessStarted() on success', () => { | ||
| actions.sendSMS('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
|
|
||
| require('core/web_api').startPasswordless.mock.calls[0][2](null); | ||
|
|
||
| const { swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
|
|
||
| swap.mock.calls[0][3]('model'); | ||
| expectMockToMatch(require('core/index').setSubmitting, 1); | ||
| expectMockToMatch(require('connection/passwordless/index').setPasswordlessStarted, 1); | ||
| }); | ||
| describe('normalizes the error message', () => { | ||
| it('with a generic error', () => { | ||
| actions.sendSMS('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| const error = new Error('foobar'); | ||
| error.error = 'some_error_code'; | ||
| require('core/web_api').startPasswordless.mock.calls[0][2](error); | ||
|
|
||
| jest.runAllTimers(); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
| it('with a sms_provider_error error and description includes (Code: 21211)', () => { | ||
| actions.sendSMS('id'); | ||
| require('core/actions').validateAndSubmit.mock.calls[0][2]('model'); | ||
| const error = new Error('foobar'); | ||
| error.error = 'sms_provider_error'; | ||
| error.description = 'something (Code: 21211)'; | ||
| require('core/web_api').startPasswordless.mock.calls[0][2](error); | ||
|
|
||
| jest.runAllTimers(); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('login()', () => { | ||
| it('sets setSubmitting to true', () => { | ||
| actions.logIn('id'); | ||
|
|
||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
|
|
||
| it('calls webApi.passwordlessVerify() with sms options', () => { | ||
| actions.logIn('id'); | ||
| expectMockToMatch(require('core/web_api').passwordlessVerify, 1); | ||
| }); | ||
|
|
||
| it('calls webApi.passwordlessVerify() with email options', () => { | ||
| require('connection/passwordless/index').isEmail = () => true; | ||
| actions.logIn('id'); | ||
| expectMockToMatch(require('core/web_api').passwordlessVerify, 1); | ||
| }); | ||
|
|
||
| describe('on webApi.passwordlessVerify() callback', () => { | ||
| describe('when there is an error', () => { | ||
| it('formats the error', () => { | ||
| actions.logIn('id'); | ||
|
|
||
| const error = new Error('foobar'); | ||
| error.error = 'some_error_code'; | ||
| require('core/web_api').passwordlessVerify.mock.calls[0][2](error); | ||
|
|
||
| const { swap } = require('store/index'); | ||
| expectMockToMatch(swap, 2); | ||
| }); | ||
|
|
||
| it('emits the "authorization_error" event', () => { | ||
| actions.logIn('id'); | ||
|
|
||
| const error = new Error('foobar'); | ||
| error.error = 'some_error_code'; | ||
| require('core/web_api').passwordlessVerify.mock.calls[0][2](error); | ||
|
|
||
| expectMockToMatch(require('core/index').emitAuthorizationErrorEvent, 1); | ||
| }); | ||
| }); | ||
|
|
||
| it('calls logInSuccess on success', () => { | ||
| actions.logIn('id'); | ||
| require('core/web_api').passwordlessVerify.mock.calls[0][2](null, { result: true }); | ||
|
|
||
| expectMockToMatch(require('core/actions').logInSuccess, 1); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('toggleTermsAcceptance()', () => { | ||
| it('calls internalToggleTermsAcceptance()', () => { | ||
| actions.toggleTermsAcceptance('id'); | ||
|
|
||
| const { swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
|
|
||
| swap.mock.calls[0][3]('model'); | ||
|
|
||
| expectMockToMatch(require('connection/passwordless/index').toggleTermsAcceptance, 1); | ||
| }); | ||
| }); | ||
| it('restart calls restartPasswordless', () => { | ||
| actions.restart('id'); | ||
|
|
||
| const { swap } = require('store/index'); | ||
| expectMockToMatch(swap, 1); | ||
| }); | ||
| }); |
| @@ -0,0 +1,105 @@ | ||
| import { expectMockToMatch } from 'testUtils'; | ||
|
|
||
| describe('passwordless connection', () => { | ||
| let mockFns; | ||
| beforeEach(() => { | ||
| jest.resetModules(); | ||
|
|
||
| mockFns = { | ||
| get: jest.fn(), | ||
| initNS: jest.fn(), | ||
| tget: jest.fn(), | ||
| tremove: jest.fn(), | ||
| tset: jest.fn() | ||
| }; | ||
|
|
||
| jest.mock('utils/data_utils', () => ({ | ||
| dataFns: arr => { | ||
| return mockFns; | ||
| } | ||
| })); | ||
| jest.mock('field/phone_number', () => ({ | ||
| initLocation: jest.fn() | ||
| })); | ||
| jest.mock('core/web_api', () => ({ | ||
| getUserCountry: jest.fn() | ||
| })); | ||
| jest.mock('sync', () => jest.fn()); | ||
| jest.mock('core/index', () => ({ | ||
| id: () => 'id' | ||
| })); | ||
| }); | ||
| describe('initPasswordless()', () => { | ||
| let initPasswordless; | ||
| beforeEach(() => { | ||
| initPasswordless = require('connection/passwordless/index').initPasswordless; | ||
| }); | ||
| describe('calls initNS ', () => { | ||
| it('with send:code when opts.passwordlessMethod is undefined', () => { | ||
| initPasswordless(null, {}); | ||
| expectMockToMatch(mockFns.initNS, 1); | ||
| }); | ||
| it('with send:code when opts.passwordlessMethod is code', () => { | ||
| initPasswordless(null, { | ||
| passwordlessMethod: 'code' | ||
| }); | ||
| expectMockToMatch(mockFns.initNS, 1); | ||
| }); | ||
| it('with send:link when opts.passwordlessMethod is link', () => { | ||
| initPasswordless(null, { | ||
| passwordlessMethod: 'link' | ||
| }); | ||
| expectMockToMatch(mockFns.initNS, 1); | ||
| }); | ||
| it('with mustAcceptTerms:true when opts.mustAcceptTerms is true', () => { | ||
| initPasswordless(null, { | ||
| mustAcceptTerms: true | ||
| }); | ||
| expectMockToMatch(mockFns.initNS, 1); | ||
| }); | ||
| it('with mustAcceptTerms:false when opts.mustAcceptTerms is false', () => { | ||
| initPasswordless(null, { | ||
| mustAcceptTerms: false | ||
| }); | ||
| expectMockToMatch(mockFns.initNS, 1); | ||
| }); | ||
| }); | ||
| it('should load default location via options.defaultLocation', () => { | ||
| initPasswordless(null, { | ||
| defaultLocation: 'en' | ||
| }); | ||
| expectMockToMatch(require('field/phone_number').initLocation, 1); | ||
| }); | ||
| it('should call webAPI.getUserCountry when there is no default location', () => { | ||
| initPasswordless(null, {}); | ||
| const sync = require('sync'); | ||
| expectMockToMatch(sync, 1); | ||
|
|
||
| const { syncFn, successFn } = sync.mock.calls[0][2]; | ||
| syncFn(null, 'cb'); | ||
| expectMockToMatch(require('core/web_api').getUserCountry, 1); | ||
|
|
||
| successFn('model', 'en'); | ||
| expectMockToMatch(require('field/phone_number').initLocation, 1); | ||
| }); | ||
| }); | ||
| describe('mustAcceptTerms()', () => { | ||
| it('should return `mustAcceptTerms`', () => { | ||
| require('connection/passwordless/index').mustAcceptTerms('model'); | ||
| expectMockToMatch(mockFns.get, 1); | ||
| }); | ||
| }); | ||
|
|
||
| describe('toggleTermsAcceptance()', () => { | ||
| it('should tset `termsAccepted` to false when `termsAccepted` is true', () => { | ||
| mockFns.get.mockReturnValue(true); | ||
| require('connection/passwordless/index').toggleTermsAcceptance('model'); | ||
| expectMockToMatch(mockFns.tset, 1); | ||
| }); | ||
| it('should tset `termsAccepted` to true when `termsAccepted` is false', () => { | ||
| mockFns.get.mockReturnValue(false); | ||
| require('connection/passwordless/index').toggleTermsAcceptance('model'); | ||
| expectMockToMatch(mockFns.tset, 1); | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,25 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`core.actions checkSession should set submitting on start 1`] = ` | ||
| Array [ | ||
| "getEntity", | ||
| "lock", | ||
| "id", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`core.actions checkSession should set submitting on start 2`] = ` | ||
| Array [ | ||
| "updateEntity", | ||
| "lock", | ||
| "id", | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`core.actions checkSession should set submitting on start 3`] = ` | ||
| Array [ | ||
| "model", | ||
| true, | ||
| ] | ||
| `; |
| @@ -0,0 +1,20 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`SignedInConfirmation renders correctly 1`] = ` | ||
| <div | ||
| className="auth0-lock-confirmation" | ||
| > | ||
| <div | ||
| className="auth0-lock-confirmation-content" | ||
| > | ||
| <span | ||
| dangerouslySetInnerHTML={ | ||
| Object { | ||
| "__html": "<svg focusable=\\"false\\" width=\\"56px\\" height=\\"56px\\" viewBox=\\"0 0 52 52\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" class=\\"checkmark\\"> <circle cx=\\"26\\" cy=\\"26\\" r=\\"25\\" fill=\\"none\\" class=\\"checkmark__circle\\"></circle> <path fill=\\"none\\" d=\\"M14.1 27.2l7.1 7.2 16.7-16.8\\" class=\\"checkmark__check\\"></path> </svg>", | ||
| } | ||
| } | ||
| /> | ||
| <p /> | ||
| </div> | ||
| </div> | ||
| `; |
| @@ -0,0 +1,34 @@ | ||
| import { checkSession } from '../../core/actions'; | ||
| import { expectMockToMatch } from 'testUtils'; | ||
|
|
||
| jest.mock('../../core/web_api', () => ({ | ||
| checkSession: jest.fn() | ||
| })); | ||
|
|
||
| jest.mock('store/index', () => ({ | ||
| read: jest.fn(() => 'model'), | ||
| getEntity: 'getEntity', | ||
| swap: jest.fn(), | ||
| updateEntity: 'updateEntity' | ||
| })); | ||
|
|
||
| jest.mock('core/index', () => ({ | ||
| id: () => 'id', | ||
| setSubmitting: jest.fn() | ||
| })); | ||
|
|
||
| describe('core.actions', () => { | ||
| beforeEach(() => { | ||
| jest.resetAllMocks(); | ||
| }); | ||
| describe('checkSession', () => { | ||
| it('should set submitting on start', () => { | ||
| checkSession('id', 'params', 'cb'); | ||
| const { read, swap } = require('store/index'); | ||
| expectMockToMatch(read, 1); | ||
| expectMockToMatch(swap, 1); | ||
| swap.mock.calls[0][3]('model'); | ||
| expectMockToMatch(require('core/index').setSubmitting, 1); | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,61 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'excellent' correctly with a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 4, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'excellent' correctly without a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 10, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'fair' correctly with a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 4, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'fair' correctly without a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 8, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'good' correctly with a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 4, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'good' correctly without a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 8, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'low' correctly with a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 4, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'low' correctly without a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 6, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'none' correctly with a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 4, | ||
| } | ||
| `; | ||
|
|
||
| exports[`core/client/index initClient loads password policy 'none' correctly without a password_complexity_options option 1`] = ` | ||
| Object { | ||
| "minLength": 1, | ||
| } | ||
| `; |
| @@ -0,0 +1,44 @@ | ||
| import Immutable from 'immutable'; | ||
| import { initClient } from '../../../core/client'; | ||
|
|
||
| describe('core/client/index', () => { | ||
| describe('initClient', () => { | ||
| ['none', 'low', 'fair', 'good', 'excellent'].forEach(policy => { | ||
| it(`loads password policy '${policy}' correctly without a password_complexity_options option`, () => { | ||
| const client = { | ||
| strategies: [ | ||
| { | ||
| name: 'auth0', | ||
| connections: [ | ||
| { | ||
| name: 'Username-Password-Authentication', | ||
| passwordPolicy: policy | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }; | ||
| const result = initClient(Immutable.fromJS({}), client).toJS(); | ||
| expect(result.client.connections.database[0].passwordPolicy.length).toMatchSnapshot(); | ||
| }); | ||
| it(`loads password policy '${policy}' correctly with a password_complexity_options option`, () => { | ||
| const client = { | ||
| strategies: [ | ||
| { | ||
| name: 'auth0', | ||
| connections: [ | ||
| { | ||
| name: 'Username-Password-Authentication', | ||
| passwordPolicy: policy, | ||
| password_complexity_options: { min_length: 4 } | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }; | ||
| const result = initClient(Immutable.fromJS({}), client).toJS(); | ||
| expect(result.client.connections.database[0].passwordPolicy.length).toMatchSnapshot(); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,39 @@ | ||
| const getSyncRemoteData = () => require('core/remote_data').syncRemoteData; | ||
|
|
||
| describe('remote_data.syncRemoteData()', () => { | ||
| beforeEach(() => { | ||
| jest.resetModules(); | ||
|
|
||
| jest.mock('sync', () => jest.fn()); | ||
|
|
||
| jest.mock('connection/enterprise', () => ({ | ||
| isADEnabled: () => true | ||
| })); | ||
|
|
||
| jest.mock('core/index', () => ({ | ||
| useTenantInfo: () => true, | ||
| id: () => 'id' | ||
| })); | ||
|
|
||
| jest.mock('core/sso/data', () => ({ | ||
| fetchSSOData: jest.fn() | ||
| })); | ||
| }); | ||
| describe('calls getSSOData with AD information', () => { | ||
| [true, false].forEach(isAdEnabled => { | ||
| it(`when isADEnabled is ${isAdEnabled}`, () => { | ||
| require('connection/enterprise').isADEnabled = () => isAdEnabled; | ||
| const syncRemoteData = getSyncRemoteData(); | ||
| syncRemoteData(); | ||
| const ssoCall = require('sync').mock.calls.find(c => c[1] === 'sso'); | ||
| ssoCall[2].syncFn('model', 'callback'); | ||
| const [ | ||
| id, | ||
| sendADInformation, | ||
| callback | ||
| ] = require('core/sso/data').fetchSSOData.mock.calls[0]; | ||
| expect(sendADInformation).toBe(isAdEnabled); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
| @@ -0,0 +1,14 @@ | ||
| import React from 'react'; | ||
| import I from 'immutable'; | ||
|
|
||
| import { expectComponent } from 'testUtils'; | ||
|
|
||
| import SignedInConfirmation from '../../core/signed_in_confirmation'; | ||
|
|
||
| const lock = I.fromJS({ id: '__lock-id__' }); | ||
|
|
||
| describe('SignedInConfirmation', () => { | ||
| it('renders correctly', async () => { | ||
| expectComponent(<SignedInConfirmation lock={lock} />).toMatchSnapshot(); | ||
| }); | ||
| }); |
| @@ -0,0 +1,65 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain doesn't match current host should map access_denied error to invalid_user_password when error.code === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain doesn't match current host should map access_denied error to invalid_user_password when error.error === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain is undefined should map access_denied error to invalid_user_password when error.code === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain is undefined should map access_denied error to invalid_user_password when error.error === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain match current host should not map access_denied error to invalid_user_password when error.code === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`normalizeError access_denied to invalid_user_password mapping domain match current host should not map access_denied error to invalid_user_password when error.error === access_denied 1`] = ` | ||
| Object { | ||
| "code": "invalid_user_password", | ||
| "description": "foobar", | ||
| "error": "invalid_user_password", | ||
| } | ||
| `; | ||
|
|
||
| exports[`webAuthOverrides should omit overrides that are not compatible with WebAuth 1`] = ` | ||
| Object { | ||
| "__jwks_uri": "https://jwks.com", | ||
| "__tenant": "tenant1", | ||
| "__token_issuer": "issuer1", | ||
| } | ||
| `; | ||
|
|
||
| exports[`webAuthOverrides should return overrides if any field is compatible with WebAuth 1`] = ` | ||
| Object { | ||
| "__jwks_uri": "https://jwks.com", | ||
| "__tenant": "tenant1", | ||
| "__token_issuer": "issuer1", | ||
| } | ||
| `; |
| @@ -1,29 +1,316 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`Auth0APIClient getSSOData should call client.client.getSSOData 1`] = ` | ||
| Array [ | ||
| true, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient getUserCountry should call getUserCountry 1`] = ` | ||
| Array [ | ||
| "cb", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient init with overrides always uses telemetry set in the \`auth0Client\` query param and inside the ULP 1`] = ` | ||
| Object { | ||
| "env": Object { | ||
| "auth0.js-ulp": "a0js.version", | ||
| "envOverride": true, | ||
| "lock.js-ulp": "lock.version", | ||
| }, | ||
| "name": "test-sdk", | ||
| "version": "1.0.0", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient init with overrides forwards options to WebAuth 1`] = ` | ||
| Object { | ||
| "_sendTelemetry": true, | ||
| "_telemetryInfo": Object { | ||
| "env": Object { | ||
| "auth0.js": "a0js.version", | ||
| }, | ||
| "name": "lock.js", | ||
| "version": "lock.version", | ||
| }, | ||
| "audience": "foo", | ||
| "clientID": "cid", | ||
| "domain": "me.auth0.com", | ||
| "leeway": 30, | ||
| "nonce": "nonce", | ||
| "overrides": Object { | ||
| "__jwks_uri": "https://jwks.com", | ||
| "__tenant": "tenant1", | ||
| "__token_issuer": "issuer1", | ||
| }, | ||
| "plugins": Array [ | ||
| Object { | ||
| "name": "ExamplePlugin", | ||
| }, | ||
| ], | ||
| "redirectUri": "//localhost:8080/login/callback", | ||
| "responseMode": "query", | ||
| "responseType": "code", | ||
| "scope": "custom_scope", | ||
| "state": "state", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient init with overrides forwards options to WebAuth with a default leeway 1`] = ` | ||
| Object { | ||
| "_sendTelemetry": true, | ||
| "_telemetryInfo": Object { | ||
| "env": Object { | ||
| "auth0.js": "a0js.version", | ||
| }, | ||
| "name": "lock.js", | ||
| "version": "lock.version", | ||
| }, | ||
| "audience": "foo", | ||
| "clientID": "cid", | ||
| "domain": "me.auth0.com", | ||
| "leeway": 60, | ||
| "nonce": "nonce", | ||
| "overrides": Object { | ||
| "__jwks_uri": "https://jwks.com", | ||
| "__tenant": "tenant1", | ||
| "__token_issuer": "issuer1", | ||
| }, | ||
| "plugins": Array [ | ||
| Object { | ||
| "name": "ExamplePlugin", | ||
| }, | ||
| ], | ||
| "redirectUri": "//localhost:8080/login/callback", | ||
| "responseMode": "query", | ||
| "responseType": "code", | ||
| "scope": "custom_scope", | ||
| "state": "state", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient init with overrides overrides telemetry when outside the ULP 1`] = ` | ||
| Object { | ||
| "env": Object { | ||
| "auth0.js": "a0js.version", | ||
| "envOverride": true, | ||
| "lock.js": "lock.version", | ||
| }, | ||
| "name": "test-sdk", | ||
| "version": "1.0.0", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn should trim spaces in the email 1`] = ` | ||
| Object { | ||
| "email": "foo@example.com", | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "realm": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn should trim spaces in the mfa_code 1`] = ` | ||
| Object { | ||
| "mfa_code": "123456", | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "realm": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn should trim spaces in the username 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "realm": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn should trim spaces in the username with a space 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "realm": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo bar", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn with credentials should call client.login 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "realm": undefined, | ||
| "sso": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn with credentials should fail when in popup mode 1`] = `"Cross origin login is not supported in popup mode"`; | ||
| exports[`Auth0APIClient logIn with credentials should call popup.loginWithCredentials when redirect is false and sso is false 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn with credentials should call popup.loginWithCredentials when redirect is false and sso is true 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "popupOptions": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn with social/enterprise (without username and email) should call authorize when redirect===true 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "sso": undefined, | ||
| "popupOptions": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient logIn with social/enterprise (without username and email) should call popup.authorize when redirect===false 1`] = ` | ||
| Object { | ||
| "nonce": undefined, | ||
| "sso": undefined, | ||
| "owp": true, | ||
| "popupOptions": undefined, | ||
| "scope": undefined, | ||
| "state": undefined, | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient parseHash should pass __enableIdPInitiatedLogin when options._enableIdPInitiatedLogin===true 1`] = ` | ||
| Array [ | ||
| Object { | ||
| "__enableIdPInitiatedLogin": true, | ||
| "hash": "hash", | ||
| "nonce": undefined, | ||
| "state": undefined, | ||
| }, | ||
| "cb", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient parseHash should pass __enableIdPInitiatedLogin when options._enableImpersonation===true 1`] = ` | ||
| Array [ | ||
| Object { | ||
| "__enableIdPInitiatedLogin": true, | ||
| "hash": "hash", | ||
| "nonce": undefined, | ||
| "state": undefined, | ||
| }, | ||
| "cb", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient parseHash should pass __enableIdPInitiatedLogin:false when options._enableImpersonation and options._enableIdPInitiatedLogin are not present 1`] = ` | ||
| Array [ | ||
| Object { | ||
| "__enableIdPInitiatedLogin": false, | ||
| "hash": "hash", | ||
| "nonce": undefined, | ||
| "state": undefined, | ||
| }, | ||
| "cb", | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessStart should call client.passwordlessStart 1`] = ` | ||
| Array [ | ||
| Object { | ||
| "foo": "bar", | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessStart should trim spaces in the email 1`] = ` | ||
| Object { | ||
| "email": "foo@example.com", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessStart should trim spaces in the phoneNumber 1`] = ` | ||
| Object { | ||
| "phoneNumber": "+554899999", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessVerify should call client.passwordlessLogin 1`] = ` | ||
| Array [ | ||
| Object { | ||
| "foo": "bar", | ||
| "popup": true, | ||
| }, | ||
| [Function], | ||
| ] | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessVerify should trim spaces in the email 1`] = ` | ||
| Object { | ||
| "email": " foo@example.com ", | ||
| "popup": false, | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient passwordlessVerify should trim spaces in the phoneNumber 1`] = ` | ||
| Object { | ||
| "phoneNumber": " +554899999 ", | ||
| "popup": false, | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient resetPassword should trim spaces in the email 1`] = ` | ||
| Object { | ||
| "email": "foo@example.com", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient resetPassword should trim spaces in the username 1`] = ` | ||
| Object { | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient resetPassword should trim spaces in the username with a space 1`] = ` | ||
| Object { | ||
| "username": "foo bar", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient signUp should trim spaces in the email 1`] = ` | ||
| Object { | ||
| "email": "foo@example.com", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient signUp should trim spaces in the username 1`] = ` | ||
| Object { | ||
| "username": "foo", | ||
| } | ||
| `; | ||
|
|
||
| exports[`Auth0APIClient signUp should trim spaces in the username with a space 1`] = ` | ||
| Object { | ||
| "username": "foo bar", | ||
| } | ||
| `; |
| @@ -1,21 +1,94 @@ | ||
| import expect from 'expect.js'; | ||
| import { webAuthOverrides } from 'core/web_api/helper'; | ||
| import { webAuthOverrides, normalizeError } from 'core/web_api/helper'; | ||
|
|
||
| describe('webAuthOverrides', () => { | ||
| it('should return overrides if any field is compatible with WebAuth', function() { | ||
| expect(webAuthOverrides({ __tenant: 'tenant1', __token_issuer: 'issuer1' })).to.eql({ | ||
| __tenant: 'tenant1', | ||
| __token_issuer: 'issuer1' | ||
| }); | ||
| expect( | ||
| webAuthOverrides({ | ||
| __tenant: 'tenant1', | ||
| __token_issuer: 'issuer1', | ||
| __jwks_uri: 'https://jwks.com' | ||
| }) | ||
| ).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should omit overrides that are not compatible with WebAuth', function() { | ||
| expect( | ||
| webAuthOverrides({ __tenant: 'tenant1', __token_issuer: 'issuer1', backgroundColor: 'blue' }) | ||
| ).to.eql({ __tenant: 'tenant1', __token_issuer: 'issuer1' }); | ||
| webAuthOverrides({ | ||
| __tenant: 'tenant1', | ||
| __token_issuer: 'issuer1', | ||
| __jwks_uri: 'https://jwks.com', | ||
| backgroundColor: 'blue' | ||
| }) | ||
| ).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should return null if no fields are compatible with WebAuth', function() { | ||
| expect(webAuthOverrides({ backgroundColor: 'blue' })).to.not.be.ok(); | ||
| expect(webAuthOverrides({ backgroundColor: 'blue' })).toBe(null); | ||
| }); | ||
| }); | ||
|
|
||
| describe('normalizeError', () => { | ||
| it('does nothing when there is no error', () => { | ||
| const normalized = normalizeError(undefined); | ||
| expect(normalized).toBe(undefined); | ||
| }); | ||
|
|
||
| describe('access_denied to invalid_user_password mapping', function() { | ||
| const domainMock = 'domainMock'; | ||
| const errorObjWithError = { | ||
| error: 'access_denied', | ||
| description: 'foobar' | ||
| }; | ||
| const errorObjWithCode = { | ||
| code: 'access_denied', | ||
| description: 'foobar' | ||
| }; | ||
| let currentWindowObj; | ||
|
|
||
| beforeAll(function() { | ||
| currentWindowObj = global.window; | ||
| global.window = { | ||
| locaction: { | ||
| host: domainMock | ||
| } | ||
| }; | ||
| }); | ||
|
|
||
| afterAll(function() { | ||
| global.window = currentWindowObj; | ||
| }); | ||
|
|
||
| describe('domain is undefined', function() { | ||
| it('should map access_denied error to invalid_user_password when error.error === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithError); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| it('should map access_denied error to invalid_user_password when error.code === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithCode); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| }); | ||
|
|
||
| describe("domain doesn't match current host", function() { | ||
| it('should map access_denied error to invalid_user_password when error.error === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithError, 'loremIpsum'); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| it('should map access_denied error to invalid_user_password when error.code === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithCode, 'loremIpsum'); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('domain match current host', function() { | ||
| it('should not map access_denied error to invalid_user_password when error.error === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithError, domainMock); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| it('should not map access_denied error to invalid_user_password when error.code === access_denied', () => { | ||
| const actualError = normalizeError(errorObjWithCode, domainMock); | ||
| expect(actualError).toMatchSnapshot(); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |