Skip to content

Commit

Permalink
feat(Combobox): restrict custom values
Browse files Browse the repository at this point in the history
  • Loading branch information
pylafleur committed Mar 18, 2024
1 parent 307fdd0 commit 9fa52a1
Show file tree
Hide file tree
Showing 5 changed files with 300 additions and 114 deletions.
41 changes: 17 additions & 24 deletions packages/react/src/components/combobox/combobox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ describe('Combobox', () => {
expect(findByTestId(wrapper, 'listbox').length).toEqual(1);
});

test('opens when the textbox receives the focus and the input has a value', () => {
const wrapper = shallow(<Combobox options={provinces} defaultValue="Quebec" />);

getByTestId(wrapper, 'textbox').simulate('focus');

expect(getByTestId(wrapper, 'listbox').length).toEqual(1);
});

test('does not open when the textbox receives the focus and the input has no value', () => {
const wrapper = shallow(<Combobox options={provinces} />);

Expand Down Expand Up @@ -93,7 +85,7 @@ describe('Combobox', () => {
});

test('setting the prop to a arbitrary value assigns this value to the input', () => {
const wrapper = shallow(<Combobox options={provinces} defaultValue="Nowhere" />);
const wrapper = shallow(<Combobox options={provinces} allowCustomValue defaultValue="Nowhere" />);

expect(getByTestId(wrapper, 'textbox').prop('value')).toBe('Nowhere');
});
Expand Down Expand Up @@ -149,29 +141,30 @@ describe('Combobox', () => {

describe('list autocomplete', () => {
test('typing a valid letter opens the listbox', () => {
const wrapper = shallow(<Combobox options={provinces} autoComplete="list" />);
const wrapper = shallow(<Combobox options={provinces} />);

getByTestId(wrapper, 'textbox').simulate(
'change',
{ target: { value: 'q' } },
);

expect(getByTestId(wrapper, 'listbox').length).toEqual(1);
expect(getByTestId(wrapper, 'listbox').length).toBeGreaterThan(0);
});

test('typing an invalid letter does not open the listbox', () => {
const wrapper = shallow(<Combobox options={provinces} autoComplete="list" />);
test('typing an invalid letter opens the listbox with the no option placeholder', () => {
const wrapper = shallow(<Combobox options={provinces} />);

getByTestId(wrapper, 'textbox').simulate(
'change',
{ target: { value: 'z' } },
);

expect(getByTestId(wrapper, 'listbox').length).toEqual(0);
expect(getByTestId(wrapper, 'listbox').length).toEqual(1);
expect(getByTestId(wrapper, 'listbox').prop('options')[0].disabled).toBeTruthy();
});

test('typing a letter filters the list', () => {
const wrapper = shallow(<Combobox options={provinces} autoComplete="list" defaultOpen />);
const wrapper = shallow(<Combobox options={provinces} defaultOpen />);

getByTestId(wrapper, 'textbox').simulate(
'change',
Expand All @@ -185,7 +178,7 @@ describe('Combobox', () => {

test('erasing characters updates the list to match the remaining input', () => {
const wrapper = shallow(
<Combobox options={provinces} autoComplete="list" defaultOpen defaultValue="New B" />,
<Combobox options={provinces} defaultOpen defaultValue="New B" />,
);

getByTestId(wrapper, 'textbox').simulate(
Expand All @@ -207,7 +200,7 @@ describe('Combobox', () => {

describe('inline autocomplete', () => {
test('typing a valid letter opens the listbox', () => {
const wrapper = shallow(<Combobox options={provinces} autoComplete="inline" />);
const wrapper = shallow(<Combobox options={provinces} inlineAutoComplete />);

getByTestId(wrapper, 'textbox').simulate(
'change',
Expand All @@ -218,7 +211,7 @@ describe('Combobox', () => {
});

test('typing the first letter of an existing option autocompletes the input', () => {
const wrapper = shallow(<Combobox options={provinces} autoComplete="inline" />);
const wrapper = shallow(<Combobox options={provinces} inlineAutoComplete />);

getByTestId(wrapper, 'textbox').simulate(
'change',
Expand All @@ -229,7 +222,7 @@ describe('Combobox', () => {
});

test('the suggested part of the input is highlighted', async () => {
const wrapper = mountWithTheme(<Combobox options={provinces} autoComplete="inline" />);
const wrapper = mountWithTheme(<Combobox options={provinces} inlineAutoComplete />);

await actAndWaitForEffects(wrapper, () => {
getByTestId(wrapper, 'textbox').simulate(
Expand All @@ -243,7 +236,7 @@ describe('Combobox', () => {
});

test('erasing characters removes the suggestion', async () => {
const wrapper = mountWithTheme(<Combobox options={provinces} autoComplete="inline" defaultValue="Que" />);
const wrapper = mountWithTheme(<Combobox options={provinces} inlineAutoComplete defaultValue="Que" />);

await actAndWaitForEffects(wrapper, () => {
getByTestId(wrapper, 'textbox').simulate(
Expand All @@ -262,7 +255,7 @@ describe('Combobox', () => {
});

test('focusing an option with ArrowUp fills the input with its value', () => {
const wrapper = mountWithTheme(<Combobox options={provinces} autoComplete="inline" defaultOpen />);
const wrapper = mountWithTheme(<Combobox options={provinces} inlineAutoComplete defaultOpen />);

getByTestId(wrapper, 'textbox').simulate(
'keydown',
Expand All @@ -273,7 +266,7 @@ describe('Combobox', () => {
});

test('focusing an option with ArrowDown fills the input with its value', () => {
const wrapper = mountWithTheme(<Combobox options={provinces} autoComplete="inline" defaultOpen />);
const wrapper = mountWithTheme(<Combobox options={provinces} inlineAutoComplete defaultOpen />);

getByTestId(wrapper, 'textbox').simulate(
'keydown',
Expand All @@ -300,7 +293,7 @@ describe('Combobox', () => {
});

test('the input value is updated when the value prop changes to an arbitrary value', () => {
const wrapper = shallow(<Combobox options={provinces} value="Quebec" />);
const wrapper = shallow(<Combobox options={provinces} allowCustomValue value="Quebec" />);

wrapper.setProps({ value: 'Nowhere' }).update();

Expand Down Expand Up @@ -376,7 +369,7 @@ describe('Combobox', () => {
test('callback does not receive the suggestion when fired', () => {
const callback = jest.fn();
const wrapper = mountWithTheme(
<Combobox options={provinces} autoComplete="inline" onChange={callback} />,
<Combobox options={provinces} inlineAutoComplete onChange={callback} />,
);

getByTestId(wrapper, 'textbox').simulate(
Expand Down
96 changes: 88 additions & 8 deletions packages/react/src/components/combobox/combobox.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,26 @@ input + .c2 {
box-shadow: 0 0 0 2px #84C6EA;
}
.c5::-webkit-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c5::-moz-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c5:-ms-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c5::placeholder {
font-style: italic;
color: #B7BBC2;
}
.c8 {
-webkit-align-items: center;
-webkit-box-align: center;
Expand All @@ -233,7 +253,7 @@ input + .c2 {
height: var(--size-1x);
padding: var(--spacing-half);
position: absolute;
right: var(--spacing-half);
right: 0;
width: var(--size-1x);
}
Expand All @@ -255,7 +275,7 @@ input + .c2 {
class="c4"
>
<input
aria-autocomplete="none"
aria-autocomplete="list"
aria-controls="uuid1_listbox"
aria-expanded="true"
aria-invalid="false"
Expand Down Expand Up @@ -701,6 +721,26 @@ input + .c2 {
box-shadow: 0 0 0 2px #84C6EA;
}
.c7::-webkit-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c7::-moz-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c7:-ms-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c7::placeholder {
font-style: italic;
color: #B7BBC2;
}
.c10 {
-webkit-align-items: center;
-webkit-box-align: center;
Expand All @@ -716,7 +756,7 @@ input + .c2 {
height: var(--size-1x);
padding: var(--spacing-half);
position: absolute;
right: var(--spacing-half);
right: 0;
width: var(--size-1x);
}
Expand Down Expand Up @@ -754,7 +794,7 @@ input + .c2 {
class="c6"
>
<input
aria-autocomplete="none"
aria-autocomplete="list"
aria-controls="uuid1_listbox"
aria-describedby="uuid1_invalid"
aria-expanded="true"
Expand Down Expand Up @@ -1153,6 +1193,26 @@ exports[`Combobox matches the snapshot (mobile) 1`] = `
box-shadow: 0 0 0 2px #84C6EA;
}
.c3::-webkit-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c3::-moz-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c3:-ms-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c3::placeholder {
font-style: italic;
color: #B7BBC2;
}
.c6 {
-webkit-align-items: center;
-webkit-box-align: center;
Expand All @@ -1168,7 +1228,7 @@ exports[`Combobox matches the snapshot (mobile) 1`] = `
height: var(--size-1x);
padding: var(--spacing-half);
position: absolute;
right: var(--spacing-half);
right: 0;
width: var(--size-1x);
}
Expand All @@ -1183,7 +1243,7 @@ exports[`Combobox matches the snapshot (mobile) 1`] = `
class="c2"
>
<input
aria-autocomplete="none"
aria-autocomplete="list"
aria-controls="uuid1_listbox"
aria-expanded="true"
aria-invalid="false"
Expand Down Expand Up @@ -1615,6 +1675,26 @@ input + .c2 {
box-shadow: 0 0 0 2px #84C6EA;
}
.c6::-webkit-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c6::-moz-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c6:-ms-input-placeholder {
font-style: italic;
color: #B7BBC2;
}
.c6::placeholder {
font-style: italic;
color: #B7BBC2;
}
.c9 {
-webkit-align-items: center;
-webkit-box-align: center;
Expand All @@ -1630,7 +1710,7 @@ input + .c2 {
height: var(--size-1x);
padding: var(--spacing-half);
position: absolute;
right: var(--spacing-half);
right: 0;
width: var(--size-1x);
}
Expand Down Expand Up @@ -1658,7 +1738,7 @@ input + .c2 {
class="c5"
>
<input
aria-autocomplete="none"
aria-autocomplete="list"
aria-controls="uuid1_listbox"
aria-describedby="uuid1_hint"
aria-expanded="true"
Expand Down
Loading

0 comments on commit 9fa52a1

Please sign in to comment.