From c2679a1069e46df7183c2e1bf3e7cf77c9f30510 Mon Sep 17 00:00:00 2001 From: Lisa Kim Date: Wed, 26 Feb 2020 09:16:18 -0800 Subject: [PATCH] Unit test FormLogin (#35) * Add prop type definition in FormLogin --- .../shared/components/FormLogin/FormLogin.jsx | 23 ++- .../components/FormLogin/FormLogin.test.js | 167 ++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 packages/shared/components/FormLogin/FormLogin.test.js diff --git a/packages/shared/components/FormLogin/FormLogin.jsx b/packages/shared/components/FormLogin/FormLogin.jsx index bc70d917e..52205b18a 100644 --- a/packages/shared/components/FormLogin/FormLogin.jsx +++ b/packages/shared/components/FormLogin/FormLogin.jsx @@ -143,9 +143,30 @@ export default function LoginForm(props) { } LoginForm.propTypes = { + /** + * authProviders is an array of Single Sign On (SSO) Providers. + * eg: github, google, bitbucket, microsoft, unknown, etc. + * + * enums are defined in shared/ButtonSso/utils.js + */ + authProviders: PropTypes.array, + + /** + * auth2faType defines login type. + * eg: u2f, otp, off (disabled). + * + * enums are defined in shared/services/enums.js + */ auth2faType: PropTypes.string, + + /** + * attempt contains props that indicate login processing status. + * + * fmt: {isFailed: bool, isProcessing: bool, message: string} + */ + attempt: PropTypes.object.isRequired, + onLoginWithU2f: PropTypes.func.isRequired, onLogin: PropTypes.func.isRequired, onLoginWithSso: PropTypes.func.isRequired, - attempt: PropTypes.object.isRequired, }; diff --git a/packages/shared/components/FormLogin/FormLogin.test.js b/packages/shared/components/FormLogin/FormLogin.test.js new file mode 100644 index 000000000..9a65f5ed6 --- /dev/null +++ b/packages/shared/components/FormLogin/FormLogin.test.js @@ -0,0 +1,167 @@ +/** + * Copyright 2020 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import FormLogin from './FormLogin'; +import { render, fireEvent } from 'design/utils/testing'; +import { Auth2faTypeEnum, AuthProviderTypeEnum } from '../../services/enums'; +import { TypeEnum as Type } from '../ButtonSso/'; + +test('login with auth2faType: disabled with ssoProviders', () => { + const onLogin = jest.fn(); + const onLoginWithSso = jest.fn(); + const onLoginWithU2f = jest.fn(); + + const { getByText, getByPlaceholderText } = render( + + ); + + expect(getByText('titleText')).toBeInTheDocument(); + + // fill form + fireEvent.change(getByPlaceholderText(/user name/i), { + target: { value: 'username' }, + }); + fireEvent.change(getByPlaceholderText(/password/i), { + target: { value: '123' }, + }); + fireEvent.click(getByText(/login/i)); + + expect(onLogin).toHaveBeenCalledWith('username', '123', ''); + expect(onLoginWithSso).not.toHaveBeenCalled(); + expect(onLoginWithU2f).not.toHaveBeenCalled(); + jest.clearAllMocks(); + + // test ssoProvider buttons + fireEvent.click(getByText(/github/i)); + expect(onLoginWithSso).toHaveBeenCalledTimes(1); + expect(onLogin).not.toHaveBeenCalled(); + expect(onLoginWithU2f).not.toHaveBeenCalled(); +}); + +test('login with auth2faType: OTP', () => { + const onLogin = jest.fn(); + const onLoginWithSso = jest.fn(); + const onLoginWithU2f = jest.fn(); + + const { getByText, getByPlaceholderText } = render( + + ); + + // fill form + fireEvent.change(getByPlaceholderText(/user name/i), { + target: { value: 'username' }, + }); + fireEvent.change(getByPlaceholderText(/password/i), { + target: { value: '123' }, + }); + fireEvent.change(getByPlaceholderText(/123 456/i), { + target: { value: '456' }, + }); + fireEvent.click(getByText(/login/i)); + + expect(onLogin).toHaveBeenCalledWith('username', '123', '456'); + expect(onLoginWithSso).not.toHaveBeenCalled(); + expect(onLoginWithU2f).not.toHaveBeenCalled(); +}); + +test('login with auth2faType: U2F', () => { + const onLogin = jest.fn(); + const onLoginWithSso = jest.fn(); + const onLoginWithU2f = jest.fn(); + + const { getByText } = render( + + ); + + const expEl = getByText( + /insert your U2F key and press the button on the key/i + ); + + expect(expEl).toBeInTheDocument(); + expect(getByText(/login/i)).toBeDisabled(); +}); + +test('input validation errors with OTP', () => { + const onLogin = jest.fn(); + const onLoginWithSso = jest.fn(); + const onLoginWithU2f = jest.fn(); + + const { getByText } = render( + + ); + + fireEvent.click(getByText(/login/i)); + + expect(onLogin).not.toHaveBeenCalled(); + expect(onLoginWithSso).not.toHaveBeenCalled(); + expect(onLoginWithU2f).not.toHaveBeenCalled(); + + expect(getByText(/username is required/i)).toBeInTheDocument(); + expect(getByText(/password is required/i)).toBeInTheDocument(); + expect(getByText(/token is required/i)).toBeInTheDocument(); +}); + +test('attempt object with prop isFailing and error message', () => { + const onLogin = jest.fn(); + const onLoginWithSso = jest.fn(); + const onLoginWithU2f = jest.fn(); + + const { getByText } = render( + + ); + + expect(getByText('errMsg')).toBeInTheDocument(); +});