wix-style-react
Version:
277 lines (231 loc) • 9.9 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import dropdownDriverFactory from '../Dropdown.driver';
import Dropdown from '../Dropdown';
import { sleep } from 'wix-ui-test-utils/react-helpers';
import {
createRendererWithDriver,
createRendererWithUniDriver,
cleanup,
} from '../../../test/utils/unit';
import { dropdownUniDriverFactory } from '../Dropdown.uni.driver';
describe('Dropdown', () => {
describe('[sync]', () => {
runTests(createRendererWithDriver(dropdownDriverFactory));
});
describe('[async]', () => {
runTests(createRendererWithUniDriver(dropdownUniDriverFactory));
});
function runTests(render) {
afterEach(() => cleanup());
const createDriver = jsx => render(jsx).driver;
const getOptions = () => [
{ id: 0, value: 'Option 1' },
{ id: 1, value: 'Option 2' },
{ id: 2, value: 'Option 3', disabled: true },
{ id: 3, value: 'Option 4' },
{ id: 'divider1', value: '-' },
{
id: 'element1',
value: <span style={{ color: 'brown' }}>Option 4</span>,
},
];
describe('Uncontrolled SelectedId', () => {
it('should select item with selectedId on init state', async () => {
const { inputDriver, dropdownLayoutDriver } = createDriver(
<Dropdown options={getOptions()} initialSelectedId={0} />,
);
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
});
it('should select an item when clicked', async () => {
const { driver, dropdownLayoutDriver } = createDriver(
<Dropdown options={getOptions()} />,
);
await driver.focus();
await dropdownLayoutDriver.clickAtOption(0);
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
});
it('should enter the selected option text when selected', async () => {
const { driver, inputDriver, dropdownLayoutDriver } = createDriver(
<Dropdown options={getOptions()} />,
);
await driver.focus();
await dropdownLayoutDriver.clickAtOption(0);
expect(await inputDriver.getValue()).toBe('Option 1');
});
it('should close when clicking on input (header)', async () => {
const { dropdownLayoutDriver, inputDriver } = createDriver(
<Dropdown options={getOptions()} />,
);
await inputDriver.click();
expect(await dropdownLayoutDriver.isShown()).toBe(true);
return sleep(200).then(async () => {
await inputDriver.click();
expect(await dropdownLayoutDriver.isShown()).toBe(false);
});
});
it('should not be editable ', async () => {
const { driver } = createDriver(<Dropdown options={getOptions()} />);
expect(await driver.isEditable()).toBe(false);
});
it('should have no selection when initialSelectedId is null', async () => {
const { driver: _driver } = render(
<Dropdown
options={[{ id: 0, value: 'Option 1' }]}
initialSelectedId={null}
/>,
);
const { dropdownLayoutDriver, inputDriver } = _driver;
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(false);
expect(await inputDriver.getValue()).toBe('');
});
describe('initiallySelected', () => {
it('should keep selectedId and value when initialSelectedId changed', async () => {
const { driver: _driver, rerender } = render(
<Dropdown options={getOptions()} initialSelectedId={0} />,
);
const { dropdownLayoutDriver } = _driver;
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
rerender(<Dropdown options={getOptions()} initialSelectedId={1} />);
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
});
});
it(`should update selectedId when options change and id does not exist anymore`, async () => {
const { driver: _driver, rerender } = render(
<Dropdown
options={[
{ id: 0, value: 'Option 1' },
{ id: 1, value: 'Option 2' },
]}
initialSelectedId={0}
/>,
);
const { inputDriver, dropdownLayoutDriver } = _driver;
const option = await dropdownLayoutDriver.optionById(0);
expect(await option.isSelected()).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
rerender(<Dropdown options={[{ id: 1, value: 'Option 2' }]} />);
const options = await dropdownLayoutDriver.options();
const isAnyOptionSelected = (
await Promise.all(options.map(option => option.isSelected()))
).some(val => val);
expect(isAnyOptionSelected).toBe(false);
expect(await inputDriver.getValue()).toBe('');
});
it('should select item with selectedId on async init', async () => {
const { driver: _driver, rerender } = render(
<Dropdown options={[]} selectedId={0} />,
);
const { inputDriver, dropdownLayoutDriver } = _driver;
const options = await dropdownLayoutDriver.options();
const isAnyOptionSelected = (
await Promise.all(options.map(option => option.isSelected()))
).some(val => val);
expect(isAnyOptionSelected).toBe(false);
expect(await inputDriver.getValue()).toBe('');
rerender(
<Dropdown
options={[
{ id: 0, value: 'Option 1' },
{ id: 1, value: 'Option 2' },
]}
selectedId={0}
/>,
);
const option = await dropdownLayoutDriver.optionById(0);
expect(await option.isSelected()).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
});
describe('PropTypes Validation', () => {
let consoleErrorSpy;
beforeEach(() => {
consoleErrorSpy = jest
.spyOn(global.console, 'error')
.mockImplementation(jest.fn());
});
afterEach(() => {
consoleErrorSpy.mockRestore();
PropTypes.checkPropTypes.resetWarningCache();
});
it('should log error when selectedId and initialSelectedId are used together', async () => {
render(
<Dropdown
options={getOptions()}
selectedId={0}
initialSelectedId={0}
/>,
);
expect(consoleErrorSpy).toHaveBeenCalledTimes(1);
expect(consoleErrorSpy).toBeCalledWith(
expect.stringContaining(
`'selectedId' and 'initialSelectedId' cannot both be used at the same time.`,
),
);
});
});
});
describe('Controlled SelectedId', () => {
it('should keep current selection and value when option clicked', async () => {
const { driver, dropdownLayoutDriver, inputDriver } = createDriver(
<Dropdown options={getOptions()} selectedId={0} />,
);
await driver.focus();
await dropdownLayoutDriver.clickAtOption(1);
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
});
it('should have no selection if selectedId does not exist', async () => {
const { dropdownLayoutDriver } = createDriver(
<Dropdown options={[{ id: 0, value: 'Option 1' }]} selectedId={99} />,
);
const option = await dropdownLayoutDriver.optionById(0);
expect(await option.isSelected()).toBe(false);
});
it('should update selection and value when selectedId changes', async () => {
const { driver: _driver, rerender } = render(
<Dropdown options={getOptions()} selectedId={0} />,
);
const { dropdownLayoutDriver, inputDriver } = _driver;
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
rerender(<Dropdown options={getOptions()} selectedId={1} />);
expect(await dropdownLayoutDriver.isOptionSelected(1)).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 2');
});
it('should have no selection when selectedId is null', async () => {
const { driver: _driver } = render(
<Dropdown
options={[{ id: 0, value: 'Option 1' }]}
selectedId={null}
/>,
);
const { dropdownLayoutDriver, inputDriver } = _driver;
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(false);
expect(await inputDriver.getValue()).toBe('');
});
});
describe('Rerender', () => {
it('should clear selection when selectedId is updated to null', async () => {
const { driver: _driver, rerender } = render(
<Dropdown options={getOptions()} selectedId={0} />,
);
const { dropdownLayoutDriver, inputDriver } = _driver;
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(true);
expect(await inputDriver.getValue()).toBe('Option 1');
rerender(<Dropdown options={getOptions()} selectedId={null} />);
expect(await dropdownLayoutDriver.isOptionSelected(0)).toBe(false);
expect(await inputDriver.getValue()).toBe('');
});
});
describe('Properties', () => {
it('should not open dropdown on input click [when] readOnly prop is set to true', async () => {
const { dropdownLayoutDriver, inputDriver } = createDriver(
<Dropdown readOnly options={getOptions()} />,
);
await inputDriver.click();
expect(await dropdownLayoutDriver.isShown()).toBe(false);
});
});
}
});