From 128f9de279f599e16585b1b9754f24b9174b32d0 Mon Sep 17 00:00:00 2001 From: Kristofer Selbekk Date: Wed, 21 Feb 2018 16:12:24 +0100 Subject: [PATCH] chore(ffe-datepicker-react): Migrate tests to jest --- packages/ffe-datepicker-react/.eslintrc | 10 + packages/ffe-datepicker-react/package.json | 29 +- ...{ActiveDate.test.js => ActiveDate.spec.js} | 7 +- .../src/datelogic/simpledate.spec.js | 154 ++++++ .../src/datelogic/simpledate.test.js | 161 ------- .../src/datepicker/Datepicker.spec.js | 411 ++++++++++++++++ .../src/datepicker/Datepicker.test.js | 438 ------------------ .../input/{Input.test.js => Input.spec.js} | 32 +- .../src/util/test-setup.js | 14 - packages/ffe-datepicker-react/test-setup.js | 4 + 10 files changed, 608 insertions(+), 652 deletions(-) create mode 100644 packages/ffe-datepicker-react/.eslintrc rename packages/ffe-datepicker-react/src/calendar/{ActiveDate.test.js => ActiveDate.spec.js} (76%) create mode 100644 packages/ffe-datepicker-react/src/datelogic/simpledate.spec.js delete mode 100644 packages/ffe-datepicker-react/src/datelogic/simpledate.test.js create mode 100644 packages/ffe-datepicker-react/src/datepicker/Datepicker.spec.js delete mode 100644 packages/ffe-datepicker-react/src/datepicker/Datepicker.test.js rename packages/ffe-datepicker-react/src/input/{Input.test.js => Input.spec.js} (71%) delete mode 100644 packages/ffe-datepicker-react/src/util/test-setup.js create mode 100644 packages/ffe-datepicker-react/test-setup.js diff --git a/packages/ffe-datepicker-react/.eslintrc b/packages/ffe-datepicker-react/.eslintrc new file mode 100644 index 0000000000..e4bbd9dc3f --- /dev/null +++ b/packages/ffe-datepicker-react/.eslintrc @@ -0,0 +1,10 @@ +{ + "overrides": [ + { + "files": [ "src/**/*.spec.js"], + "env": { + "jest": true + } + } + ] + } diff --git a/packages/ffe-datepicker-react/package.json b/packages/ffe-datepicker-react/package.json index 37528026e6..2b34b9a87e 100644 --- a/packages/ffe-datepicker-react/package.json +++ b/packages/ffe-datepicker-react/package.json @@ -4,32 +4,22 @@ "main": "lib/ffe-datepicker-react.js", "license": "UNLICENSED", "scripts": { - "build": "babel -d lib/. --ignore=*.test.js src/.", + "build": "babel -d lib/. --ignore=*.spec.js src/.", "lint": "eslint src/.", "test": "npm run test:spec && npm run test:nsp", - "test:spec": "mocha --require src/util/test-setup.js --compilers js:babel-core/register 'src/**/*.test.js'", + "test:spec": "jest", "test:nsp": "nsp check", - "test:watch": "npm test -- -w" + "test:watch": "jest --watch" }, "devDependencies": { - "chai": "^4.1.2", - "chai-enzyme": "^1.0.0-beta.0", "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.1", "eslint": "^4.13.1", - "jsdom": "^11.5.1", - "mocha": "^4.1.0", + "jest": "^22.4.0", "nsp": "^3.1.0", - "react": "^16.0.0", - "react-dom": "^16.0.0", - "react-test-renderer": "^16.0.0", - "sinon": "^4.1.3", - "sinon-chai": "^2.14.0" + "react": "^16.2.0", + "react-dom": "^16.2.0" }, - "files": [ - "lib", - "*.js" - ], "peerDependencies": { "ffe-datepicker": "^4.2.5", "ffe-form": "2.x - 8.x", @@ -41,5 +31,12 @@ "ffe-icons-react": "^4.0.5", "prop-types": "^15.6.0", "uuid": "^3.1.0" + }, + "files": [ + "lib", + "*.js" + ], + "jest": { + "setupTestFrameworkScriptFile": "./test-setup.js" } } diff --git a/packages/ffe-datepicker-react/src/calendar/ActiveDate.test.js b/packages/ffe-datepicker-react/src/calendar/ActiveDate.spec.js similarity index 76% rename from packages/ffe-datepicker-react/src/calendar/ActiveDate.test.js rename to packages/ffe-datepicker-react/src/calendar/ActiveDate.spec.js index df088196da..7df167ee57 100644 --- a/packages/ffe-datepicker-react/src/calendar/ActiveDate.test.js +++ b/packages/ffe-datepicker-react/src/calendar/ActiveDate.spec.js @@ -1,7 +1,4 @@ -/* eslint-env mocha */ - import { shallow } from 'enzyme'; -import { assert } from 'chai'; import React from 'react'; import ActiveDate from './ActiveDate'; import simpleDate from '../datelogic/simpledate'; @@ -19,11 +16,11 @@ describe('', () => { it('should render an active date', () => { const wrapper = shallow(activeDate); - assert.equal(wrapper.find('td.ffe-calendar__day').length, 1); + expect(wrapper.find('td.ffe-calendar__day').exists()).toBe(true); }); it('should have role gridcell', () => { const wrapper = shallow(activeDate); - assert.equal(wrapper.find('[role="gridcell"]').length, 1); + expect(wrapper.find('[role="gridcell"]').exists()).toBe(true); }); }); diff --git a/packages/ffe-datepicker-react/src/datelogic/simpledate.spec.js b/packages/ffe-datepicker-react/src/datelogic/simpledate.spec.js new file mode 100644 index 0000000000..c7237982e4 --- /dev/null +++ b/packages/ffe-datepicker-react/src/datelogic/simpledate.spec.js @@ -0,0 +1,154 @@ +import simpleDate from './simpledate'; +import ErrorTypes from './error-types'; + +describe('simpleDate fromString', () => { + describe('triggers', () => { + it('onSuccess callback', () => { + const onSuccess = jest.fn(); + const date = simpleDate.fromString('01.01.2016', onSuccess); + + expect(onSuccess).toHaveBeenCalledTimes(1); + expect(onSuccess.mock.calls[0][0]).toBe(date); + }); + + it('onError callback with INVALID_DATE_FORMAT', () => { + const onError = jest.fn(); + simpleDate.fromString('---', () => {}, onError); + expect(onError).toHaveBeenCalledTimes(1); + expect(onError.mock.calls[0][0]).toBe( + ErrorTypes.INVALID_DATE_FORMAT, + ); + }); + + it('onError callback with INVALID_DATE', () => { + const onError = jest.fn(); + simpleDate.fromString('29.02.2015', () => {}, onError); + + expect(onError).toHaveBeenCalledTimes(1); + expect(onError.mock.calls[0][0]).toBe(ErrorTypes.INVALID_DATE); + }); + }); + + describe('formats', () => { + it('single digit dates as double digit values', () => { + expect(simpleDate.fromString('01.01.2016').format()).toBe( + '01.01.2016', + ); + }); + + it('double digit dates as double digit values', () => { + expect(simpleDate.fromString('10.10.2016').format()).toBe( + '10.10.2016', + ); + }); + }); + + describe('does not accept', () => { + it('date format prepended anything other than digits', () => + expect(simpleDate.fromString('----10102016')).toBeNull()); + + it('date format appended anything after valid date', () => + expect(simpleDate.fromString('10102016----')).toBeNull()); + + it('date without year', () => + expect(simpleDate.fromString('10.10.')).toBeNull()); + + it('date without day', () => + expect(simpleDate.fromString('.10.2016')).toBeNull()); + + it('date without month', () => + expect(simpleDate.fromString('10..2016')).toBeNull()); + + it('date with 1 digit as year', () => + expect(simpleDate.fromString('10.10.6')).toBeNull()); + + it('date with 3 digits as year', () => + expect(simpleDate.fromString('10.10.206')).toBeNull()); + + it('date with more than 4 digits as year', () => + expect(simpleDate.fromString('10.10.201673829')).toBeNull()); + + it('date higher than 31', () => + expect(simpleDate.fromString('32.03.2015')).toBeNull()); + + it('february 29 in none-leap years', () => + expect(simpleDate.fromString('29.02.2015')).toBeNull()); + + it('month higher than 12', () => + expect(simpleDate.fromString('25.13.2015')).toBeNull()); + }); + + describe('accepts', () => { + it('single digit day', () => { + expect(simpleDate.fromString('5.04.2015').format()).toBe( + '05.04.2015', + ); + }); + + it('single digit month', () => { + expect(simpleDate.fromString('25.1.2015').format()).toBe( + '25.01.2015', + ); + }); + + it('double digit year', () => { + expect(simpleDate.fromString('10.10.17').format()).toBe( + '10.10.2017', + ); + }); + + it('no separators for 4 digit years', () => { + expect(simpleDate.fromString('10102016').format()).toBe( + '10.10.2016', + ); + }); + + it('no separators for 2 digit years', () => { + expect(simpleDate.fromString('101016').format()).toBe('10.10.2016'); + }); + + it('given separators for 4 digit years', () => { + '. -/'.split('').forEach(separator => { + const date = simpleDate.fromString( + `10${separator}10${separator}2016`, + ); + expect(date.format()).toBe(`10.10.2016`); + }); + }); + + it('given separators for 2 digit years', () => { + '. -/'.split('').forEach(separator => { + const date = simpleDate.fromString( + `10${separator}10${separator}16`, + ); + expect(date.format()).toBe('10.10.2016'); + }); + }); + }); + + describe('during last day of month', () => { + describe('given date from month with 30 days', () => { + it('parses', () => { + expect(simpleDate.fromString('01.09.2017')).not.toBeNull(); + }); + + it('formats', () => { + expect(simpleDate.fromString('01.09.2017').format()).toEqual( + '01.09.2017', + ); + }); + }); + + describe('given date from month with 28 days', () => { + it('parses', () => { + expect(simpleDate.fromString('05.02.2015')).not.toBeNull(); + }); + + it('formats', () => { + expect(simpleDate.fromString('05.02.2015').format()).toEqual( + '05.02.2015', + ); + }); + }); + }); +}); diff --git a/packages/ffe-datepicker-react/src/datelogic/simpledate.test.js b/packages/ffe-datepicker-react/src/datelogic/simpledate.test.js deleted file mode 100644 index 6e7dec7f0f..0000000000 --- a/packages/ffe-datepicker-react/src/datelogic/simpledate.test.js +++ /dev/null @@ -1,161 +0,0 @@ -/* eslint-env mocha */ - -import { assert } from 'chai'; -import { spy, useFakeTimers } from 'sinon'; -import simpleDate from './simpledate'; -import ErrorTypes from './error-types'; - -describe('simpleDate fromString', () => { - describe('triggers', () => { - it('onSuccess callback', () => { - const onSuccess = spy(); - const date = simpleDate.fromString('01.01.2016', onSuccess); - assert.isTrue(onSuccess.calledWith(date)); - }); - - it('onError callback with INVALID_DATE_FORMAT', () => { - const onError = spy(); - simpleDate.fromString('---', () => {}, onError); - assert.isTrue(onError.calledWith(ErrorTypes.INVALID_DATE_FORMAT)); - }); - - it('onError callback with INVALID_DATE', () => { - const onError = spy(); - simpleDate.fromString('29.02.2015', () => {}, onError); - assert.isTrue(onError.calledWith(ErrorTypes.INVALID_DATE)); - }); - }); - - describe('formats', () => { - it('single digit dates as double digit values', () => - assert.deepEqual( - simpleDate.fromString('01.01.2016').format(), - '01.01.2016', - )); - - it('double digit dates as double digit values', () => - assert.deepEqual( - simpleDate.fromString('10.10.2016').format(), - '10.10.2016', - )); - }); - - describe('does not accept', () => { - it('date format prepended anything other than digits', () => - assert.isNull(simpleDate.fromString('----10102016'))); - - it('date format appended anything after valid date', () => - assert.isNull(simpleDate.fromString('10102016----'))); - - it('date without year', () => - assert.isNull(simpleDate.fromString('10.10.'))); - - it('date without day', () => - assert.isNull(simpleDate.fromString('.10.2016'))); - - it('date without month', () => - assert.isNull(simpleDate.fromString('10..2016'))); - - it('date with 1 digit as year', () => - assert.isNull(simpleDate.fromString('10.10.6'))); - - it('date with 3 digits as year', () => - assert.isNull(simpleDate.fromString('10.10.206'))); - - it('date with more than 4 digits as year', () => - assert.isNull(simpleDate.fromString('10.10.201673829'))); - - it('date higher than 31', () => - assert.isNull(simpleDate.fromString('32.03.2015'))); - - it('february 29 in none-leap years', () => - assert.isNull(simpleDate.fromString('29.02.2015'))); - - it('month higher than 12', () => - assert.isNull(simpleDate.fromString('25.13.2015'))); - }); - - describe('accepts', () => { - it('single digit day', () => - assert.deepEqual( - simpleDate.fromString('5.04.2015').format(), - '05.04.2015', - )); - - it('single digit month', () => - assert.deepEqual( - simpleDate.fromString('25.1.2015').format(), - '25.01.2015', - )); - - it('double digit year', () => - assert.deepEqual( - simpleDate.fromString('10.10.17').format(), - '10.10.2017', - )); - - it('no separators for 4 digit years', () => - assert.deepEqual( - simpleDate.fromString('10102016').format(), - '10.10.2016', - )); - - it('no separators for 2 digit years', () => - assert.deepEqual( - simpleDate.fromString('101016').format(), - '10.10.2016', - )); - - it('given separators for 4 digit years', () => { - '. -/'.split('').forEach(separator => { - const date = simpleDate.fromString( - `10${separator}10${separator}2016`, - ); - assert.deepEqual(date.format(), `10.10.2016`); - }); - }); - - it('given separators for 2 digit years', () => { - '. -/'.split('').forEach(separator => { - const date = simpleDate.fromString( - `10${separator}10${separator}16`, - ); - assert.deepEqual(date.format(), '10.10.2016'); - }); - }); - }); - - describe('during last day of month', () => { - let clock; - - before(() => { - clock = useFakeTimers(new Date(2017, 6, 31).getTime()); - }); - - after(() => { - clock.restore(); - }); - - describe('given date from month with 30 days', () => { - it('parses', () => - assert.isNotNull(simpleDate.fromString('01.09.2017'))); - - it('formats', () => - assert.deepEqual( - simpleDate.fromString('01.09.2017').format(), - '01.09.2017', - )); - }); - - describe('given date from month with 28 days', () => { - it('parses', () => - assert.isNotNull(simpleDate.fromString('05.02.2015'))); - - it('formats', () => - assert.deepEqual( - simpleDate.fromString('05.02.2015').format(), - '05.02.2015', - )); - }); - }); -}); diff --git a/packages/ffe-datepicker-react/src/datepicker/Datepicker.spec.js b/packages/ffe-datepicker-react/src/datepicker/Datepicker.spec.js new file mode 100644 index 0000000000..c18cfc6c0c --- /dev/null +++ b/packages/ffe-datepicker-react/src/datepicker/Datepicker.spec.js @@ -0,0 +1,411 @@ +import { shallow, mount } from 'enzyme'; +import React from 'react'; + +import DateInput from '../input'; +import Calendar from '../calendar'; +import Datepicker from './Datepicker'; +import i18n from '../i18n/i18n'; +import ErrorTypes from '../datelogic/error-types'; + +const defaultProps = { + value: '', + onChange: () => {}, + language: 'nb', +}; + +const getShallowWrapper = props => + shallow(); +const getMountedWrapper = props => + mount(); + +const ERROR_CLASS = '.ffe-field-error-message'; + +describe('', () => { + describe('with empty value', () => { + it('renders a wrapper for the datepicker components', () => { + const wrapper = getShallowWrapper(); + expect(wrapper.find('.ffe-datepicker').exists()).toBe(true); + }); + + it('contains a single DateInput component', () => { + const wrapper = getShallowWrapper(); + expect(wrapper.find(DateInput)).toHaveLength(1); + }); + + it('does not contain a Calendar component', () => { + const wrapper = getShallowWrapper(); + expect(wrapper.find(Calendar).exists()).toBe(false); + }); + + it('does not have an error message', () => { + const wrapper = getShallowWrapper(); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(false); + }); + }); + + describe('with focus on DateInput', () => { + it('contains a Calendar', () => { + const wrapper = getMountedWrapper(); + const input = wrapper.find('input'); + input.simulate('focus'); + + expect(wrapper.find(Calendar)).toHaveLength(1); + }); + }); + + describe('with click on DateInput', () => { + it('contains a Calendar', () => { + const wrapper = getMountedWrapper(); + const input = wrapper.find('input'); + input.simulate('click'); + expect(wrapper.find(Calendar)).toHaveLength(1); + }); + }); + + describe('with click after errors', () => { + it('works when field contains invalid input', () => { + const wrapper = getMountedWrapper(); + const input = wrapper.find('input'); + wrapper.setProps({ value: 'invalid date' }); + + input.simulate('blur'); + input.simulate('click'); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + expect(wrapper.find(Calendar).exists()).toBe(true); + }); + }); + + describe('when input field changes', () => { + it('calls onChange method', () => { + const onChange = jest.fn(); + const wrapper = getMountedWrapper({ onChange }); + const input = wrapper.find('input'); + + input.simulate('change', { target: { value: '14.03.2017' } }); + + expect(onChange).toHaveBeenCalledTimes(1); + }); + }); + + describe('given prop', () => { + describe('calendarAbove', () => { + it('has correct calendar above class', () => { + const wrapper = getMountedWrapper({ calendarAbove: true }); + wrapper.find('input').simulate('focus'); + + expect( + wrapper + .find('.ffe-calendar--datepicker') + .hasClass('ffe-calendar--datepicker--above'), + ).toBe(true); + }); + }); + + describe('onError', () => { + it('runs the error callback', () => { + const onError = jest.fn(); + const wrapper = getMountedWrapper({ + value: 'iamturtles', + onError, + }); + + const input = wrapper.find('input'); + input.simulate('blur'); + + expect(onError).toHaveBeenCalledWith( + ErrorTypes.INVALID_DATE_FORMAT, + i18n.nb[ErrorTypes.INVALID_DATE_FORMAT], + ); + }); + }); + + describe('ariaInvalid', () => { + it('has correct aria-invalid value if given prop', () => { + const wrapper = getMountedWrapper({ ariaInvalid: true }); + expect(wrapper.find('input').prop('aria-invalid')).toBe('true'); + }); + }); + + describe('inputProps', () => { + it('is passed on to input field', () => { + const inputProps = { + className: 'customClass', + id: 'custom-input-id', + }; + const wrapper = getMountedWrapper({ inputProps }); + + expect(wrapper.find('input').hasClass('customClass')).toBe( + true, + ); + expect(wrapper.find('input').prop('id')).toBe( + 'custom-input-id', + ); + }); + }); + + describe('onValidationComplete', () => { + it('runs onValidationComplete with formatted and validated value', () => { + const onValidationComplete = jest.fn(); + const wrapper = getMountedWrapper({ onValidationComplete }); + + wrapper.setProps({ value: '14317' }); + + wrapper.find('input').simulate('blur'); + + expect(onValidationComplete.mock.calls[0][0]).toBe( + '14.03.2017', + ); + }); + }); + }); + + describe('validating input on blur', () => { + describe('with invalid value', () => { + it('has an error message', () => { + const wrapper = getMountedWrapper({ value: 'iamturtles' }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('hides error message if hideErrors prop is true', () => { + const wrapper = getMountedWrapper({ + value: 'iamturtles', + hideErrors: true, + }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(false); + }); + }); + + describe('with date', () => { + describe('below minimum date', () => { + it('has correct error-class', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2014', + minDate: '01.01.2016', + }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2014', + minDate: '01.01.2016', + }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).text()).toBe( + i18n.nb.MIN_DATE, + ); + }); + }); + + describe('above maximum date', () => { + it('has correct error-class', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2016', + maxDate: '01.01.2016', + }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2016', + maxDate: '01.01.2016', + }); + + wrapper.find('input').simulate('blur'); + + expect(wrapper.find(ERROR_CLASS).text()).toBe( + i18n.nb.MAX_DATE, + ); + }); + }); + }); + }); + describe('validate input on minDate prop change', () => { + describe('with minDate after maxDate', () => { + const overrides = { + value: '15.11.2014', + minDate: '01.11.2014', + maxDate: '01.12.2014', + }; + + it('has an error message', () => { + const wrapper = getMountedWrapper(overrides); + wrapper.setProps({ minDate: '01.01.2015' }); + wrapper.update(); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper(overrides); + wrapper.setProps({ minDate: '01.01.2015' }); + wrapper.update(); + expect(wrapper.find(ERROR_CLASS).text()).toBe(i18n.nb.MIN_DATE); + }); + + it('removes the error message', () => { + const wrapper = getMountedWrapper(overrides); + wrapper.setProps({ minDate: '01.01.2015' }); + wrapper.update(); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + + wrapper.setProps({ minDate: '01.01.2014' }); + wrapper.update(); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(false); + }); + }); + }); + + describe('validate input on maxDate prop change', () => { + describe('with maxDate before minDate', () => { + const overrides = { + value: '15.11.2014', + minDate: '01.11.2014', + maxDate: '01.12.2014', + }; + + it('has an error message', () => { + const wrapper = getMountedWrapper(overrides); + wrapper.setProps({ maxDate: '01.01.2014' }); + wrapper.update(); + + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper(overrides); + wrapper.setProps({ maxDate: '01.01.2014' }); + wrapper.update(); + + expect(wrapper.find(ERROR_CLASS).text()).toBe(i18n.nb.MAX_DATE); + }); + + describe('setting valid maxDate', () => { + it('removes the error message', () => { + const wrapper = getMountedWrapper(overrides); + + wrapper.setProps({ maxDate: '01.01.2014' }); + wrapper.update(); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + + wrapper.setProps({ maxDate: '01.12.2014' }); + wrapper.update(); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(false); + }); + }); + }); + }); + + describe('validate correct visibility of Calendar on DateInput blur', () => { + const openCalendarAndBlurDateInput = wrapper => { + const input = wrapper.find('input'); + input.simulate('click'); + input.simulate('blur'); + }; + + describe('should not be visible on invalid date value', () => { + it('has an error message', () => { + const wrapper = getMountedWrapper({ value: 'iamturtles' }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('hides error message if hideErrors prop is true', () => { + const wrapper = getMountedWrapper({ + value: 'iamturtles', + hideErrors: true, + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(false); + }); + + it('hides calendar', () => { + const wrapper = getMountedWrapper({ value: 'iamturtles' }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(Calendar).exists()).toBe(false); + }); + }); + + describe('should be visible with valid date value', () => { + describe('when date is below minimum date', () => { + it('has correct error-class', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2014', + minDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2014', + minDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).text()).toBe( + i18n.nb.MIN_DATE, + ); + }); + + it('has calendar open', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2014', + minDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(Calendar)).toHaveLength(1); + }); + }); + + describe('when date is above maximum date', () => { + it('has correct error-class', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2016', + maxDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).exists()).toBe(true); + }); + + it('has correct error-message', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2016', + maxDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(ERROR_CLASS).text()).toBe( + i18n.nb.MAX_DATE, + ); + }); + + it('has calendar open', () => { + const wrapper = getMountedWrapper({ + value: '31.12.2016', + maxDate: '01.01.2016', + }); + openCalendarAndBlurDateInput(wrapper); + expect(wrapper.find(Calendar)).toHaveLength(1); + }); + }); + }); + }); +}); diff --git a/packages/ffe-datepicker-react/src/datepicker/Datepicker.test.js b/packages/ffe-datepicker-react/src/datepicker/Datepicker.test.js deleted file mode 100644 index 8c7c36df54..0000000000 --- a/packages/ffe-datepicker-react/src/datepicker/Datepicker.test.js +++ /dev/null @@ -1,438 +0,0 @@ -/* eslint-env mocha */ -import { expect } from 'chai'; -import { shallow, mount } from 'enzyme'; -import { spy } from 'sinon'; -import React from 'react'; -import DateInput from '../input'; -import Calendar from '../calendar'; -import Datepicker from './Datepicker'; -import i18n from '../i18n/i18n'; -import ErrorTypes from '../datelogic/error-types'; - -describe('', () => { - const errorClass = '.ffe-field-error-message'; - - let defaultProps; - let wrapper; - - beforeEach(() => { - defaultProps = { - value: '', - onChange: () => {}, - language: 'nb', - }; - }); - - describe('with empty value', () => { - beforeEach(() => { - wrapper = shallow(); - }); - - it('renders a wrapper for the datepicker components', () => - expect(wrapper).to.have.descendants('.ffe-datepicker')); - - it('contains a single DateInput component', () => - expect(wrapper) - .to.have.exactly(1) - .descendants(DateInput)); - - it('does not contain a Calendar component', () => - expect(wrapper).to.not.have.descendants(Calendar)); - - it('does not have an error message', () => - expect(wrapper).to.not.have.descendants(errorClass)); - }); - - describe('with focus on DateInput', () => { - beforeEach(() => { - wrapper = mount(); - const input = wrapper.find(DateInput).find('input'); - input.simulate('focus'); - }); - - it('contains a Calendar', () => - expect(wrapper) - .to.have.exactly(1) - .descendants(Calendar)); - }); - - describe('with click on DateInput', () => { - beforeEach(() => { - wrapper = mount(); - const input = wrapper.find(DateInput).find('input'); - input.simulate('click'); - }); - - it('contains a Calendar', () => - expect(wrapper) - .to.have.exactly(1) - .descendants(Calendar)); - }); - - describe('with click after errors', () => { - let input; - - beforeEach(() => { - wrapper = mount(); - input = wrapper.find(DateInput).find('input'); - wrapper.setProps({ value: 'invalid date' }); - input.simulate('blur'); - input.simulate('click'); - }); - - it('works when field contains invalid input', () => { - expect(wrapper).to.have.descendants(errorClass); - expect(wrapper).to.have.descendants(Calendar); - }); - }); - - describe('when input field changes', () => { - let onChange; - - beforeEach(() => { - onChange = spy(); - wrapper = mount( - , - ); - const input = wrapper.find(DateInput).find('input'); - input.simulate('change', { target: { value: '14.03.2017' } }); - }); - - it('calls onChange method', () => - expect(onChange).to.have.been.calledOnce); - }); - - describe('given prop', () => { - describe('calendarAbove', () => { - let calendar; - - beforeEach(() => { - wrapper = mount( - , - ); - wrapper - .find(DateInput) - .find('input') - .simulate('focus'); - calendar = wrapper.find(Calendar); - }); - - it('has correct calendar above class', () => - expect(calendar).to.have.className( - 'ffe-calendar--datepicker--above', - )); - }); - - describe('onError', () => { - let onError; - - beforeEach(() => { - onError = spy(); - wrapper = mount( - , - ); - const input = wrapper.find(DateInput).find('input'); - input.simulate('blur'); - }); - - it('runs the error callback', () => - expect(onError).to.have.been.calledWithExactly( - ErrorTypes.INVALID_DATE_FORMAT, - i18n.nb[ErrorTypes.INVALID_DATE_FORMAT], - )); - }); - - describe('ariaInvalid', () => { - let input; - - beforeEach(() => { - wrapper = mount( - , - ); - input = wrapper.find(DateInput).find('input'); - }); - - it('has correct aria-invalid value if given prop', () => - expect(input).to.have.attr('aria-invalid', 'true')); - }); - - describe('inputProps', () => { - let input; - - beforeEach(() => { - wrapper = mount( - , - ); - input = wrapper.find(DateInput).find('input'); - }); - - it('is passed on to input field', () => { - expect(input).to.have.className('customClass'); - expect(input).to.have.id('custom-input-id'); - }); - }); - - describe('onValidationComplete', () => { - let onValidationComplete; - - beforeEach(() => { - onValidationComplete = spy(); - wrapper = mount( - , - ); - - wrapper.setProps({ value: '14317' }); - - const input = wrapper.find(DateInput).find('input'); - input.simulate('blur'); - }); - - it('runs onValidationComplete with formatted and validated value', () => { - expect(onValidationComplete).to.have.been.calledWith( - '14.03.2017', - ); - }); - }); - }); - - describe('validating input on blur', () => { - describe('with invalid value', () => { - beforeEach(() => { - wrapper = mount( - , - ); - - wrapper - .find(DateInput) - .find('input') - .simulate('blur'); - }); - - it('has an error message', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('hides error message if hideErrors prop is true', () => { - wrapper.setProps({ hideErrors: true }); - expect(wrapper).to.not.have.descendants(errorClass); - }); - }); - - describe('with date', () => { - let errorMessage; - - describe('below minimum date', () => { - beforeEach(() => { - wrapper = mount( - , - ); - - wrapper - .find(DateInput) - .find('input') - .simulate('blur'); - errorMessage = wrapper.find(errorClass); - }); - - it('has correct error-class', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => - expect(errorMessage).to.have.text(i18n.nb.MIN_DATE)); - }); - - describe('above maximum date', () => { - beforeEach(() => { - wrapper = mount( - , - ); - - wrapper - .find(DateInput) - .find('input') - .simulate('blur'); - errorMessage = wrapper.find(errorClass); - }); - - it('has correct error-class', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => - expect(errorMessage).to.have.text(i18n.nb.MAX_DATE)); - }); - }); - }); - describe('validate input on minDate prop change', () => { - describe('with minDate after maxDate', () => { - let errorMessage; - beforeEach(() => { - wrapper = mount( - , - ); - wrapper.setProps({ minDate: '01.01.2015' }); - wrapper.update(); - errorMessage = wrapper.find(errorClass); - }); - - it('has an error message', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => - expect(errorMessage).to.have.text(i18n.nb.MIN_DATE)); - - describe('setting valid minDate', () => { - beforeEach(() => { - wrapper.setProps({ minDate: '01.11.2014' }); - wrapper.update(); - }); - - it('removes the error message', () => - expect(wrapper).not.to.have.descendants(errorClass)); - }); - }); - }); - - describe('validate input on maxDate prop change', () => { - describe('with maxDate before minDate', () => { - let errorMessage; - beforeEach(() => { - wrapper = mount( - , - ); - wrapper.setProps({ maxDate: '01.01.2014' }); - wrapper.update(); - errorMessage = wrapper.find(errorClass); - }); - - it('has an error message', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => - expect(errorMessage).to.have.text(i18n.nb.MAX_DATE)); - - describe('setting valid maxDate', () => { - beforeEach(() => { - wrapper.setProps({ maxDate: '01.12.2014' }); - wrapper.update(); - }); - it('removes the error message', () => - expect(wrapper).not.to.have.descendants(errorClass)); - }); - }); - }); - - describe('validate correct visibility of Calendar on DateInput blur', () => { - const openCalendarAndBlurDateInput = datepicker => { - const input = wrapper.find(DateInput).find('input'); - input.simulate('click'); - input.simulate('blur'); - }; - describe('should not be visible on invalid date value', () => { - beforeEach(() => { - wrapper = mount( - , - ); - openCalendarAndBlurDateInput(wrapper); - }); - - it('has an error message', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('hides error message if hideErrors prop is true', () => { - wrapper.setProps({ hideErrors: true }); - expect(wrapper).to.not.have.descendants(errorClass); - }); - - it('hides calendar', () => { - expect(wrapper).to.not.have.descendants(Calendar); - }); - }); - - describe('should be visible with valid date value', () => { - let errorMessage; - - describe('when date is below minimum date', () => { - beforeEach(() => { - wrapper = mount( - , - ); - openCalendarAndBlurDateInput(wrapper); - errorMessage = wrapper.find(errorClass); - }); - - it('has correct error-class', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => { - expect(errorMessage).to.have.text(i18n.nb.MIN_DATE); - expect(wrapper).to.have.descendants(Calendar); - }); - - it('has calendar open', () => - expect(wrapper) - .to.have.exactly(1) - .descendants(Calendar)); - }); - - describe('when date is above maximum date', () => { - beforeEach(() => { - wrapper = mount( - , - ); - - openCalendarAndBlurDateInput(wrapper); - errorMessage = wrapper.find(errorClass); - }); - - it('has correct error-class', () => - expect(wrapper).to.have.descendants(errorClass)); - - it('has correct error-message', () => - expect(errorMessage).to.have.text(i18n.nb.MAX_DATE)); - - it('has calendar open', () => - expect(wrapper) - .to.have.exactly(1) - .descendants(Calendar)); - }); - }); - }); -}); diff --git a/packages/ffe-datepicker-react/src/input/Input.test.js b/packages/ffe-datepicker-react/src/input/Input.spec.js similarity index 71% rename from packages/ffe-datepicker-react/src/input/Input.test.js rename to packages/ffe-datepicker-react/src/input/Input.spec.js index 5fa7d6abbc..33d1ce717f 100644 --- a/packages/ffe-datepicker-react/src/input/Input.test.js +++ b/packages/ffe-datepicker-react/src/input/Input.spec.js @@ -1,8 +1,4 @@ -/* eslint-env mocha */ - import { shallow } from 'enzyme'; -import { expect } from 'chai'; -import sinon from 'sinon'; import React from 'react'; import Input from './Input'; @@ -23,33 +19,33 @@ const getWrapper = props => shallow(); describe('', () => { it('should render a wrapper for the input field', () => { const wrapper = getWrapper(); - expect(wrapper.hasClass('ffe-dateinput')).to.equal(true); + expect(wrapper.hasClass('ffe-dateinput')).toBe(true); }); describe('nested input field', () => { it('should be a single input field', () => { const input = getWrapper().find('input'); - expect(input.length).to.equal(1); + expect(input).toHaveLength(1); }); it('should have BEM element class name', () => { const input = getWrapper().find('input'); - expect(input.hasClass('ffe-dateinput__field')).to.equal(true); + expect(input.hasClass('ffe-dateinput__field')).toBe(true); }); it('should have given value', () => { const input = getWrapper().find('input'); - expect(input.prop('value')).to.equal('2016-03-07'); + expect(input.prop('value')).toBe('2016-03-07'); }); it('should have property from input props', () => { const input = getWrapper().find('input'); - expect(input.prop('placeholder')).to.equal('Given placeholder'); + expect(input.prop('placeholder')).toBe('Given placeholder'); }); it('should have given aria-invalid', () => { const input = getWrapper().find('input'); - expect(input.prop('aria-invalid')).to.equal('false'); + expect(input.prop('aria-invalid')).toBe('false'); }); it('should fall back to use ariaInvalid prop if aria-invalid is not set', () => { @@ -57,33 +53,33 @@ describe('', () => { 'aria-invalid': undefined, ariaInvalid: true, }).find('input'); - expect(input.prop('aria-invalid')).to.equal('true'); + expect(input.prop('aria-invalid')).toBe('true'); }); it('should have class name from input props', () => { const input = getWrapper().find('input'); - expect(input.hasClass('given-class-name')).to.equal(true); + expect(input.hasClass('given-class-name')).toBe(true); }); it('should delegate change events', () => { - const spy = sinon.spy(); + const spy = jest.fn(); const input = getWrapper({ onChange: spy }).find('input'); input.simulate('change'); - expect(spy.calledOnce).to.equal(true); + expect(spy).toHaveBeenCalledTimes(1); }); it('should delegate focus events', () => { - const spy = sinon.spy(); + const spy = jest.fn(); const input = getWrapper({ onFocus: spy }).find('input'); input.simulate('focus'); - expect(spy.calledOnce).to.equal(true); + expect(spy).toHaveBeenCalledTimes(1); }); it('should delegate key down events', () => { - const spy = sinon.spy(); + const spy = jest.fn(); const input = getWrapper({ onKeyDown: spy }).find('input'); input.simulate('keypress'); - expect(spy.calledOnce).to.equal(true); + expect(spy).toHaveBeenCalledTimes(1); }); }); }); diff --git a/packages/ffe-datepicker-react/src/util/test-setup.js b/packages/ffe-datepicker-react/src/util/test-setup.js deleted file mode 100644 index 5ed6c270ba..0000000000 --- a/packages/ffe-datepicker-react/src/util/test-setup.js +++ /dev/null @@ -1,14 +0,0 @@ -import { JSDOM } from 'jsdom'; -import chai from 'chai'; -import sinonChai from 'sinon-chai'; -import chaiEnzyme from 'chai-enzyme'; -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -chai.use(chaiEnzyme()); -chai.use(sinonChai); - -global.window = new JSDOM('').window; -global.document = global.window.document; - -Enzyme.configure({ adapter: new Adapter() }); diff --git a/packages/ffe-datepicker-react/test-setup.js b/packages/ffe-datepicker-react/test-setup.js new file mode 100644 index 0000000000..fc7b0dce1f --- /dev/null +++ b/packages/ffe-datepicker-react/test-setup.js @@ -0,0 +1,4 @@ +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; + +Enzyme.configure({ adapter: new Adapter() });