import React from 'react';
import { render } from '@testing-library/react';
import { Icon } from '@leafygreen-ui/icon';
import { ComboboxGroup, ComboboxOption } from '..';
import {
flattenChildren,
getDisplayNameForValue,
getNameAndValue,
wrapJSX,
} from '.';
describe('packages/combobox/utils', () => {
describe('wrapJSX', () => {
test('Wraps the matched string in the provided element', () => {
const JSX = wrapJSX('Apple', 'pp', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('pp');
expect(container).toHaveTextContent('Apple');
});
test('Wraps the entire string when it matches', () => {
const JSX = wrapJSX('Apple', 'Apple', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('Apple');
expect(container).toHaveTextContent('Apple');
});
test('Keeps case consistent with source', () => {
const JSX = wrapJSX('Apple', 'aPPlE', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('Apple');
expect(container).toHaveTextContent('Apple');
});
// No match
test('Wraps nothing when there is no match', () => {
const JSX = wrapJSX('Apple', 'q', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(0);
expect(container).toHaveTextContent('Apple');
});
// Multiple matches
test('wraps all instances of a match', () => {
const JSX = wrapJSX('Pepper', 'p', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(3);
expect(ems[0]).toHaveTextContent('P');
expect(ems[1]).toHaveTextContent('p');
expect(ems[2]).toHaveTextContent('p');
expect(container).toHaveTextContent('Pepper');
});
test('wraps all instances of longer match', () => {
const JSX = wrapJSX('Pepper', 'pe', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(2);
expect(ems[0]).toHaveTextContent('Pe');
expect(ems[1]).toHaveTextContent('pe');
expect(container).toHaveTextContent('Pepper');
});
// No `wrap`
test('Returns the input string when "wrap" is empty', () => {
const JSX = wrapJSX('Apple', '', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(0);
expect(container).toHaveTextContent(`Apple`);
});
test('Returns the input string when "wrap" is `undefined`', () => {
const JSX = wrapJSX('Apple', undefined, 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(0);
expect(container).toHaveTextContent(`Apple`);
});
// No `element`
test('Returns the input string when "element" is empty', () => {
const JSX = wrapJSX('Apple', 'ap', '' as keyof HTMLElementTagNameMap);
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(0);
expect(container).toHaveTextContent(`Apple`);
});
test('Returns the input string when "element" is undefined', () => {
const JSX = wrapJSX('Apple', 'ap');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(0);
expect(container).toHaveTextContent(`Apple`);
});
// Sanitization
test('Wraps a string that contains a Regex special character', () => {
const JSX = wrapJSX('*(foo)', '*(', 'em');
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('*(');
expect(container).toHaveTextContent('*(foo');
});
test('Wraps a string that contains a long Regex string', () => {
const JSX = wrapJSX(
'^(([a-z])+.)+[A-Z]([a-z])+$',
'^(([a-z])+.)+[A-Z]([a-z])+$',
'em',
);
const { container } = render(JSX);
const ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('^(([a-z])+.)+[A-Z]([a-z])+$');
expect(container).toHaveTextContent('^(([a-z])+.)+[A-Z]([a-z])+$');
});
// Multiple calls
test('Updates after a second call', () => {
const JSX = wrapJSX('Apple', 'p', 'em');
const { container, rerender } = render(JSX);
let ems = container.querySelectorAll('em');
expect(ems).toHaveLength(2);
const JSX2 = wrapJSX('Apple', 'pp', 'em');
rerender(JSX2);
ems = container.querySelectorAll('em');
expect(ems).toHaveLength(1);
expect(ems[0]).toHaveTextContent('pp');
expect(container).toHaveTextContent(`Apple`);
});
});
describe('getNameAndValue', () => {
test('Returns both value and displayName as given', () => {
const result = getNameAndValue({
value: 'value',
displayName: 'Display Name',
});
expect(result).toEqual({ value: 'value', displayName: 'Display Name' });
});
test('Returns a generated displayName', () => {
const result = getNameAndValue({ value: 'value' });
expect(result).toEqual({ value: 'value', displayName: 'value' });
});
test('Returns a generated value', () => {
const result = getNameAndValue({ displayName: 'Display Name' });
expect(result).toEqual({
value: 'display-name',
displayName: 'Display Name',
});
});
});
describe('getDisplayNameForValue', () => {
const options = [
{ value: 'apple', displayName: 'Apple', isDisabled: false },
{ value: 'banana', displayName: 'Banana', isDisabled: false },
{ value: 'carrot', displayName: 'Carrot', isDisabled: true },
];
test('Returns the displayName when a matching option is found', () => {
const result = getDisplayNameForValue('apple', options);
expect(result).toBe('Apple');
});
test('Returns the value when no matching option is found', () => {
const result = getDisplayNameForValue('unknown', options);
expect(result).toBe('unknown');
});
test('Returns empty string when value is null', () => {
const result = getDisplayNameForValue(null, options);
expect(result).toBe('');
});
test('Returns empty string when value is empty string', () => {
const result = getDisplayNameForValue('', options);
expect(result).toBe('');
});
test('Returns displayName for disabled option', () => {
const result = getDisplayNameForValue('carrot', options);
expect(result).toBe('Carrot');
});
test('Returns empty string when options array is empty and value is null', () => {
const result = getDisplayNameForValue(null, []);
expect(result).toBe('');
});
test('Returns value when options array is empty but value is provided', () => {
const result = getDisplayNameForValue('test', []);
expect(result).toBe('test');
});
test('Returns string displayName when option has string displayName', () => {
const optionsWithString = [
{
value: 'string-option',
displayName: 'Bold text',
isDisabled: false,
},
];
const result = getDisplayNameForValue('string-option', optionsWithString);
expect(result).toBe('Bold text');
});
});
describe('flattenChildren', () => {
test('returns a single option', () => {
const children = ;
const flat = flattenChildren(children);
expect(flat).toEqual([
{
value: 'test',
displayName: 'Test',
hasGlyph: false,
isDisabled: false,
badge: undefined,
},
]);
});
test('returns multiple options', () => {
const children = [
,
,
];
const flat = flattenChildren(children);
expect(flat).toEqual([
{
value: 'apple',
displayName: 'Apple',
hasGlyph: false,
isDisabled: false,
badge: undefined,
},
{
value: 'banana',
displayName: 'Banana',
hasGlyph: false,
isDisabled: false,
badge: undefined,
},
]);
});
test('returns hasGlyph and isDisabled', () => {
const children = (
}
disabled
/>
);
const flat = flattenChildren(children);
expect(flat).toEqual([
{
value: 'test',
displayName: 'Test',
hasGlyph: true,
isDisabled: true,
badge: undefined,
},
]);
});
test('flattens options with customContent', () => {
const children = [
Testing
New
}
/>,
}
disabled
/>,
];
const flat = flattenChildren(children);
expect(flat).toEqual([
{
value: 'test',
displayName: 'Testing New',
hasGlyph: false,
isDisabled: false,
},
{
value: 'test',
displayName: 'Test',
hasGlyph: true,
isDisabled: true,
},
]);
});
test('flattens nested options', () => {
const children = [
,
,
,
];
const flat = flattenChildren(children);
expect(flat).toEqual([
{
value: 'apple',
displayName: 'Apple',
hasGlyph: false,
isDisabled: false,
},
{
value: 'banana',
displayName: 'Banana',
hasGlyph: false,
isDisabled: false,
},
{
value: 'ghost',
displayName: 'Ghost',
hasGlyph: false,
isDisabled: false,
},
{
value: 'habanero',
displayName: 'Habanero',
hasGlyph: false,
isDisabled: false,
},
]);
});
});
});