Repository URL to install this package:
|
Version:
5.2.1-rc.0 ▾
|
@doodle/components
/
src
/
components
/
controls
/
Input
/
__tests__
/
MultiEmailSelect
/
MultiEmailSelect.spec.js
|
|---|
import React from 'react';
import { mount } from 'enzyme';
import MultiEmailSelect from '../../MultiEmailSelect/MultiEmailSelect';
import Option from '../../MultiEmailSelect/Option';
import { colorBrand200, colorRed200 } from '../../../../constants/colors';
const CheckIcon = require('../../../../visuals/Icon/svg/d_check.svg');
const QuestionmarkIcon = require('../../../../visuals/Icon/svg/d_questionmark.svg');
const PeopleIcon = require('../../../../visuals/Icon/svg/ic_people.svg');
describe('MultiEmailSelect', () => {
let placeholder;
let note;
let emailsLimit;
let options;
let initialValues;
let component;
let input;
let onValueChangeSpy;
const mockPasteEvent = text => {
const event = {
preventDefault: jest.fn(),
clipboardData: {
getData: () => text,
},
};
return event;
};
beforeAll(() => {
placeholder = 'Enter emails';
note = '"Allow entire domains: @example.com, or subdomains: @*.example.com"';
emailsLimit = 50;
options = [
{ value: 'tt@doodle.com', label: 'Timo Timber' },
{ value: 'tay@doodle.com', label: 'Tayo Awoyemi' },
{ value: 'st@stan.com', label: 'Stan Theman' },
{ value: 'zh@doodle.com', label: 'Zari fari' },
{ value: 'mms@doodle.com', label: 'Mima Salu' },
{ value: 'kl@doodle.com', label: 'Klaus Larifari' },
{ value: 'opef@doodle.com', label: 'Opaloda Ottoddf' },
{ value: 'opfe@doodle.com', label: 'Opaidap Ottod' },
{ value: 'opaa@doodle.com', label: 'Opalfodks Ottod' },
{ value: 'fran@doodle.example.com', label: 'Fran Example' },
{ value: 'carolina@doodle.example.com', label: 'Carolina Example' },
];
initialValues = [{ value: 'test@email.com', label: 'Test Label' }];
onValueChangeSpy = jest.fn();
});
beforeEach(() => {
component = mount(
<MultiEmailSelect
placeholder={placeholder}
note={note}
emailsLimit={emailsLimit}
options={options}
onValueChange={onValueChangeSpy}
/>
);
input = component.find('input');
});
it('matches a snapshot', () => {
expect(component.getElement()).toMatchSnapshot();
});
it('does not display the suggestion menu if there are less then 3 characters', () => {
input.instance().value = 'ti';
input.simulate('change');
expect(component.find('.MultiEmailSelect__menu').length).toBe(0);
});
it('displays the suggestion menu if there are 3 or more characters', () => {
input.instance().value = 'tim';
input.simulate('change');
expect(component.find('.MultiEmailSelect__menu').length).toBe(1);
});
it('displays the correct option in the suggestion menu if there are 3 or more characters', () => {
input.instance().value = 'tim';
input.simulate('change');
expect(
component
.find('.MultiEmailSelect__option-label')
.at(1)
.text()
).toBe('Timo Timber');
});
it('adds a domain to the selected option', () => {
input.instance().value = 'neu@neu.de';
input.simulate('change', { target: { value: 'neu@neu.de' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('neu@neu.de');
});
it('adds a domain to the selected option', () => {
input.instance().value = 'a@test.de';
input.simulate('change', { target: { value: 'a@test.de' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('a@test.de');
});
it('does not add a new email adress to the selected option if it has multiple @s', () => {
input.instance().value = 'test@test@test.de';
input.simulate('change', { target: { value: 'test@test@test.de' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').exists()).toBe(true);
});
it('does add inputs that are neither emails, domains or options', () => {
input.instance().value = 'testestest';
input.simulate('change', { target: { value: 'testestest' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').exists()).toBeTruthy();
});
it('adds a entry from the options to the selected options if the name of that option is entered', () => {
input.instance().value = 'Timo Timber';
input.simulate('change', { target: { value: 'Timo' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('Timo Timber');
});
it('adds pasted email to the selected options', () => {
component.instance().onPasteHandler(mockPasteEvent('test@test.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('test@test.de');
});
it('adds multiple space sperated, pasted emails to the selected options', () => {
component.instance().onPasteHandler(mockPasteEvent('test@test.de hallo@hallo.de 123@123.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(3);
});
it('adds multiple comma sperated, pasted emails to the selected options', () => {
component.instance().onPasteHandler(mockPasteEvent('test@test.de, hallo@hallo.de, 123@123.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(3);
});
it('adds multiple semicolon sperated, pasted emails to the selected options', () => {
component.instance().onPasteHandler(mockPasteEvent('test@test.de; hallo@hallo.de; 123@123.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(3);
});
it('adds pasted emails from complex strings to the selected options', () => {
[
'Patricia Magro (pm@doodle.com), Katharina Schneider (ks@doodle.com)',
'„Patricia Magro“ (pm@doodle.com), „Katharina Schneider“ (ks@doodle.com)',
'"Patricia Magro" (pm@doodle.com), "Katharina Schneider" (ks@doodle.com)',
'‚Patricia Magro’ (pm@doodle.com), ‚Katharina Schneider’ (ks@doodle.com)',
"'Patricia Magro' (pm@doodle.com), 'Katharina Schneider' (ks@doodle.com)",
'Patricia Magro (pm@doodle.com)\nKatharina Schneider (ks@doodle.com)',
'pm@doodle.com\nks@doodle.com',
'Patricia Magro <pm@doodle.com>, Katharina Schneider <ks@doodle.com>',
].forEach(testCase => {
component.instance().onPasteHandler(mockPasteEvent(testCase));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(2);
// remove the selected options
input.simulate('keyDown', { keyCode: 8, key: 'Backspace' });
input.simulate('keyDown', { keyCode: 8, key: 'Backspace' });
});
});
it('should add all pasted invalid emails', () => {
component.instance().onPasteHandler(mockPasteEvent('test@test.de hallo@hallo@hallo.de 123 hey@ @okay.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(5);
});
it('should not add emails when the limit is reached', () => {
component.setProps({ emailsLimit: 3 });
component.instance().onPasteHandler(mockPasteEvent('test@test.de hallo@hallo.de 123@123.de'));
component.update();
input.instance().value = 'new@new.de';
input.simulate('change', { target: { value: 'new@new.de' } });
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(3);
});
it('should not add emails via paste when the limit is reached', () => {
component.setProps({ emailsLimit: 3 });
component.instance().onPasteHandler(mockPasteEvent('test@test.de hallo@hallo.de 123@123.de'));
component.update();
component.instance().onPasteHandler(mockPasteEvent('new@new.de doodle@doodle.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(3);
});
it('should add all emails via paste, even when the limit is reached, while pasting the emails', () => {
component.setProps({ emailsLimit: 3 });
component
.instance()
.onPasteHandler(mockPasteEvent('test@test.de hallo@hallo.de 123@123.de new@new.de doodle@doodle.de'));
component.update();
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(5);
});
it('should show the email suggestion hook if there are no options provided and the input field got valid value', () => {
component.setProps({
options: null,
activateSuggestions: {
headline: 'See contacts suggestions',
text: 'From Gmail, Outlook, Office 365',
buttonText: 'Activate suggestions',
buttonLink: '/account',
silentButtonText: 'Later',
},
});
component.instance();
input.instance().value = 'email@mm.co';
input.simulate('change', { target: { value: 'email@mm.co' } });
expect(component.find('.ActivateSuggestions').exists()).toBeTruthy();
});
it('should show the initial options in the menu if thesy are provided and the input field is focused', () => {
component.setProps({
initialOptions: {
participated: {
label: 'Participated',
icon: CheckIcon,
options: [{ value: 'aa@doodle.com', label: 'aa@doodle.com' }],
},
notParticipated: {
label: 'Not Participated yet',
icon: QuestionmarkIcon,
options: [{ value: 'gg@doodle.com', label: 'gg@doodle.com' }],
},
everyone: {
label: 'Everyone',
icon: PeopleIcon,
options: [
{ value: 'aa@doodle.com', label: 'aa@doodle.com' },
{ value: 'gg@doodle.com', label: 'gg@doodle.com' },
],
},
},
});
component.instance();
input.instance();
input.simulate('focus');
expect(component.find(Option).length).toBe(3);
});
it('should add the emails from a initial options group', () => {
component.setProps({
initialOptions: {
participated: {
label: 'Participated',
icon: CheckIcon,
options: [{ value: 'aa@doodle.com', label: 'aa@doodle.com' }, { value: 'bb@doodle.com', label: 'Bella Be' }],
},
notParticipated: {
label: 'Not Participated yet',
icon: QuestionmarkIcon,
options: [{ value: 'gg@doodle.com', label: 'gg@doodle.com' }],
},
everyone: {
label: 'Everyone',
icon: PeopleIcon,
options: [
{ value: 'aa@doodle.com', label: 'aa@doodle.com' },
{ value: 'gg@doodle.com', label: 'gg@doodle.com' },
],
},
},
});
component.instance();
input.instance();
input.simulate('focus');
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find('.MultiEmailSelect__multi-value__label').length).toBe(2);
});
it('should remove an initial options group from the suggestion menu after it has been selected', () => {
component.setProps({
initialOptions: {
participated: {
label: 'Participated',
icon: CheckIcon,
options: [{ value: 'aa@doodle.com', label: 'aa@doodle.com' }, { value: 'bb@doodle.com', label: 'Bella Be' }],
},
notParticipated: {
label: 'Not Participated yet',
icon: QuestionmarkIcon,
options: [{ value: 'gg@doodle.com', label: 'gg@doodle.com' }],
},
everyone: {
label: 'Everyone',
icon: PeopleIcon,
options: [
{ value: 'aa@doodle.com', label: 'aa@doodle.com' },
{ value: 'gg@doodle.com', label: 'gg@doodle.com' },
],
},
},
});
component.instance();
input.instance();
input.simulate('focus');
input.simulate('keyDown', { keyCode: 9, key: 'Tab' });
expect(component.find(Option).length).toBe(2);
});
it('should render provided initial values', () => {
component.setState({ value: initialValues });
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('Test Label');
});
it('should display the values with a custom color, when a decorator is provided', () => {
component.setProps({
decorateValue: valueEntry =>
valueEntry.value === 'test@email.com' ? { style: { backgroundColor: '#ababab' } } : null,
});
component.setState({
value: initialValues,
});
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe('#ababab');
});
it('should display the values with the default color, when the decorator does not return anything', () => {
component.setProps({
decorateValue: valueEntry =>
valueEntry.value === 'another@email.com' ? { style: { backgroundColor: '#ababab' } } : null,
});
component.setState({
value: initialValues,
});
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(
colorBrand200
);
});
it('should display invalid values with the error colour', () => {
const value = [{ value: 'invalid', label: 'Test' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(colorRed200);
});
it('exposes values including a property that indicates whether the value is valid or not', () => {
component.instance().onChangeHandler([{ value: 'invalid*invitee', label: 'invalid*invitee' }]);
expect(onValueChangeSpy).toHaveBeenLastCalledWith([
{
label: 'invalid*invitee',
value: 'invalid*invitee',
valid: false,
},
]);
});
it('displays name as label if value exists in contact list', () => {
const value = [{ value: 'bb@doodle.com', label: 'Bella Be' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value__label').text()).toBe('Bella Be');
});
it('button should be in disabled state if 1 or more invalid values', () => {
const values = [{ value: 'invalid', label: 'invalid' }, { value: 'aa@doodle.com', label: 'aa@doodle.com' }];
component.setState({ value: values });
expect(component.find('.Button').prop('disabled')).toBe(true);
});
it('button should be in disabled state if email limit has been exceeded', () => {
const values = [
{ value: 'aa@doodle.com', label: 'aa@doodle.com' },
{ value: 'gg@doodle.com', label: 'gg@doodle.com' },
{ value: 'bb@doodle.com', label: 'Bella Be' },
];
component.setProps({ emailsLimit: 2 });
component.setState({ value: values });
expect(component.find('.Button').prop('disabled')).toBe(true);
});
it('should consider emails with an incomplete domain invalid', () => {
const value = [{ value: 'e@e', label: 'Test' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(colorRed200);
});
it('should consider two emails that are not separated by a space as invalid', () => {
const value = [{ value: 'hello@hello.comhi@hi.co', label: 'Test' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(colorRed200);
});
it('should not accept special characters in the domain', () => {
const value = [{ value: 'hey@ex$mple.com', label: 'Test' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(colorRed200);
});
it('should consider emails without a name before the domain (or subdomain) as invalid', () => {
const value = [{ value: '@example.com', label: 'Test' }];
component.setState({ value });
expect(component.find('.MultiEmailSelect__multi-value-container').prop('style').backgroundColor).toBe(colorRed200);
});
it('allows text to stay inside the component when "blur" is triggered', () => {
input.instance().value = 'neu@neu.de';
input.simulate('change', { target: { value: 'neu@neu.de' } });
input.simulate('blur');
expect(component.exists('.MultiEmailSelect__value-container input')).toBe(true);
expect(component.exists('.MultiEmailSelect__multi-value-container')).toBe(false);
});
it('adds a new invitee and cleans the input when an email is confirmed', () => {
input.instance().value = 'neu@neu.de';
input.simulate('change', { target: { value: 'neu@neu.de' } });
input.simulate('keyDown', { keyCode: 13, key: 'Enter' });
expect(component.exists('.MultiEmailSelect__multi-value-container')).toBe(true);
expect(component.find('.MultiEmailSelect__value-container input').text()).toBe('');
});
});