@open-mercato/ui 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6930.1.1e5976efc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -71,7 +71,7 @@ describe('ComboboxInput clearable behavior', () => {
71
71
  />
72
72
  )
73
73
 
74
- const input = screen.getByRole('textbox') as HTMLInputElement
74
+ const input = screen.getByRole('combobox') as HTMLInputElement
75
75
  expect(input.value).toBe('Red')
76
76
 
77
77
  fireEvent.focus(input)
@@ -96,7 +96,7 @@ describe('ComboboxInput clearable behavior', () => {
96
96
  />
97
97
  )
98
98
 
99
- const input = screen.getByRole('textbox') as HTMLInputElement
99
+ const input = screen.getByRole('combobox') as HTMLInputElement
100
100
  fireEvent.focus(input)
101
101
  fireEvent.change(input, { target: { value: '' } })
102
102
 
@@ -111,7 +111,7 @@ describe('ComboboxInput clearable behavior', () => {
111
111
  const onChange = jest.fn()
112
112
  render(<Harness initialValue="red" clearable onChange={onChange} />)
113
113
 
114
- const input = screen.getByRole('textbox') as HTMLInputElement
114
+ const input = screen.getByRole('combobox') as HTMLInputElement
115
115
  expect(input.value).toBe('Red')
116
116
 
117
117
  const clearBtn = screen.getByRole('button', { name: /clear value/i })
@@ -86,3 +86,80 @@ describe('LookupSelect onReady stability', () => {
86
86
  expect(input.value).toBe('Mercato Fashion Online')
87
87
  })
88
88
  })
89
+
90
+ describe('LookupSelect keyboard accessibility', () => {
91
+ const ITEMS = [
92
+ { id: 'plot-1', title: 'Fazenda Norte' },
93
+ { id: 'plot-2', title: 'Fazenda Sul' },
94
+ ]
95
+
96
+ function renderWithResults(onChange: (next: string | null) => void) {
97
+ const utils = render(
98
+ <LookupSelect
99
+ value={null}
100
+ onChange={onChange}
101
+ fetchItems={async () => ITEMS}
102
+ minQuery={2}
103
+ />,
104
+ )
105
+ return utils
106
+ }
107
+
108
+ it('exposes combobox/listbox/option semantics once results render', async () => {
109
+ const { container } = renderWithResults(() => {})
110
+ const input = getInput(container)
111
+ expect(input).toHaveAttribute('role', 'combobox')
112
+ expect(input).toHaveAttribute('aria-autocomplete', 'list')
113
+
114
+ fireEvent.change(input, { target: { value: 'Faz' } })
115
+ const options = await screen.findAllByRole('option')
116
+ expect(options).toHaveLength(2)
117
+ expect(screen.getByRole('listbox')).toBeInTheDocument()
118
+ expect(input).toHaveAttribute('aria-expanded', 'true')
119
+ })
120
+
121
+ it('selects the highlighted result with ArrowDown + Enter', async () => {
122
+ const onChange = jest.fn()
123
+ const { container } = renderWithResults(onChange)
124
+ const input = getInput(container)
125
+
126
+ fireEvent.change(input, { target: { value: 'Faz' } })
127
+ await screen.findAllByRole('option')
128
+
129
+ fireEvent.keyDown(input, { key: 'ArrowDown' })
130
+ expect(input).toHaveAttribute('aria-activedescendant')
131
+ fireEvent.keyDown(input, { key: 'Enter' })
132
+ expect(onChange).toHaveBeenCalledWith('plot-1')
133
+ })
134
+
135
+ it('moves the highlight with repeated arrows and wraps', async () => {
136
+ const onChange = jest.fn()
137
+ const { container } = renderWithResults(onChange)
138
+ const input = getInput(container)
139
+
140
+ fireEvent.change(input, { target: { value: 'Faz' } })
141
+ await screen.findAllByRole('option')
142
+
143
+ fireEvent.keyDown(input, { key: 'ArrowDown' })
144
+ fireEvent.keyDown(input, { key: 'ArrowDown' })
145
+ fireEvent.keyDown(input, { key: 'Enter' })
146
+ expect(onChange).toHaveBeenCalledWith('plot-2')
147
+ })
148
+
149
+ it('clears the query with Escape instead of leaking it to the dialog', async () => {
150
+ const escapeSpy = jest.fn()
151
+ const { container } = render(
152
+ <div onKeyDown={escapeSpy}>
153
+ <LookupSelect value={null} onChange={() => {}} fetchItems={async () => ITEMS} minQuery={2} />
154
+ </div>,
155
+ )
156
+ const input = getInput(container)
157
+ fireEvent.change(input, { target: { value: 'Faz' } })
158
+ await screen.findAllByRole('option')
159
+
160
+ escapeSpy.mockClear()
161
+ fireEvent.keyDown(input, { key: 'Escape' })
162
+ expect(input.value).toBe('')
163
+ expect(escapeSpy).not.toHaveBeenCalled()
164
+ })
165
+ })