From 71dcb6c140942ec5c2c5770537823d849a1d6a57 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Sun, 29 Oct 2017 18:56:24 +0000 Subject: [PATCH] Minor test tweaks --- src/scripts/src/actions/choices.test.js | 2 +- src/scripts/src/actions/groups.test.js | 2 +- src/scripts/src/actions/items.test.js | 2 +- src/scripts/src/actions/misc.test.js | 2 +- src/scripts/src/choices.js | 138 +- src/scripts/src/choices.test.backup.js | 1114 ++++++++++++++++ src/scripts/src/choices.test.js | 1168 +---------------- src/scripts/src/components/container.test.js | 2 +- src/scripts/src/components/dropdown.test.js | 2 +- src/scripts/src/components/input.test.js | 2 +- src/scripts/src/components/list.test.js | 2 +- .../src/components/wrapped-element.test.js | 43 +- .../src/components/wrapped-input.test.js | 2 +- .../src/components/wrapped-select.test.js | 2 +- src/scripts/src/reducers/choices.test.js | 2 +- src/scripts/src/reducers/groups.test.js | 2 +- src/scripts/src/reducers/index.test.js | 2 +- src/scripts/src/reducers/items.test.js | 3 +- src/scripts/src/store/store.test.js | 2 +- 19 files changed, 1300 insertions(+), 1194 deletions(-) create mode 100644 src/scripts/src/choices.test.backup.js diff --git a/src/scripts/src/actions/choices.test.js b/src/scripts/src/actions/choices.test.js index 3061ddb..14dd37e 100644 --- a/src/scripts/src/actions/choices.test.js +++ b/src/scripts/src/actions/choices.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as actions from './choices'; -describe('choice actions', () => { +describe('actions/choices', () => { describe('addChoice action', () => { it('returns ADD_CHOICE action', () => { const value = 'test'; diff --git a/src/scripts/src/actions/groups.test.js b/src/scripts/src/actions/groups.test.js index 381acea..815561f 100644 --- a/src/scripts/src/actions/groups.test.js +++ b/src/scripts/src/actions/groups.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as actions from './groups'; -describe('group actions', () => { +describe('actions/groups', () => { describe('addGroup action', () => { it('returns ADD_GROUP action', () => { const value = 'test'; diff --git a/src/scripts/src/actions/items.test.js b/src/scripts/src/actions/items.test.js index 57f2c6d..887a76a 100644 --- a/src/scripts/src/actions/items.test.js +++ b/src/scripts/src/actions/items.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as actions from './items'; -describe('item actions', () => { +describe('actions/items', () => { describe('addItem action', () => { it('returns ADD_ITEM action', () => { const value = 'test'; diff --git a/src/scripts/src/actions/misc.test.js b/src/scripts/src/actions/misc.test.js index b19b5a1..029f1ef 100644 --- a/src/scripts/src/actions/misc.test.js +++ b/src/scripts/src/actions/misc.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as actions from './misc'; -describe('misc actions', () => { +describe('actions/misc', () => { describe('clearAll action', () => { it('returns CLEAR_ALL action', () => { const expectedAction = { diff --git a/src/scripts/src/choices.js b/src/scripts/src/choices.js index 81f2c78..c538dde 100644 --- a/src/scripts/src/choices.js +++ b/src/scripts/src/choices.js @@ -997,6 +997,26 @@ class Choices { }); } + /** + * Select placeholder choice + */ + _selectPlaceholderChoice() { + const placeholderChoice = this.store.getPlaceholderChoice(); + + if (placeholderChoice) { + this._addItem( + placeholderChoice.value, + placeholderChoice.label, + placeholderChoice.id, + placeholderChoice.groupId, + null, + placeholderChoice.placeholder, + ); + this._triggerChange(placeholderChoice.value); + } + } + + /** * Process enter/click of an item button * @param {Array} activeItems The currently active items @@ -1026,25 +1046,6 @@ class Choices { } } - /** - * Select placeholder choice - */ - _selectPlaceholderChoice() { - const placeholderChoice = this.store.getPlaceholderChoice(); - - if (placeholderChoice) { - this._addItem( - placeholderChoice.value, - placeholderChoice.label, - placeholderChoice.id, - placeholderChoice.groupId, - null, - placeholderChoice.placeholder, - ); - this._triggerChange(placeholderChoice.value); - } - } - /** * Process click of an item * @param {Array} activeItems The currently active items @@ -1160,6 +1161,38 @@ class Choices { } } + /** + * Apply or remove a loading state to the component. + * @param {Boolean} isLoading default value set to 'true'. + * @return + * @private + */ + _handleLoadingState(isLoading = true) { + let placeholderItem = this.itemList.getChild(`.${this.config.classNames.placeholder}`); + if (isLoading) { + this.containerOuter.addLoadingState(); + if (this.isSelectOneElement) { + if (!placeholderItem) { + placeholderItem = this._getTemplate('placeholder', this.config.loadingText); + this.itemList.append(placeholderItem); + } else { + placeholderItem.innerHTML = this.config.loadingText; + } + } else { + this.input.setPlaceholder(this.config.loadingText); + } + } else { + this.containerOuter.removeLoadingState(); + + if (this.isSelectOneElement) { + placeholderItem.innerHTML = (this.placeholder || ''); + } else { + this.input.setPlaceholder(this.placeholder || ''); + } + } + } + + /** * Validates whether an item can be added by a user * @param {Array} activeItems The currently active items @@ -1218,37 +1251,6 @@ class Choices { }; } - /** - * Apply or remove a loading state to the component. - * @param {Boolean} isLoading default value set to 'true'. - * @return - * @private - */ - _handleLoadingState(isLoading = true) { - let placeholderItem = this.itemList.getChild(`.${this.config.classNames.placeholder}`); - if (isLoading) { - this.containerOuter.addLoadingState(); - if (this.isSelectOneElement) { - if (!placeholderItem) { - placeholderItem = this._getTemplate('placeholder', this.config.loadingText); - this.itemList.append(placeholderItem); - } else { - placeholderItem.innerHTML = this.config.loadingText; - } - } else { - this.input.setPlaceholder(this.config.loadingText); - } - } else { - this.containerOuter.removeLoadingState(); - - if (this.isSelectOneElement) { - placeholderItem.innerHTML = (this.placeholder || ''); - } else { - this.input.setPlaceholder(this.placeholder || ''); - } - } - } - /** * Retrieve the callback used to populate component's choices in an async way. * @returns {Function} The callback as a function. @@ -1708,6 +1710,24 @@ class Choices { } } + /** + * Mouse over (hover) event + * @param {Object} e Event + * @return + * @private + */ + _onMouseOver(e) { + // If the dropdown is either the target or one of its children is the target + const targetWithinDropdown = ( + e.target === this.dropdown || this.dropdown.element.contains(e.target) + ); + const shouldHighlightChoice = targetWithinDropdown && e.target.hasAttribute('data-choice'); + + if (shouldHighlightChoice) { + this._highlightChoice(e.target); + } + } + /** * Click event * @param {Object} e Event @@ -1756,24 +1776,6 @@ class Choices { } } - /** - * Mouse over (hover) event - * @param {Object} e Event - * @return - * @private - */ - _onMouseOver(e) { - // If the dropdown is either the target or one of its children is the target - const targetWithinDropdown = ( - e.target === this.dropdown || this.dropdown.element.contains(e.target) - ); - const shouldHighlightChoice = targetWithinDropdown && e.target.hasAttribute('data-choice'); - - if (shouldHighlightChoice) { - this._highlightChoice(e.target); - } - } - /** * Focus event * @param {Object} e Event diff --git a/src/scripts/src/choices.test.backup.js b/src/scripts/src/choices.test.backup.js new file mode 100644 index 0000000..fdcd03d --- /dev/null +++ b/src/scripts/src/choices.test.backup.js @@ -0,0 +1,1114 @@ +/* eslint-disable no-unused-expressions */ +import 'whatwg-fetch'; +import 'es6-promise'; +import 'core-js/fn/object/assign'; +import 'custom-event-autopolyfill'; +import { expect } from 'chai'; +import sinon from 'sinon'; + +import Choices from './choices'; +import Dropdown from './components/dropdown'; +import Container from './components/container'; +import Input from './components/input'; +import List from './components/list'; +import WrappedInput from './components/wrapped-input'; +import WrappedSelect from './components/wrapped-select'; + +describe('Choices', () => { + describe('initialize Choices', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('input'); + input.type = 'text'; + input.className = 'js-choices'; + + document.body.appendChild(input); + instance = new Choices(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should be defined', () => { + expect(instance).to.not.be.undefined; + }); + + it('should have initialised', () => { + expect(instance.initialised).to.be.true; + }); + + it('should not re-initialise if passed element again', () => { + const reinitialise = new Choices(instance.passedElement.element); + sinon.spy(reinitialise, '_createTemplates'); + expect(reinitialise._createTemplates.callCount).to.equal(0); + }); + + it('should have a blank state', () => { + expect(instance.currentState.items.length).to.equal(0); + expect(instance.currentState.groups.length).to.equal(0); + expect(instance.currentState.choices.length).to.equal(0); + }); + + it('should have config options', () => { + expect(instance.config.silent).to.be.a('boolean'); + expect(instance.config.items).to.be.an('array'); + expect(instance.config.choices).to.be.an('array'); + expect(instance.config.renderChoiceLimit).to.be.a('number'); + expect(instance.config.maxItemCount).to.be.a('number'); + expect(instance.config.addItems).to.be.a('boolean'); + expect(instance.config.removeItems).to.be.a('boolean'); + expect(instance.config.removeItemButton).to.be.a('boolean'); + expect(instance.config.editItems).to.be.a('boolean'); + expect(instance.config.duplicateItems).to.be.a('boolean'); + expect(instance.config.delimiter).to.be.a('string'); + expect(instance.config.paste).to.be.a('boolean'); + expect(instance.config.searchEnabled).to.be.a('boolean'); + expect(instance.config.searchChoices).to.be.a('boolean'); + expect(instance.config.searchFloor).to.be.a('number'); + expect(instance.config.searchResultLimit).to.be.a('number'); + expect(instance.config.searchFields, 'should be string or array').to.satisfy(searchFields => + Array.isArray(searchFields) || typeof searchFields === 'string'); + expect(instance.config.position).to.be.a('string'); + expect(instance.config.regexFilter).to.be.null; + expect(instance.config.sortFilter).to.be.a('function'); + expect(instance.config.shouldSort).to.be.a('boolean'); + expect(instance.config.shouldSortItems).to.be.a('boolean'); + expect(instance.config.placeholder).to.be.a('boolean'); + expect(instance.config.placeholderValue).to.be.null; + expect(instance.config.prependValue).to.be.null; + expect(instance.config.appendValue).to.be.null; + expect(instance.config.renderSelectedChoices).to.be.a('string'); + expect(instance.config.loadingText).to.be.a('string'); + expect(instance.config.noResultsText).to.be.a('string'); + expect(instance.config.noChoicesText).to.be.a('string'); + expect(instance.config.itemSelectText).to.be.a('string'); + expect(instance.config.classNames).to.be.an('object'); + expect(instance.config.callbackOnInit).to.be.null; + expect(instance.config.callbackOnCreateTemplates).to.be.null; + }); + + it('should expose public methods', () => { + expect(instance.init).to.be.a('function'); + expect(instance.destroy).to.be.a('function'); + expect(instance.render).to.be.a('function'); + expect(instance.renderGroups).to.be.a('function'); + expect(instance.renderItems).to.be.a('function'); + expect(instance.renderChoices).to.be.a('function'); + expect(instance.highlightItem).to.be.a('function'); + expect(instance.unhighlightItem).to.be.a('function'); + expect(instance.highlightAll).to.be.a('function'); + expect(instance.unhighlightAll).to.be.a('function'); + expect(instance.removeItemsByValue).to.be.a('function'); + expect(instance.removeActiveItems).to.be.a('function'); + expect(instance.removeHighlightedItems).to.be.a('function'); + expect(instance.showDropdown).to.be.a('function'); + expect(instance.hideDropdown).to.be.a('function'); + expect(instance.toggleDropdown).to.be.a('function'); + expect(instance.getValue).to.be.a('function'); + expect(instance.setValue).to.be.a('function'); + expect(instance.setValueByChoice).to.be.a('function'); + expect(instance.setChoices).to.be.a('function'); + expect(instance.disable).to.be.a('function'); + expect(instance.enable).to.be.a('function'); + expect(instance.ajax).to.be.a('function'); + expect(instance.clearStore).to.be.a('function'); + expect(instance.clearInput).to.be.a('function'); + }); + + it('should hide passed input', () => { + expect(instance.passedElement.element.style.display).to.equal('none'); + }); + + it('should create an outer container', () => { + expect(instance.containerOuter).to.be.an.instanceof(Container); + }); + + it('should create an inner container', () => { + expect(instance.containerInner).to.be.an.instanceof(Container); + }); + + it('should create a choice list', () => { + expect(instance.choiceList).to.be.an.instanceof(List); + }); + + it('should create an item list', () => { + expect(instance.itemList).to.be.an.instanceof(List); + }); + + it('should create an input', () => { + expect(instance.input).to.be.an.instanceof(Input); + }); + + it('should create a dropdown', () => { + expect(instance.dropdown).to.be.an.instanceof(Dropdown); + }); + + it('should backup and recover original styles', () => { + const origStyle = 'background-color: #ccc; margin: 5px padding: 10px;'; + + instance.destroy(); + input.setAttribute('style', origStyle); + instance = new Choices(input); + + let style = input.getAttribute('data-choice-orig-style'); + expect(style).to.equal(origStyle); + + instance.destroy(); + style = input.getAttribute('data-choice-orig-style'); + expect(style).to.be.null; + + style = input.getAttribute('style'); + expect(style).to.equal(origStyle); + }); + }); + + describe('should accept text inputs', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('input'); + input.type = 'text'; + input.className = 'js-choices'; + input.placeholder = 'Placeholder text'; + + document.body.appendChild(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should wrap passed input', () => { + instance = new Choices(input); + expect(instance.passedElement).to.be.an.instanceof(WrappedInput); + }); + + it('should accept a user inputted value', () => { + instance = new Choices(input); + + instance.input.element.focus(); + instance.input.element.value = 'test'; + + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + expect(instance.currentState.items[0].value).to.include(instance.input.element.value); + }); + + it('should copy the passed placeholder to the cloned input', () => { + instance = new Choices(input); + + expect(instance.input.element.placeholder).to.equal(input.placeholder); + }); + + it('should not allow duplicates if duplicateItems is false', () => { + instance = new Choices(input, { + duplicateItems: false, + items: ['test 1'], + }); + + instance.input.element.focus(); + instance.input.element.value = 'test 1'; + + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + expect(instance.currentState.items[instance.currentState.items.length - 1].value).to.equal(instance.input.element.value); + }); + + it('should filter input if regexFilter is passed', () => { + instance = new Choices(input, { + regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + }); + + instance.input.element.focus(); + instance.input.element.value = 'josh@joshuajohnson.co.uk'; + + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + instance.input.element.focus(); + instance.input.element.value = 'not an email address'; + + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + const lastItem = instance.currentState.items[instance.currentState.items.length - 1]; + + expect(lastItem.value).to.equal('josh@joshuajohnson.co.uk'); + expect(lastItem.value).not.to.equal('not an email address'); + }); + + it('should prepend and append values if passed', () => { + instance = new Choices(input, { + prependValue: 'item-', + appendValue: '-value', + }); + + instance.input.element.focus(); + instance.input.element.value = 'test'; + + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + const lastItem = instance.currentState.items[instance.currentState.items.length - 1]; + + expect(lastItem.value).not.to.equal('test'); + expect(lastItem.value).to.equal('item-test-value'); + }); + }); + + describe('should accept single select inputs', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.placeholder = 'Placeholder text'; + + for (let i = 1; i < 4; i++) { + const option = document.createElement('option'); + + option.value = `Value ${i}`; + option.innerHTML = `Label ${i}`; + + input.appendChild(option); + } + + document.body.appendChild(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should wrap passed input', () => { + instance = new Choices(input); + expect(instance.passedElement).to.be.an.instanceof(WrappedSelect); + }); + + it('should open the choice list on focusing', () => { + instance = new Choices(input); + instance.input.element.focus(); + expect(instance.dropdown.element.classList.contains(instance.config.classNames.activeState)).to.be.true; + }); + + it('should select the first choice', () => { + instance = new Choices(input); + expect(instance.currentState.items[0].value).to.include('Value 1'); + }); + + it('should highlight the choices on keydown', () => { + instance = new Choices(input, { + renderChoiceLimit: -1, + }); + instance.input.element.focus(); + + for (let i = 0; i < 2; i++) { + // Key down to third choice + instance._onKeyDown({ + target: instance.input.element, + keyCode: 40, + ctrlKey: false, + preventDefault: () => {}, + }); + } + + expect(instance.highlightPosition).to.equal(2); + }); + + it('should select choice on enter key press', () => { + instance = new Choices(input); + instance.input.element.focus(); + + // Key down to second choice + instance._onKeyDown({ + target: instance.input.element, + keyCode: 40, + ctrlKey: false, + preventDefault: () => {}, + }); + + // Key down to select choice + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + preventDefault: () => {}, + }); + + expect(instance.currentState.items.length).to.equal(2); + }); + + it('should trigger add/change event on selection', () => { + instance = new Choices(input); + + const onChangeStub = sinon.stub(); + const addSpyStub = sinon.stub(); + const passedElement = instance.passedElement; + + passedElement.element.addEventListener('change', onChangeStub); + passedElement.element.addEventListener('addItem', addSpyStub); + + instance.input.element.focus(); + + // Key down to second choice + instance._onKeyDown({ + target: instance.input.element, + keyCode: 40, + ctrlKey: false, + preventDefault: () => {}, + }); + + // Key down to select choice + instance._onKeyDown({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + preventDefault: () => {}, + }); + + const returnValue = onChangeStub.lastCall.args[0].detail.value; + expect(returnValue).to.be.a('string'); + expect(onChangeStub.callCount).to.equal(1); + expect(addSpyStub.callCount).to.equal(1); + }); + + it('should open the dropdown on click', () => { + instance = new Choices(input); + const container = instance.containerOuter.element; + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + expect(document.activeElement === instance.input.element && container.classList.contains('is-open')).to.be.true; + }); + + it('should close the dropdown on double click', () => { + instance = new Choices(input); + const container = instance.containerOuter.element; + const openState = instance.config.classNames.openState; + + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + expect(document.activeElement === instance.input.element && container.classList.contains(openState)).to.be.false; + }); + + it('should trigger showDropdown on dropdown opening', () => { + instance = new Choices(input); + const container = instance.containerOuter.element; + + const showDropdownStub = sinon.spy(); + const passedElement = instance.passedElement; + + passedElement.element.addEventListener('showDropdown', showDropdownStub); + + instance.input.focus(); + + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + expect(showDropdownStub.callCount).to.equal(1); + }); + + it('should trigger hideDropdown on dropdown closing', () => { + instance = new Choices(input); + + const container = instance.containerOuter.element; + const hideDropdownStub = sinon.stub(); + const passedElement = instance.passedElement; + + passedElement.element.addEventListener('hideDropdown', hideDropdownStub); + + instance.input.element.focus(); + + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + instance._onClick({ + target: container, + ctrlKey: false, + preventDefault: () => {}, + }); + + expect(hideDropdownStub.callCount).to.equal(1); + }); + + it('should filter choices when searching', () => { + instance = new Choices(input); + + const onSearchStub = sinon.spy(); + const passedElement = instance.passedElement; + + passedElement.element.addEventListener('search', onSearchStub); + + instance.input.element.focus(); + instance.input.element.value = '3 '; + + // Key down to search + instance._onKeyUp({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + const mostAccurateResult = instance.currentState.choices.find(choice => choice.active); + + expect(instance.isSearching && mostAccurateResult.value === 'Value 3').to.be.true; + expect(onSearchStub.callCount).to.equal(1); + }); + + it('shouldn\'t filter choices when searching', () => { + instance = new Choices(input, { + searchChoices: false, + }); + + instance.setValue(['Javascript', 'HTML', 'Jasmine']); + + const onSearchStub = sinon.spy(); + const passedElement = instance.passedElement; + + passedElement.element.addEventListener('search', onSearchStub); + + instance.input.element.focus(); + instance.input.element.value = 'Javascript'; + + // Key down to search + instance._onKeyUp({ + target: instance.input.element, + keyCode: 13, + ctrlKey: false, + }); + + const activeOptions = instance.currentState.choices.filter(choice => choice.active); + + expect(activeOptions.length).to.equal(instance.currentState.choices.length); + expect(onSearchStub.callCount).to.equal(1); + }); + + it('shouldn\'t sort choices if shouldSort is false', () => { + instance = new Choices(input, { + shouldSort: false, + choices: [ + { + value: 'Value 5', + label: 'Label Five', + }, { + value: 'Value 6', + label: 'Label Six', + }, { + value: 'Value 7', + label: 'Label Seven', + }, + ], + }); + + expect(instance.currentState.choices[0].value).to.equal('Value 5'); + }); + + it('should sort choices if shouldSort is true', () => { + instance = new Choices(input, { + shouldSort: true, + choices: [ + { + value: 'Value 5', + label: 'Label Five', + }, { + value: 'Value 6', + label: 'Label Six', + }, { + value: 'Value 7', + label: 'Label Seven', + }, + ], + }); + + expect(instance.currentState.choices[0].value).to.equal('Value 1'); + }); + }); + + describe('should accept multiple select inputs', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.setAttribute('multiple', ''); + + for (let i = 1; i < 4; i++) { + const option = document.createElement('option'); + + option.value = `Value ${i}`; + option.innerHTML = `Value ${i}`; + + if (i % 2) { + option.selected = true; + } + + input.appendChild(option); + } + + document.body.appendChild(input); + + instance = new Choices(input, { + placeholderValue: 'Placeholder text', + choices: [ + { + value: 'One', + label: 'Label One', + selected: true, + disabled: false, + }, { + value: 'Two', + label: 'Label Two', + disabled: true, + }, { + value: 'Three', + label: 'Label Three', + }, + ], + }); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should wrap passed input', () => { + expect(instance.passedElement).to.be.an.instanceof(WrappedSelect); + }); + + it('should add any pre-defined values', () => { + expect(instance.currentState.items.length).to.be.above(1); + }); + + it('should add options defined in the config + pre-defined options', () => { + expect(instance.currentState.choices.length).to.equal(6); + }); + + it('should add a placeholder defined in the config to the search input', () => { + expect(instance.input.element.placeholder).to.equal('Placeholder text'); + }); + }); + + describe('should handle public methods on select input types', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.multiple = true; + input.placeholder = 'Placeholder text'; + + for (let i = 1; i < 10; i++) { + const option = document.createElement('option'); + + option.value = `Value ${i}`; + option.innerHTML = `Value ${i}`; + + if (i % 2) { + option.selected = true; + } + + input.appendChild(option); + } + + document.body.appendChild(input); + instance = new Choices(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should handle highlightItem()', () => { + const items = instance.currentState.items; + const randomItem = items[Math.floor(Math.random() * items.length)]; + + instance.highlightItem(randomItem); + + expect(randomItem.highlighted).to.be.true; + }); + + it('should handle unhighlightItem()', () => { + const items = instance.currentState.items; + const randomItem = items[Math.floor(Math.random() * items.length)]; + + instance.unhighlightItem(randomItem); + + expect(randomItem.highlighted).to.be.false; + }); + + it('should handle highlightAll()', () => { + const items = instance.currentState.items; + + instance.highlightAll(); + + const unhighlightedItems = items.some(item => item.highlighted === false); + + expect(unhighlightedItems).to.be.false; + }); + + it('should handle unhighlightAll()', () => { + const items = instance.currentState.items; + + instance.unhighlightAll(); + + const highlightedItems = items.some(item => item.highlighted === true); + + expect(highlightedItems).to.be.false; + }); + + it('should handle removeHighlightedItems()', () => { + const items = instance.currentState.items; + instance.highlightAll(); + instance.removeHighlightedItems(); + + const activeItems = items.some(item => item.active === true); + + expect(activeItems).to.be.false; + }); + + it('should handle showDropdown()', () => { + instance.showDropdown(); + + const hasOpenState = instance.containerOuter.element.classList.contains(instance.config.classNames.openState); + const hasAttr = instance.containerOuter.element.getAttribute('aria-expanded') === 'true'; + const hasActiveState = instance.dropdown.element.classList.contains(instance.config.classNames.activeState); + + expect(hasOpenState && hasAttr && hasActiveState).to.be.true; + }); + + it('should handle hideDropdown()', () => { + instance.showDropdown(); + instance.hideDropdown(); + + const hasOpenState = instance.containerOuter.element.classList.contains(instance.config.classNames.openState); + const hasAttr = instance.containerOuter.element.getAttribute('aria-expanded') === 'true'; + const hasActiveState = instance.dropdown.element.classList.contains(instance.config.classNames.activeState); + + + expect(hasOpenState && hasAttr && hasActiveState).to.be.false; + }); + + it('should handle toggleDropdown()', () => { + sinon.spy(instance, 'hideDropdown'); + instance.showDropdown(); + instance.toggleDropdown(); + expect(instance.hideDropdown.callCount).to.equal(1); + }); + + it('should handle getValue()', () => { + const valueObjects = instance.getValue(); + const valueStrings = instance.getValue(true); + + expect(valueStrings[0]).to.be.a('string'); + expect(valueObjects[0]).to.be.an('object'); + expect(valueObjects).to.be.an('array'); + expect(valueObjects.length).to.equal(5); + }); + + it('should handle setValue()', () => { + instance.setValue(['Set value 1', 'Set value 2', 'Set value 3']); + const valueStrings = instance.getValue(true); + + expect(valueStrings[valueStrings.length - 1]).to.equal('Set value 3'); + expect(valueStrings[valueStrings.length - 2]).to.equal('Set value 2'); + expect(valueStrings[valueStrings.length - 3]).to.equal('Set value 1'); + }); + + it('should handle setValueByChoice()', () => { + const choices = instance.store.getChoicesFilteredByActive(); + const randomChoice = choices[Math.floor(Math.random() * choices.length)]; + + instance.highlightAll(); + instance.removeHighlightedItems(); + instance.setValueByChoice(randomChoice.value); + + const value = instance.getValue(true); + + expect(value[0]).to.equal(randomChoice.value); + }); + + it('should handle setChoices()', () => { + instance.setChoices([{ + label: 'Group one', + id: 1, + disabled: false, + choices: [ + { + value: 'Child One', + label: 'Child One', + selected: true, + }, { + value: 'Child Two', + label: 'Child Two', + disabled: true, + }, { + value: 'Child Three', + label: 'Child Three', + }, + ], + }, { + label: 'Group two', + id: 2, + disabled: false, + choices: [ + { + value: 'Child Four', + label: 'Child Four', + disabled: true, + }, { + value: 'Child Five', + label: 'Child Five', + }, { + value: 'Child Six', + label: 'Child Six', + }, + ], + }], 'value', 'label'); + + + const groups = instance.currentState.groups; + const choices = instance.currentState.choices; + + expect(groups[groups.length - 1].value).to.equal('Group two'); + expect(groups[groups.length - 2].value).to.equal('Group one'); + expect(choices[choices.length - 1].value).to.equal('Child Six'); + expect(choices[choices.length - 2].value).to.equal('Child Five'); + }); + + it('should handle setChoices() with blank values', () => { + instance.setChoices([{ + label: 'Choice one', + value: 'one', + }, { + label: 'Choice two', + value: '', + }], 'value', 'label', true); + + + const choices = instance.currentState.choices; + expect(choices[0].value).to.equal('one'); + expect(choices[1].value).to.equal(''); + }); + + it('should handle clearStore()', () => { + instance.clearStore(); + + expect(instance.currentState.items).to.have.lengthOf(0); + expect(instance.currentState.choices).to.have.lengthOf(0); + expect(instance.currentState.groups).to.have.lengthOf(0); + }); + + it('should handle disable()', () => { + instance.disable(); + + expect(instance.input.element.disabled).to.be.true; + expect( + instance.containerOuter.element.classList.contains( + instance.config.classNames.disabledState, + ), + ).to.be.true; + expect(instance.containerOuter.element.getAttribute('aria-disabled')).to.equal('true'); + }); + + it('should handle enable()', () => { + instance.enable(); + + expect(instance.input.element.disabled).to.be.false; + expect( + instance.containerOuter.element.classList.contains( + instance.config.classNames.disabledState, + ), + ).to.be.false; + expect(instance.containerOuter.element.hasAttribute('aria-disabled')).to.be.false; + }); + + it('should handle ajax()', () => { + const dummyFn = sinon.spy(); + + instance.ajax(dummyFn); + + expect(dummyFn.callCount).to.equal(1); + }); + }); + + describe('should handle public methods on select-one input types', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.placeholder = 'Placeholder text'; + + for (let i = 1; i < 10; i++) { + const option = document.createElement('option'); + + option.value = `Value ${i}`; + option.innerHTML = `Value ${i}`; + + if (i % 2) { + option.selected = true; + } + + input.appendChild(option); + } + + document.body.appendChild(input); + instance = new Choices(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should handle disable()', () => { + instance.disable(); + + expect(instance.containerOuter.element.getAttribute('tabindex')).to.equal('-1'); + }); + + it('should handle enable()', () => { + instance.enable(); + + expect(instance.containerOuter.element.getAttribute('tabindex')).to.equal('0'); + }); + }); + + describe('should handle public methods on text input types', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('input'); + input.type = 'text'; + input.className = 'js-choices'; + input.value = 'Value 1, Value 2, Value 3, Value 4'; + + document.body.appendChild(input); + instance = new Choices(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should handle clearInput()', () => { + instance.clearInput(); + expect(instance.input.element.value).to.equal(''); + }); + + it('should handle removeItemsByValue()', () => { + const items = instance.currentState.items; + const randomItem = items[Math.floor(Math.random() * items.length)]; + + instance.removeItemsByValue(randomItem.value); + expect(randomItem.active).to.be.false; + }); + }); + + describe('should react to config options', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.setAttribute('multiple', ''); + + for (let i = 1; i < 4; i++) { + const option = document.createElement('option'); + + option.value = `Value ${i}`; + option.innerHTML = `Value ${i}`; + + if (i % 2) { + option.selected = true; + } + + input.appendChild(option); + } + + document.body.appendChild(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should flip the dropdown', () => { + instance = new Choices(input, { + position: 'top', + }); + + const container = instance.containerOuter.element; + instance.input.element.focus(); + expect(container.classList.contains(instance.config.classNames.flippedState)).to.be.true; + }); + + it('shouldn\'t flip the dropdown', () => { + instance = new Choices(input, { + position: 'bottom', + }); + + const container = instance.containerOuter.element; + instance.input.element.focus(); + expect(container.classList.contains(instance.config.classNames.flippedState)).to.be.false; + }); + + it('should render selected choices', () => { + instance = new Choices(input, { + renderSelectedChoices: 'always', + renderChoiceLimit: -1, + }); + + const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); + expect(renderedChoices.length).to.equal(3); + }); + + it('shouldn\'t render selected choices', () => { + instance = new Choices(input, { + renderSelectedChoices: 'auto', + renderChoiceLimit: -1, + }); + + const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); + expect(renderedChoices.length).to.equal(1); + }); + + it('shouldn\'t render choices up to a render limit', () => { + // Remove existing choices (to make test simpler) + while (input.firstChild) { + input.removeChild(input.firstChild); + } + + instance = new Choices(input, { + choices: [ + { + value: 'Option 1', + selected: false, + }, + { + value: 'Option 2', + selected: false, + }, + { + value: 'Option 3', + selected: false, + }, + { + value: 'Option 4', + selected: false, + }, + { + value: 'Option 5', + selected: false, + }, + ], + renderSelectedChoices: 'auto', + renderChoiceLimit: 4, + }); + + const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); + expect(renderedChoices.length).to.equal(4); + }); + }); + + describe('should allow custom properties provided by the user on items or choices', () => { + let input; + let instance; + + beforeEach(() => { + input = document.createElement('select'); + input.className = 'js-choices'; + input.setAttribute('multiple', ''); + + document.body.appendChild(input); + }); + + afterEach(() => { + instance.destroy(); + }); + + it('should allow the user to supply custom properties for a choice that will be inherited by the item when the user selects the choice', () => { + const expectedCustomProperties = { + isBestOptionEver: true, + }; + + instance = new Choices(input); + instance.setChoices([{ + value: '42', + label: 'My awesome choice', + selected: false, + disabled: false, + customProperties: expectedCustomProperties, + }], 'value', 'label', true); + + instance.setValueByChoice('42'); + const selectedItems = instance.getValue(); + + expect(selectedItems.length).to.equal(1); + expect(selectedItems[0].customProperties).to.equal(expectedCustomProperties); + }); + + it('should allow the user to supply custom properties when directly creating a selected item', () => { + const expectedCustomProperties = { + isBestOptionEver: true, + }; + + instance = new Choices(input); + + instance.setValue([{ + value: 'bar', + label: 'foo', + customProperties: expectedCustomProperties, + }]); + const selectedItems = instance.getValue(); + + expect(selectedItems.length).to.equal(1); + expect(selectedItems[0].customProperties).to.equal(expectedCustomProperties); + }); + }); +}); diff --git a/src/scripts/src/choices.test.js b/src/scripts/src/choices.test.js index fdcd03d..3c5695b 100644 --- a/src/scripts/src/choices.test.js +++ b/src/scripts/src/choices.test.js @@ -1,1114 +1,64 @@ -/* eslint-disable no-unused-expressions */ -import 'whatwg-fetch'; -import 'es6-promise'; -import 'core-js/fn/object/assign'; -import 'custom-event-autopolyfill'; -import { expect } from 'chai'; -import sinon from 'sinon'; +// import { expect } from 'chai'; +// import sinon from 'sinon'; -import Choices from './choices'; -import Dropdown from './components/dropdown'; -import Container from './components/container'; -import Input from './components/input'; -import List from './components/list'; -import WrappedInput from './components/wrapped-input'; -import WrappedSelect from './components/wrapped-select'; - -describe('Choices', () => { - describe('initialize Choices', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('input'); - input.type = 'text'; - input.className = 'js-choices'; - - document.body.appendChild(input); - instance = new Choices(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should be defined', () => { - expect(instance).to.not.be.undefined; - }); - - it('should have initialised', () => { - expect(instance.initialised).to.be.true; - }); - - it('should not re-initialise if passed element again', () => { - const reinitialise = new Choices(instance.passedElement.element); - sinon.spy(reinitialise, '_createTemplates'); - expect(reinitialise._createTemplates.callCount).to.equal(0); - }); - - it('should have a blank state', () => { - expect(instance.currentState.items.length).to.equal(0); - expect(instance.currentState.groups.length).to.equal(0); - expect(instance.currentState.choices.length).to.equal(0); - }); - - it('should have config options', () => { - expect(instance.config.silent).to.be.a('boolean'); - expect(instance.config.items).to.be.an('array'); - expect(instance.config.choices).to.be.an('array'); - expect(instance.config.renderChoiceLimit).to.be.a('number'); - expect(instance.config.maxItemCount).to.be.a('number'); - expect(instance.config.addItems).to.be.a('boolean'); - expect(instance.config.removeItems).to.be.a('boolean'); - expect(instance.config.removeItemButton).to.be.a('boolean'); - expect(instance.config.editItems).to.be.a('boolean'); - expect(instance.config.duplicateItems).to.be.a('boolean'); - expect(instance.config.delimiter).to.be.a('string'); - expect(instance.config.paste).to.be.a('boolean'); - expect(instance.config.searchEnabled).to.be.a('boolean'); - expect(instance.config.searchChoices).to.be.a('boolean'); - expect(instance.config.searchFloor).to.be.a('number'); - expect(instance.config.searchResultLimit).to.be.a('number'); - expect(instance.config.searchFields, 'should be string or array').to.satisfy(searchFields => - Array.isArray(searchFields) || typeof searchFields === 'string'); - expect(instance.config.position).to.be.a('string'); - expect(instance.config.regexFilter).to.be.null; - expect(instance.config.sortFilter).to.be.a('function'); - expect(instance.config.shouldSort).to.be.a('boolean'); - expect(instance.config.shouldSortItems).to.be.a('boolean'); - expect(instance.config.placeholder).to.be.a('boolean'); - expect(instance.config.placeholderValue).to.be.null; - expect(instance.config.prependValue).to.be.null; - expect(instance.config.appendValue).to.be.null; - expect(instance.config.renderSelectedChoices).to.be.a('string'); - expect(instance.config.loadingText).to.be.a('string'); - expect(instance.config.noResultsText).to.be.a('string'); - expect(instance.config.noChoicesText).to.be.a('string'); - expect(instance.config.itemSelectText).to.be.a('string'); - expect(instance.config.classNames).to.be.an('object'); - expect(instance.config.callbackOnInit).to.be.null; - expect(instance.config.callbackOnCreateTemplates).to.be.null; - }); - - it('should expose public methods', () => { - expect(instance.init).to.be.a('function'); - expect(instance.destroy).to.be.a('function'); - expect(instance.render).to.be.a('function'); - expect(instance.renderGroups).to.be.a('function'); - expect(instance.renderItems).to.be.a('function'); - expect(instance.renderChoices).to.be.a('function'); - expect(instance.highlightItem).to.be.a('function'); - expect(instance.unhighlightItem).to.be.a('function'); - expect(instance.highlightAll).to.be.a('function'); - expect(instance.unhighlightAll).to.be.a('function'); - expect(instance.removeItemsByValue).to.be.a('function'); - expect(instance.removeActiveItems).to.be.a('function'); - expect(instance.removeHighlightedItems).to.be.a('function'); - expect(instance.showDropdown).to.be.a('function'); - expect(instance.hideDropdown).to.be.a('function'); - expect(instance.toggleDropdown).to.be.a('function'); - expect(instance.getValue).to.be.a('function'); - expect(instance.setValue).to.be.a('function'); - expect(instance.setValueByChoice).to.be.a('function'); - expect(instance.setChoices).to.be.a('function'); - expect(instance.disable).to.be.a('function'); - expect(instance.enable).to.be.a('function'); - expect(instance.ajax).to.be.a('function'); - expect(instance.clearStore).to.be.a('function'); - expect(instance.clearInput).to.be.a('function'); - }); - - it('should hide passed input', () => { - expect(instance.passedElement.element.style.display).to.equal('none'); - }); - - it('should create an outer container', () => { - expect(instance.containerOuter).to.be.an.instanceof(Container); - }); - - it('should create an inner container', () => { - expect(instance.containerInner).to.be.an.instanceof(Container); - }); - - it('should create a choice list', () => { - expect(instance.choiceList).to.be.an.instanceof(List); - }); - - it('should create an item list', () => { - expect(instance.itemList).to.be.an.instanceof(List); - }); - - it('should create an input', () => { - expect(instance.input).to.be.an.instanceof(Input); - }); - - it('should create a dropdown', () => { - expect(instance.dropdown).to.be.an.instanceof(Dropdown); - }); - - it('should backup and recover original styles', () => { - const origStyle = 'background-color: #ccc; margin: 5px padding: 10px;'; - - instance.destroy(); - input.setAttribute('style', origStyle); - instance = new Choices(input); - - let style = input.getAttribute('data-choice-orig-style'); - expect(style).to.equal(origStyle); - - instance.destroy(); - style = input.getAttribute('data-choice-orig-style'); - expect(style).to.be.null; - - style = input.getAttribute('style'); - expect(style).to.equal(origStyle); - }); +describe('choices', () => { + describe('public methods', () => { + describe('init', () => {}); + describe('destroy', () => {}); + describe('renderGroups', () => {}); + describe('renderChoices', () => {}); + describe('renderItems', () => {}); + describe('render', () => {}); + describe('highlightItem', () => {}); + describe('unhighlightItem', () => {}); + describe('highlightAll', () => {}); + describe('unhighlightAll', () => {}); + describe('removeItemsByValue', () => {}); + describe('removeActiveItems', () => {}); + describe('removeHighlightedItems', () => {}); + describe('showDropdown', () => {}); + describe('hideDropdown', () => {}); + describe('toggleDropdown', () => {}); + describe('getValue', () => {}); + describe('setValue', () => {}); + describe('setValueByChoice', () => {}); + describe('setChoices', () => {}); + describe('clearStore', () => {}); + describe('clearInput', () => {}); + describe('disable', () => {}); }); - describe('should accept text inputs', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('input'); - input.type = 'text'; - input.className = 'js-choices'; - input.placeholder = 'Placeholder text'; - - document.body.appendChild(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should wrap passed input', () => { - instance = new Choices(input); - expect(instance.passedElement).to.be.an.instanceof(WrappedInput); - }); - - it('should accept a user inputted value', () => { - instance = new Choices(input); - - instance.input.element.focus(); - instance.input.element.value = 'test'; - - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - expect(instance.currentState.items[0].value).to.include(instance.input.element.value); - }); - - it('should copy the passed placeholder to the cloned input', () => { - instance = new Choices(input); - - expect(instance.input.element.placeholder).to.equal(input.placeholder); - }); - - it('should not allow duplicates if duplicateItems is false', () => { - instance = new Choices(input, { - duplicateItems: false, - items: ['test 1'], - }); - - instance.input.element.focus(); - instance.input.element.value = 'test 1'; - - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - expect(instance.currentState.items[instance.currentState.items.length - 1].value).to.equal(instance.input.element.value); - }); - - it('should filter input if regexFilter is passed', () => { - instance = new Choices(input, { - regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, - }); - - instance.input.element.focus(); - instance.input.element.value = 'josh@joshuajohnson.co.uk'; - - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - instance.input.element.focus(); - instance.input.element.value = 'not an email address'; - - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - const lastItem = instance.currentState.items[instance.currentState.items.length - 1]; - - expect(lastItem.value).to.equal('josh@joshuajohnson.co.uk'); - expect(lastItem.value).not.to.equal('not an email address'); - }); - - it('should prepend and append values if passed', () => { - instance = new Choices(input, { - prependValue: 'item-', - appendValue: '-value', - }); - - instance.input.element.focus(); - instance.input.element.value = 'test'; - - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - const lastItem = instance.currentState.items[instance.currentState.items.length - 1]; - - expect(lastItem.value).not.to.equal('test'); - expect(lastItem.value).to.equal('item-test-value'); - }); - }); - - describe('should accept single select inputs', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.placeholder = 'Placeholder text'; - - for (let i = 1; i < 4; i++) { - const option = document.createElement('option'); - - option.value = `Value ${i}`; - option.innerHTML = `Label ${i}`; - - input.appendChild(option); - } - - document.body.appendChild(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should wrap passed input', () => { - instance = new Choices(input); - expect(instance.passedElement).to.be.an.instanceof(WrappedSelect); - }); - - it('should open the choice list on focusing', () => { - instance = new Choices(input); - instance.input.element.focus(); - expect(instance.dropdown.element.classList.contains(instance.config.classNames.activeState)).to.be.true; - }); - - it('should select the first choice', () => { - instance = new Choices(input); - expect(instance.currentState.items[0].value).to.include('Value 1'); - }); - - it('should highlight the choices on keydown', () => { - instance = new Choices(input, { - renderChoiceLimit: -1, - }); - instance.input.element.focus(); - - for (let i = 0; i < 2; i++) { - // Key down to third choice - instance._onKeyDown({ - target: instance.input.element, - keyCode: 40, - ctrlKey: false, - preventDefault: () => {}, - }); - } - - expect(instance.highlightPosition).to.equal(2); - }); - - it('should select choice on enter key press', () => { - instance = new Choices(input); - instance.input.element.focus(); - - // Key down to second choice - instance._onKeyDown({ - target: instance.input.element, - keyCode: 40, - ctrlKey: false, - preventDefault: () => {}, - }); - - // Key down to select choice - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - preventDefault: () => {}, - }); - - expect(instance.currentState.items.length).to.equal(2); - }); - - it('should trigger add/change event on selection', () => { - instance = new Choices(input); - - const onChangeStub = sinon.stub(); - const addSpyStub = sinon.stub(); - const passedElement = instance.passedElement; - - passedElement.element.addEventListener('change', onChangeStub); - passedElement.element.addEventListener('addItem', addSpyStub); - - instance.input.element.focus(); - - // Key down to second choice - instance._onKeyDown({ - target: instance.input.element, - keyCode: 40, - ctrlKey: false, - preventDefault: () => {}, - }); - - // Key down to select choice - instance._onKeyDown({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - preventDefault: () => {}, - }); - - const returnValue = onChangeStub.lastCall.args[0].detail.value; - expect(returnValue).to.be.a('string'); - expect(onChangeStub.callCount).to.equal(1); - expect(addSpyStub.callCount).to.equal(1); - }); - - it('should open the dropdown on click', () => { - instance = new Choices(input); - const container = instance.containerOuter.element; - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - expect(document.activeElement === instance.input.element && container.classList.contains('is-open')).to.be.true; - }); - - it('should close the dropdown on double click', () => { - instance = new Choices(input); - const container = instance.containerOuter.element; - const openState = instance.config.classNames.openState; - - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - expect(document.activeElement === instance.input.element && container.classList.contains(openState)).to.be.false; - }); - - it('should trigger showDropdown on dropdown opening', () => { - instance = new Choices(input); - const container = instance.containerOuter.element; - - const showDropdownStub = sinon.spy(); - const passedElement = instance.passedElement; - - passedElement.element.addEventListener('showDropdown', showDropdownStub); - - instance.input.focus(); - - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - expect(showDropdownStub.callCount).to.equal(1); - }); - - it('should trigger hideDropdown on dropdown closing', () => { - instance = new Choices(input); - - const container = instance.containerOuter.element; - const hideDropdownStub = sinon.stub(); - const passedElement = instance.passedElement; - - passedElement.element.addEventListener('hideDropdown', hideDropdownStub); - - instance.input.element.focus(); - - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - instance._onClick({ - target: container, - ctrlKey: false, - preventDefault: () => {}, - }); - - expect(hideDropdownStub.callCount).to.equal(1); - }); - - it('should filter choices when searching', () => { - instance = new Choices(input); - - const onSearchStub = sinon.spy(); - const passedElement = instance.passedElement; - - passedElement.element.addEventListener('search', onSearchStub); - - instance.input.element.focus(); - instance.input.element.value = '3 '; - - // Key down to search - instance._onKeyUp({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - const mostAccurateResult = instance.currentState.choices.find(choice => choice.active); - - expect(instance.isSearching && mostAccurateResult.value === 'Value 3').to.be.true; - expect(onSearchStub.callCount).to.equal(1); - }); - - it('shouldn\'t filter choices when searching', () => { - instance = new Choices(input, { - searchChoices: false, - }); - - instance.setValue(['Javascript', 'HTML', 'Jasmine']); - - const onSearchStub = sinon.spy(); - const passedElement = instance.passedElement; - - passedElement.element.addEventListener('search', onSearchStub); - - instance.input.element.focus(); - instance.input.element.value = 'Javascript'; - - // Key down to search - instance._onKeyUp({ - target: instance.input.element, - keyCode: 13, - ctrlKey: false, - }); - - const activeOptions = instance.currentState.choices.filter(choice => choice.active); - - expect(activeOptions.length).to.equal(instance.currentState.choices.length); - expect(onSearchStub.callCount).to.equal(1); - }); - - it('shouldn\'t sort choices if shouldSort is false', () => { - instance = new Choices(input, { - shouldSort: false, - choices: [ - { - value: 'Value 5', - label: 'Label Five', - }, { - value: 'Value 6', - label: 'Label Six', - }, { - value: 'Value 7', - label: 'Label Seven', - }, - ], - }); - - expect(instance.currentState.choices[0].value).to.equal('Value 5'); - }); - - it('should sort choices if shouldSort is true', () => { - instance = new Choices(input, { - shouldSort: true, - choices: [ - { - value: 'Value 5', - label: 'Label Five', - }, { - value: 'Value 6', - label: 'Label Six', - }, { - value: 'Value 7', - label: 'Label Seven', - }, - ], - }); - - expect(instance.currentState.choices[0].value).to.equal('Value 1'); - }); - }); - - describe('should accept multiple select inputs', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.setAttribute('multiple', ''); - - for (let i = 1; i < 4; i++) { - const option = document.createElement('option'); - - option.value = `Value ${i}`; - option.innerHTML = `Value ${i}`; - - if (i % 2) { - option.selected = true; - } - - input.appendChild(option); - } - - document.body.appendChild(input); - - instance = new Choices(input, { - placeholderValue: 'Placeholder text', - choices: [ - { - value: 'One', - label: 'Label One', - selected: true, - disabled: false, - }, { - value: 'Two', - label: 'Label Two', - disabled: true, - }, { - value: 'Three', - label: 'Label Three', - }, - ], - }); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should wrap passed input', () => { - expect(instance.passedElement).to.be.an.instanceof(WrappedSelect); - }); - - it('should add any pre-defined values', () => { - expect(instance.currentState.items.length).to.be.above(1); - }); - - it('should add options defined in the config + pre-defined options', () => { - expect(instance.currentState.choices.length).to.equal(6); - }); - - it('should add a placeholder defined in the config to the search input', () => { - expect(instance.input.element.placeholder).to.equal('Placeholder text'); - }); - }); - - describe('should handle public methods on select input types', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.multiple = true; - input.placeholder = 'Placeholder text'; - - for (let i = 1; i < 10; i++) { - const option = document.createElement('option'); - - option.value = `Value ${i}`; - option.innerHTML = `Value ${i}`; - - if (i % 2) { - option.selected = true; - } - - input.appendChild(option); - } - - document.body.appendChild(input); - instance = new Choices(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should handle highlightItem()', () => { - const items = instance.currentState.items; - const randomItem = items[Math.floor(Math.random() * items.length)]; - - instance.highlightItem(randomItem); - - expect(randomItem.highlighted).to.be.true; - }); - - it('should handle unhighlightItem()', () => { - const items = instance.currentState.items; - const randomItem = items[Math.floor(Math.random() * items.length)]; - - instance.unhighlightItem(randomItem); - - expect(randomItem.highlighted).to.be.false; - }); - - it('should handle highlightAll()', () => { - const items = instance.currentState.items; - - instance.highlightAll(); - - const unhighlightedItems = items.some(item => item.highlighted === false); - - expect(unhighlightedItems).to.be.false; - }); - - it('should handle unhighlightAll()', () => { - const items = instance.currentState.items; - - instance.unhighlightAll(); - - const highlightedItems = items.some(item => item.highlighted === true); - - expect(highlightedItems).to.be.false; - }); - - it('should handle removeHighlightedItems()', () => { - const items = instance.currentState.items; - instance.highlightAll(); - instance.removeHighlightedItems(); - - const activeItems = items.some(item => item.active === true); - - expect(activeItems).to.be.false; - }); - - it('should handle showDropdown()', () => { - instance.showDropdown(); - - const hasOpenState = instance.containerOuter.element.classList.contains(instance.config.classNames.openState); - const hasAttr = instance.containerOuter.element.getAttribute('aria-expanded') === 'true'; - const hasActiveState = instance.dropdown.element.classList.contains(instance.config.classNames.activeState); - - expect(hasOpenState && hasAttr && hasActiveState).to.be.true; - }); - - it('should handle hideDropdown()', () => { - instance.showDropdown(); - instance.hideDropdown(); - - const hasOpenState = instance.containerOuter.element.classList.contains(instance.config.classNames.openState); - const hasAttr = instance.containerOuter.element.getAttribute('aria-expanded') === 'true'; - const hasActiveState = instance.dropdown.element.classList.contains(instance.config.classNames.activeState); - - - expect(hasOpenState && hasAttr && hasActiveState).to.be.false; - }); - - it('should handle toggleDropdown()', () => { - sinon.spy(instance, 'hideDropdown'); - instance.showDropdown(); - instance.toggleDropdown(); - expect(instance.hideDropdown.callCount).to.equal(1); - }); - - it('should handle getValue()', () => { - const valueObjects = instance.getValue(); - const valueStrings = instance.getValue(true); - - expect(valueStrings[0]).to.be.a('string'); - expect(valueObjects[0]).to.be.an('object'); - expect(valueObjects).to.be.an('array'); - expect(valueObjects.length).to.equal(5); - }); - - it('should handle setValue()', () => { - instance.setValue(['Set value 1', 'Set value 2', 'Set value 3']); - const valueStrings = instance.getValue(true); - - expect(valueStrings[valueStrings.length - 1]).to.equal('Set value 3'); - expect(valueStrings[valueStrings.length - 2]).to.equal('Set value 2'); - expect(valueStrings[valueStrings.length - 3]).to.equal('Set value 1'); - }); - - it('should handle setValueByChoice()', () => { - const choices = instance.store.getChoicesFilteredByActive(); - const randomChoice = choices[Math.floor(Math.random() * choices.length)]; - - instance.highlightAll(); - instance.removeHighlightedItems(); - instance.setValueByChoice(randomChoice.value); - - const value = instance.getValue(true); - - expect(value[0]).to.equal(randomChoice.value); - }); - - it('should handle setChoices()', () => { - instance.setChoices([{ - label: 'Group one', - id: 1, - disabled: false, - choices: [ - { - value: 'Child One', - label: 'Child One', - selected: true, - }, { - value: 'Child Two', - label: 'Child Two', - disabled: true, - }, { - value: 'Child Three', - label: 'Child Three', - }, - ], - }, { - label: 'Group two', - id: 2, - disabled: false, - choices: [ - { - value: 'Child Four', - label: 'Child Four', - disabled: true, - }, { - value: 'Child Five', - label: 'Child Five', - }, { - value: 'Child Six', - label: 'Child Six', - }, - ], - }], 'value', 'label'); - - - const groups = instance.currentState.groups; - const choices = instance.currentState.choices; - - expect(groups[groups.length - 1].value).to.equal('Group two'); - expect(groups[groups.length - 2].value).to.equal('Group one'); - expect(choices[choices.length - 1].value).to.equal('Child Six'); - expect(choices[choices.length - 2].value).to.equal('Child Five'); - }); - - it('should handle setChoices() with blank values', () => { - instance.setChoices([{ - label: 'Choice one', - value: 'one', - }, { - label: 'Choice two', - value: '', - }], 'value', 'label', true); - - - const choices = instance.currentState.choices; - expect(choices[0].value).to.equal('one'); - expect(choices[1].value).to.equal(''); - }); - - it('should handle clearStore()', () => { - instance.clearStore(); - - expect(instance.currentState.items).to.have.lengthOf(0); - expect(instance.currentState.choices).to.have.lengthOf(0); - expect(instance.currentState.groups).to.have.lengthOf(0); - }); - - it('should handle disable()', () => { - instance.disable(); - - expect(instance.input.element.disabled).to.be.true; - expect( - instance.containerOuter.element.classList.contains( - instance.config.classNames.disabledState, - ), - ).to.be.true; - expect(instance.containerOuter.element.getAttribute('aria-disabled')).to.equal('true'); - }); - - it('should handle enable()', () => { - instance.enable(); - - expect(instance.input.element.disabled).to.be.false; - expect( - instance.containerOuter.element.classList.contains( - instance.config.classNames.disabledState, - ), - ).to.be.false; - expect(instance.containerOuter.element.hasAttribute('aria-disabled')).to.be.false; - }); - - it('should handle ajax()', () => { - const dummyFn = sinon.spy(); - - instance.ajax(dummyFn); - - expect(dummyFn.callCount).to.equal(1); - }); - }); - - describe('should handle public methods on select-one input types', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.placeholder = 'Placeholder text'; - - for (let i = 1; i < 10; i++) { - const option = document.createElement('option'); - - option.value = `Value ${i}`; - option.innerHTML = `Value ${i}`; - - if (i % 2) { - option.selected = true; - } - - input.appendChild(option); - } - - document.body.appendChild(input); - instance = new Choices(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should handle disable()', () => { - instance.disable(); - - expect(instance.containerOuter.element.getAttribute('tabindex')).to.equal('-1'); - }); - - it('should handle enable()', () => { - instance.enable(); - - expect(instance.containerOuter.element.getAttribute('tabindex')).to.equal('0'); - }); - }); - - describe('should handle public methods on text input types', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('input'); - input.type = 'text'; - input.className = 'js-choices'; - input.value = 'Value 1, Value 2, Value 3, Value 4'; - - document.body.appendChild(input); - instance = new Choices(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should handle clearInput()', () => { - instance.clearInput(); - expect(instance.input.element.value).to.equal(''); - }); - - it('should handle removeItemsByValue()', () => { - const items = instance.currentState.items; - const randomItem = items[Math.floor(Math.random() * items.length)]; - - instance.removeItemsByValue(randomItem.value); - expect(randomItem.active).to.be.false; - }); - }); - - describe('should react to config options', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.setAttribute('multiple', ''); - - for (let i = 1; i < 4; i++) { - const option = document.createElement('option'); - - option.value = `Value ${i}`; - option.innerHTML = `Value ${i}`; - - if (i % 2) { - option.selected = true; - } - - input.appendChild(option); - } - - document.body.appendChild(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should flip the dropdown', () => { - instance = new Choices(input, { - position: 'top', - }); - - const container = instance.containerOuter.element; - instance.input.element.focus(); - expect(container.classList.contains(instance.config.classNames.flippedState)).to.be.true; - }); - - it('shouldn\'t flip the dropdown', () => { - instance = new Choices(input, { - position: 'bottom', - }); - - const container = instance.containerOuter.element; - instance.input.element.focus(); - expect(container.classList.contains(instance.config.classNames.flippedState)).to.be.false; - }); - - it('should render selected choices', () => { - instance = new Choices(input, { - renderSelectedChoices: 'always', - renderChoiceLimit: -1, - }); - - const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); - expect(renderedChoices.length).to.equal(3); - }); - - it('shouldn\'t render selected choices', () => { - instance = new Choices(input, { - renderSelectedChoices: 'auto', - renderChoiceLimit: -1, - }); - - const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); - expect(renderedChoices.length).to.equal(1); - }); - - it('shouldn\'t render choices up to a render limit', () => { - // Remove existing choices (to make test simpler) - while (input.firstChild) { - input.removeChild(input.firstChild); - } - - instance = new Choices(input, { - choices: [ - { - value: 'Option 1', - selected: false, - }, - { - value: 'Option 2', - selected: false, - }, - { - value: 'Option 3', - selected: false, - }, - { - value: 'Option 4', - selected: false, - }, - { - value: 'Option 5', - selected: false, - }, - ], - renderSelectedChoices: 'auto', - renderChoiceLimit: 4, - }); - - const renderedChoices = instance.choiceList.element.querySelectorAll('.choices__item'); - expect(renderedChoices.length).to.equal(4); - }); - }); - - describe('should allow custom properties provided by the user on items or choices', () => { - let input; - let instance; - - beforeEach(() => { - input = document.createElement('select'); - input.className = 'js-choices'; - input.setAttribute('multiple', ''); - - document.body.appendChild(input); - }); - - afterEach(() => { - instance.destroy(); - }); - - it('should allow the user to supply custom properties for a choice that will be inherited by the item when the user selects the choice', () => { - const expectedCustomProperties = { - isBestOptionEver: true, - }; - - instance = new Choices(input); - instance.setChoices([{ - value: '42', - label: 'My awesome choice', - selected: false, - disabled: false, - customProperties: expectedCustomProperties, - }], 'value', 'label', true); - - instance.setValueByChoice('42'); - const selectedItems = instance.getValue(); - - expect(selectedItems.length).to.equal(1); - expect(selectedItems[0].customProperties).to.equal(expectedCustomProperties); - }); - - it('should allow the user to supply custom properties when directly creating a selected item', () => { - const expectedCustomProperties = { - isBestOptionEver: true, - }; - - instance = new Choices(input); - - instance.setValue([{ - value: 'bar', - label: 'foo', - customProperties: expectedCustomProperties, - }]); - const selectedItems = instance.getValue(); - - expect(selectedItems.length).to.equal(1); - expect(selectedItems[0].customProperties).to.equal(expectedCustomProperties); - }); + describe('private methods', () => { + describe('_triggerChange', () => {}); + describe('_selectPlaceholderChoice', () => {}); + describe('_handleButtonAction', () => {}); + describe('_handleItemAction', () => {}); + describe('_handleChoiceAction', () => {}); + describe('_handleBackspace', () => {}); + describe('_handleLoadingState', () => {}); + describe('_canAddItem', () => {}); + describe('_ajaxCallback', () => {}); + describe('_searchChoices', () => {}); + describe('_handleSearch', () => {}); + describe('_addEventListeners', () => {}); + describe('_removeEventListeners', () => {}); + describe('_onKeyDown', () => {}); + describe('_onTouchMove', () => {}); + describe('_onTouchEnd', () => {}); + describe('_onMouseDown', () => {}); + describe('_onMouseOver', () => {}); + describe('_onClick', () => {}); + describe('_onFocus', () => {}); + describe('_onBlur', () => {}); + describe('_scrollToChoice', () => {}); + describe('_highlightChoice', () => {}); + describe('_addItem', () => {}); + describe('_removeItem', () => {}); + describe('_addChoice', () => {}); + describe('_clearChoices', () => {}); + describe('_addGroup', () => {}); + describe('_getTemplate', () => {}); + describe('_createTemplates', () => {}); + describe('_createInput', () => {}); }); }); diff --git a/src/scripts/src/components/container.test.js b/src/scripts/src/components/container.test.js index 921f28b..7d88445 100644 --- a/src/scripts/src/components/container.test.js +++ b/src/scripts/src/components/container.test.js @@ -3,7 +3,7 @@ import sinon from 'sinon'; import Container from './container'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('Container', () => { +describe('components/container', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/components/dropdown.test.js b/src/scripts/src/components/dropdown.test.js index b9b8675..4798504 100644 --- a/src/scripts/src/components/dropdown.test.js +++ b/src/scripts/src/components/dropdown.test.js @@ -3,7 +3,7 @@ import sinon from 'sinon'; import Dropdown from './dropdown'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('Dropdown', () => { +describe('components/dropdown', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/components/input.test.js b/src/scripts/src/components/input.test.js index 7187320..6f15995 100644 --- a/src/scripts/src/components/input.test.js +++ b/src/scripts/src/components/input.test.js @@ -3,7 +3,7 @@ import sinon from 'sinon'; import Input from './input'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('Input', () => { +describe('components/input', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/components/list.test.js b/src/scripts/src/components/list.test.js index cf481b3..a97c5a5 100644 --- a/src/scripts/src/components/list.test.js +++ b/src/scripts/src/components/list.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import List from './list'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('List', () => { +describe('components/list', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/components/wrapped-element.test.js b/src/scripts/src/components/wrapped-element.test.js index c941bba..9908145 100644 --- a/src/scripts/src/components/wrapped-element.test.js +++ b/src/scripts/src/components/wrapped-element.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import WrappedElement from './wrapped-element'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('WrappedElement', () => { +describe('components/wrappedElement', () => { let instance; let choicesInstance; let choicesElement; @@ -13,7 +13,48 @@ describe('WrappedElement', () => { ...DEFAULT_CONFIG, }, }; + choicesElement = document.createElement('select'); instance = new WrappedElement(choicesInstance, choicesElement, DEFAULT_CLASSNAMES); }); + + describe('conceal', () => { + let originalStyling; + + beforeEach(() => { + originalStyling = 'color:red'; + instance.element.setAttribute('style', originalStyling); + }); + + it('hides element', () => { + instance.conceal(); + expect(instance.element.tabIndex).to.equal(-1); + expect(instance.element.classList.contains(instance.classNames.input)).to.equal(true); + expect(instance.element.classList.contains(instance.classNames.hiddenState)).to.equal(true); + expect(instance.element.getAttribute('style')).to.equal('display:none;'); + expect(instance.element.getAttribute('aria-hidden')).to.equal('true'); + expect(instance.element.getAttribute('data-choice')).to.equal('active'); + expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(originalStyling); + }); + }); + + describe('reveal', () => { + let originalStyling; + + beforeEach(() => { + originalStyling = 'color:red'; + instance.element.setAttribute('data-choice-orig-style', originalStyling); + }); + + it('shows element', () => { + instance.reveal(); + expect(instance.element.tabIndex).to.equal(0); + expect(instance.element.classList.contains(instance.classNames.input)).to.equal(false); + expect(instance.element.classList.contains(instance.classNames.hiddenState)).to.equal(false); + expect(instance.element.getAttribute('style')).to.equal(originalStyling); + expect(instance.element.getAttribute('aria-hidden')).to.equal(null); + expect(instance.element.getAttribute('data-choice')).to.equal(null); + expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(null); + }); + }); }); diff --git a/src/scripts/src/components/wrapped-input.test.js b/src/scripts/src/components/wrapped-input.test.js index ad5ba69..1e77aea 100644 --- a/src/scripts/src/components/wrapped-input.test.js +++ b/src/scripts/src/components/wrapped-input.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import WrappedInput from './wrapped-input'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('WrappedInput', () => { +describe('components/wrappedInput', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/components/wrapped-select.test.js b/src/scripts/src/components/wrapped-select.test.js index df564e2..41425d4 100644 --- a/src/scripts/src/components/wrapped-select.test.js +++ b/src/scripts/src/components/wrapped-select.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import WrappedSelect from './wrapped-select'; import { DEFAULT_CLASSNAMES, DEFAULT_CONFIG } from '../constants'; -describe('WrappedSelect', () => { +describe('components/wrappedSelect', () => { let instance; let choicesInstance; let choicesElement; diff --git a/src/scripts/src/reducers/choices.test.js b/src/scripts/src/reducers/choices.test.js index 9ce9eef..c80f481 100644 --- a/src/scripts/src/reducers/choices.test.js +++ b/src/scripts/src/reducers/choices.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import choices, { defaultState } from './choices'; -describe('choices reducer', () => { +describe('reducers/choices', () => { it('should return same state when no action matches', () => { expect(choices(defaultState, {})).to.equal(defaultState); }); diff --git a/src/scripts/src/reducers/groups.test.js b/src/scripts/src/reducers/groups.test.js index aacda1f..e67ee04 100644 --- a/src/scripts/src/reducers/groups.test.js +++ b/src/scripts/src/reducers/groups.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import groups, { defaultState } from './groups'; -describe('groups reducer', () => { +describe('reducers/groups', () => { it('should return same state when no action matches', () => { expect(groups(defaultState, {})).to.equal(defaultState); }); diff --git a/src/scripts/src/reducers/index.test.js b/src/scripts/src/reducers/index.test.js index 81a8e2f..8780069 100644 --- a/src/scripts/src/reducers/index.test.js +++ b/src/scripts/src/reducers/index.test.js @@ -5,7 +5,7 @@ import groups from './groups'; import choices from './choices'; import items from './items'; -describe('rootReducer', () => { +describe('reducers/rootReducer', () => { const store = createStore(rootReducer); it('returns expected reducers', () => { diff --git a/src/scripts/src/reducers/items.test.js b/src/scripts/src/reducers/items.test.js index cd5f133..dce4afa 100644 --- a/src/scripts/src/reducers/items.test.js +++ b/src/scripts/src/reducers/items.test.js @@ -1,8 +1,7 @@ import { expect } from 'chai'; -// import * as actions from '../actions/actions'; import items, { defaultState } from './items'; -describe('items reducer', () => { +describe('reducers/items', () => { it('should return same state when no action matches', () => { expect(items(defaultState, {})).to.equal(defaultState); }); diff --git a/src/scripts/src/store/store.test.js b/src/scripts/src/store/store.test.js index 39006bb..8fa3b53 100644 --- a/src/scripts/src/store/store.test.js +++ b/src/scripts/src/store/store.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; import Store from './store'; -describe('Store', () => { +describe('reducers/store', () => { let instance; let subscribeStub; let dispatchStub;