266 lines
8.5 KiB
TypeScript
266 lines
8.5 KiB
TypeScript
|
import { suite, test, beforeEach, expect } from 'vitest';
|
|||
|
|
|||
|
import { Combobox, Option, State } from './combobox';
|
|||
|
|
|||
|
suite('Combobox', () => {
|
|||
|
const options: Option[] =
|
|||
|
'Fraises,Myrtilles,Framboises,Mûres,Canneberges,Groseilles,Baies de sureau,Mûres blanches,Baies de genièvre,Baies d’açaï'
|
|||
|
.split(',')
|
|||
|
.map((label) => ({ label, value: label }));
|
|||
|
|
|||
|
let combobox: Combobox;
|
|||
|
let currentState: State;
|
|||
|
|
|||
|
suite('single select without custom value', () => {
|
|||
|
suite('with default selection', () => {
|
|||
|
beforeEach(() => {
|
|||
|
combobox = new Combobox({
|
|||
|
options,
|
|||
|
selected: options.at(0) ?? null,
|
|||
|
render: (state) => {
|
|||
|
currentState = state;
|
|||
|
}
|
|||
|
});
|
|||
|
combobox.init();
|
|||
|
});
|
|||
|
|
|||
|
test('open select box and select option with click', () => {
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection?.label).toBe('Fraises');
|
|||
|
|
|||
|
combobox.open();
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
|
|||
|
combobox.select('Mûres');
|
|||
|
expect(currentState.selection?.label).toBe('Mûres');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
});
|
|||
|
|
|||
|
test('open select box and select option with enter', () => {
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection?.label).toBe('Fraises');
|
|||
|
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.selection?.label).toBe('Fraises');
|
|||
|
expect(currentState.focused?.label).toBe('Fraises');
|
|||
|
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.selection?.label).toBe('Fraises');
|
|||
|
expect(currentState.focused?.label).toBe('Myrtilles');
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.selection?.label).toBe('Myrtilles');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.selection?.label).toBe('Myrtilles');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
});
|
|||
|
|
|||
|
test('open select box and select option with tab', () => {
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
|
|||
|
combobox.keyboard('Tab');
|
|||
|
expect(currentState.selection?.label).toBe('Myrtilles');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.hint).toEqual({
|
|||
|
type: 'selected',
|
|||
|
label: 'Myrtilles'
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
test('do not open select box on focus', () => {
|
|||
|
combobox.focus();
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
suite('empty', () => {
|
|||
|
beforeEach(() => {
|
|||
|
combobox = new Combobox({
|
|||
|
options,
|
|||
|
selected: null,
|
|||
|
render: (state) => {
|
|||
|
currentState = state;
|
|||
|
}
|
|||
|
});
|
|||
|
combobox.init();
|
|||
|
});
|
|||
|
|
|||
|
test('open select box on focus', () => {
|
|||
|
combobox.focus();
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
});
|
|||
|
|
|||
|
suite('open', () => {
|
|||
|
beforeEach(() => {
|
|||
|
combobox.open();
|
|||
|
});
|
|||
|
|
|||
|
test('if tab on empty input nothing is selected', () => {
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
combobox.keyboard('Tab');
|
|||
|
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
});
|
|||
|
|
|||
|
test('if enter on empty input nothing is selected', () => {
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
suite('closed', () => {
|
|||
|
test('if tab on empty input nothing is selected', () => {
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Tab');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
});
|
|||
|
|
|||
|
test('if enter on empty input nothing is selected', () => {
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
test('type exact match and press enter', () => {
|
|||
|
combobox.input('Baies');
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.options.length).toEqual(3);
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection?.label).toBe('Baies d’açaï');
|
|||
|
});
|
|||
|
|
|||
|
test('type exact match and press tab', () => {
|
|||
|
combobox.input('Baies');
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Tab');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection?.label).toBe('Baies d’açaï');
|
|||
|
expect(currentState.inputValue).toEqual('Baies d’açaï');
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and press enter', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('');
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and press tab', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Tab');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('');
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and close', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.close();
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('');
|
|||
|
});
|
|||
|
|
|||
|
test('focus should circle', () => {
|
|||
|
combobox.input('Baie');
|
|||
|
expect(currentState.open).toBeTruthy();
|
|||
|
expect(currentState.options.map(({ label }) => label)).toEqual([
|
|||
|
'Baies d’açaï',
|
|||
|
'Baies de genièvre',
|
|||
|
'Baies de sureau'
|
|||
|
]);
|
|||
|
expect(currentState.focused).toBeNull();
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.focused?.label).toBe('Baies d’açaï');
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.focused?.label).toBe('Baies de genièvre');
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.focused?.label).toBe('Baies de sureau');
|
|||
|
combobox.keyboard('ArrowDown');
|
|||
|
expect(currentState.focused?.label).toBe('Baies d’açaï');
|
|||
|
combobox.keyboard('ArrowUp');
|
|||
|
expect(currentState.focused?.label).toBe('Baies de sureau');
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
suite('single select with custom value', () => {
|
|||
|
beforeEach(() => {
|
|||
|
combobox = new Combobox({
|
|||
|
options,
|
|||
|
selected: null,
|
|||
|
allowsCustomValue: true,
|
|||
|
render: (state) => {
|
|||
|
currentState = state;
|
|||
|
}
|
|||
|
});
|
|||
|
combobox.init();
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and press enter', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Enter');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('toto');
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and press tab', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.keyboard('Tab');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('toto');
|
|||
|
});
|
|||
|
|
|||
|
test('type non matching input and close', () => {
|
|||
|
combobox.input('toto');
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
|
|||
|
combobox.close();
|
|||
|
expect(currentState.open).toBeFalsy();
|
|||
|
expect(currentState.selection).toBeNull();
|
|||
|
expect(currentState.inputValue).toEqual('toto');
|
|||
|
});
|
|||
|
});
|
|||
|
});
|