From b5959e64955b4837ab2531bd3a2a91bfc1d83989 Mon Sep 17 00:00:00 2001 From: Stuart 'Stevie' Leitch Date: Sun, 5 Aug 2018 20:41:31 +0100 Subject: [PATCH] Group tests by form element and standardise names --- src/Pwnedpasswords.api.test.js | 14 +-- src/UserRegistration.js | 5 +- src/UserRegistration.test.js | 161 +++++++++++++++++++-------------- 3 files changed, 105 insertions(+), 75 deletions(-) diff --git a/src/Pwnedpasswords.api.test.js b/src/Pwnedpasswords.api.test.js index ab30ca6..231e3aa 100644 --- a/src/Pwnedpasswords.api.test.js +++ b/src/Pwnedpasswords.api.test.js @@ -25,18 +25,18 @@ describe('isPasswordPwned', () => { fetch.mockResponseOnce(apiResponse); }); - it('requests pwned passwords by partial hash', () => { + it('should request pwned passwords by partial hash', () => { isPasswordPwned(password); expect(fetch.mock.calls[0][0]).toBe('https://api.pwnedpasswords.com/range/' + expectedHashPrefix); }); - it('returns true when password is pwned', async () => { - const result = await isPasswordPwned(password); - expect(result).toBe(true); + it('should return true when password is pwned', () => { + const result = isPasswordPwned(password); + expect(result).resolves.toBe(true); }); - it('returns false when password is not pwned', async () => { - const result = await isPasswordPwned(uniquePassword); - expect(result).toBe(false); + it('should return false when password is not pwned', () => { + const result = isPasswordPwned(uniquePassword); + expect(result).resolves.toBe(false); }); }); \ No newline at end of file diff --git a/src/UserRegistration.js b/src/UserRegistration.js index 413e6e9..e6b664e 100644 --- a/src/UserRegistration.js +++ b/src/UserRegistration.js @@ -19,7 +19,10 @@ export class UserRegistration extends Component { } submitEnabled = () => { - return this.state.password && this.state.passwordMatchesConfirm; + return this.state.username && + this.state.password && + this.state.passwordMatchesConfirm && + !this.state.passwordIsPwned; }; checkForPwnedPassword = (password) => { diff --git a/src/UserRegistration.test.js b/src/UserRegistration.test.js index 8f3b281..9a300ee 100644 --- a/src/UserRegistration.test.js +++ b/src/UserRegistration.test.js @@ -3,40 +3,60 @@ import { shallow } from 'enzyme'; import {UserRegistration} from "./UserRegistration"; import * as pwn from "./Pwnedpasswords.api"; -describe ('', () => { +const username = 'username'; +const goodPassword = 'password'; +const pwnedPassword = "pwned"; - const username = 'username'; - const goodPassword = 'password'; - const pwnedPassword = "pwned"; - - pwn.isPasswordPwned = jest.fn((pwd) => { - return Promise.resolve(pwd !== goodPassword) - }); - const onSubmit = jest.fn(); +// Mock behaviours +pwn.isPasswordPwned = jest.fn((pwd) => { + return Promise.resolve(pwd !== goodPassword) +}); +const onSubmit = jest.fn(); - beforeEach(() => { - onSubmit.mockReset(); - }); +beforeEach(() => { + onSubmit.mockReset(); +}); +describe('password field', () => { - it('renders', () => { + it('should show warnings when password is pwned', async () => { const wrapper = shallow(); - expect(wrapper).toBeDefined(); + await setFieldValuesAndUpdate(wrapper, username, pwnedPassword, pwnedPassword); + + const inputField = wrapper.find('#passwordField input'); + const errorIcon = wrapper.find('#passwordField .icon'); + + expect(inputField.hasClass('is-danger')).toBe(true); + expect(errorIcon.exists()).toBe(true); }); + it ('should hide warnings when password is blank', () => { + const wrapper = shallow(); + setFieldValues(wrapper, username, '', ''); - it('notifies caller of username and password', () => { - const wrapper = shallow(); - setFieldValues(wrapper, username, goodPassword, goodPassword); + const inputField = wrapper.find('#passwordField input') + const errorIcon = wrapper.find('#passwordField .icon'); - const submitButton = wrapper.find('button'); - submitButton.simulate('click'); + expect(inputField.hasClass('is-danger')).toBe(false); + expect(errorIcon.exists()).toBe(false); + }); - expect(onSubmit).toBeCalledWith(username, goodPassword); + it ('should hide warnings when password is not pwned', async () => { + const wrapper = shallow(); + await setFieldValuesAndUpdate(wrapper, username, goodPassword, goodPassword); + + const inputField = wrapper.find('#passwordField input') + const errorIcon = wrapper.find('#passwordField .icon'); + + expect(inputField.hasClass('is-danger')).toBe(false); + expect(errorIcon.exists()).toBe(false); }); +}); + +describe('password confirmation field', () => { - it('shows error markers when password does not match confirmation', () => { + it('should show warnings when password does not match confirmation', () => { const wrapper = shallow(); setFieldValues(wrapper, username, goodPassword, 'mismatch'); @@ -47,7 +67,7 @@ describe ('', () => { expect(errorIcon.exists()).toBe(true); }); - it('hides error marker when password does matches confirmation', () => { + it('should hide warnings when password does matches confirmation', () => { const wrapper = shallow(); setFieldValues(wrapper, username, goodPassword, goodPassword); @@ -58,43 +78,49 @@ describe ('', () => { expect(errorIcon.exists()).toBe(false); }); - it('shows error marker when password is pwned', async () => { - const wrapper = shallow(); - await setFieldValuesAndUpdate(wrapper, username, pwnedPassword, pwnedPassword); +}); - const inputField = wrapper.find('#passwordField input'); - const errorIcon = wrapper.find('#passwordField .icon'); +describe('submit button', () => { - expect(inputField.hasClass('is-danger')).toBe(true); - expect(errorIcon.exists()).toBe(true); + it ('should disable submit when username is blank', () => { + const wrapper = shallow(); + setFieldValues(wrapper, '', goodPassword, goodPassword); + + const submitButton = wrapper.find('button'); + expect(submitButton.prop('disabled')).toBeTruthy(); + + // Try submitting anyway + submitButton.simulate('click'); + expect(onSubmit).not.toBeCalled(); }); - it ('hides error marker when password is blank', () => { - const wrapper = shallow(); + it('should disable submit when password and confirmation are blank', () => { + const wrapper = shallow(); setFieldValues(wrapper, username, '', ''); - const inputField = wrapper.find('#passwordField input') - const errorIcon = wrapper.find('#passwordField .icon'); + const submitButton = wrapper.find('button'); + expect(submitButton.prop('disabled')).toBeTruthy(); - expect(inputField.hasClass('is-danger')).toBe(false); - expect(errorIcon.exists()).toBe(false); + // Try submitting anyway + submitButton.simulate('click'); + expect(onSubmit).not.toBeCalled(); }); - it ('hides error marker when password is not pwned', async () => { - const wrapper = shallow(); - await setFieldValuesAndUpdate(wrapper, username, goodPassword, goodPassword); + it('should disable submit when password does not match confirmation', () => { + const wrapper = shallow(); + setFieldValues(wrapper, username, goodPassword, 'mismatch'); - const inputField = wrapper.find('#passwordField input') - const errorIcon = wrapper.find('#passwordField .icon'); + const submitButton = wrapper.find('button'); + expect(submitButton.prop('disabled')).toBeTruthy(); - expect(inputField.hasClass('is-danger')).toBe(false); - expect(errorIcon.exists()).toBe(false); + // Try submitting anyway + submitButton.simulate('click'); + expect(onSubmit).not.toBeCalled(); }); - - it('disables submit when password does not match confirmation', () => { + it('should disable submit when password is pwned', async () => { const wrapper = shallow(); - setFieldValues(wrapper, username, goodPassword, 'mismatch'); + await setFieldValuesAndUpdate(wrapper, username, pwnedPassword, pwnedPassword); const submitButton = wrapper.find('button'); expect(submitButton.prop('disabled')).toBeTruthy(); @@ -104,8 +130,7 @@ describe ('', () => { expect(onSubmit).not.toBeCalled(); }); - - it('enables submit when password matches confirmation', () => { + it('should enable submit when all fields are valid', () => { const wrapper = shallow(); setFieldValues(wrapper, username, goodPassword, goodPassword); @@ -116,36 +141,38 @@ describe ('', () => { expect(onSubmit).toBeCalled(); }); +}); + +describe ('callbacks', () => { - it('disables submit when password and confirmation are blank', () => { + it('should notify caller of username and password', () => { const wrapper = shallow(); - setFieldValues(wrapper, username, '', ''); + setFieldValues(wrapper, username, goodPassword, goodPassword); const submitButton = wrapper.find('button'); - expect(submitButton.prop('disabled')).toBeTruthy(); - - // Try submitting anyway submitButton.simulate('click'); - expect(onSubmit).not.toBeCalled(); + + expect(onSubmit).toBeCalledWith(username, goodPassword); }); - function setFieldValues(wrapper, username, password, confirm) { - const usernameField = wrapper.find('#usernameField input'); - const passwordField = wrapper.find('#passwordField input'); - const confirmField = wrapper.find('#confirmField input'); +}); - usernameField.simulate('change', stubEvent(usernameField, username)); - passwordField.simulate('change', stubEvent(passwordField, password)); - confirmField.simulate('change', stubEvent(confirmField, confirm)); - } +function setFieldValues(wrapper, username, password, confirm) { + const usernameField = wrapper.find('#usernameField input'); + const passwordField = wrapper.find('#passwordField input'); + const confirmField = wrapper.find('#confirmField input'); + usernameField.simulate('change', stubEvent(usernameField, username)); + passwordField.simulate('change', stubEvent(passwordField, password)); + confirmField.simulate('change', stubEvent(confirmField, confirm)); +} - async function setFieldValuesAndUpdate(wrapper, username, password, confirm) { - setFieldValues(wrapper, username, password, confirm); - await flushPromises(); - wrapper.update(); - } -}); + +async function setFieldValuesAndUpdate(wrapper, username, password, confirm) { + setFieldValues(wrapper, username, password, confirm); + await flushPromises(); + wrapper.update(); +} /** * Stubbed event object suitable for event simulatrion.