66 * found in the LICENSE file at https://angular.dev/license
77 */
88
9- import { signal } from '@angular/core' ;
9+ import { signal , WritableSignal } from '@angular/core' ;
1010import { ListboxInputs , ListboxPattern } from './listbox' ;
1111import { OptionPattern } from './option' ;
1212import { createKeyboardEvent } from '@angular/cdk/testing/private' ;
@@ -33,6 +33,7 @@ describe('Listbox Pattern', () => {
3333 activeIndex : inputs . activeIndex ?? signal ( 0 ) ,
3434 typeaheadDelay : inputs . typeaheadDelay ?? signal ( 0.5 ) ,
3535 wrap : inputs . wrap ?? signal ( true ) ,
36+ readonly : inputs . readonly ?? signal ( false ) ,
3637 disabled : inputs . disabled ?? signal ( false ) ,
3738 skipDisabled : inputs . skipDisabled ?? signal ( true ) ,
3839 multi : inputs . multi ?? signal ( false ) ,
@@ -148,6 +149,18 @@ describe('Listbox Pattern', () => {
148149 listbox . onKeydown ( end ( ) ) ;
149150 expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 8 ) ;
150151 } ) ;
152+
153+ it ( 'should be able to navigate in readonly mode' , ( ) => {
154+ const { listbox} = getDefaultPatterns ( ) ;
155+ listbox . onKeydown ( down ( ) ) ;
156+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 1 ) ;
157+ listbox . onKeydown ( up ( ) ) ;
158+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 0 ) ;
159+ listbox . onKeydown ( end ( ) ) ;
160+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 8 ) ;
161+ listbox . onKeydown ( home ( ) ) ;
162+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 0 ) ;
163+ } ) ;
151164 } ) ;
152165
153166 describe ( 'Keyboard Selection' , ( ) => {
@@ -178,6 +191,22 @@ describe('Listbox Pattern', () => {
178191 expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 0 ) ;
179192 expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
180193 } ) ;
194+
195+ it ( 'should not be able to change selection when in readonly mode' , ( ) => {
196+ const { listbox} = getDefaultPatterns ( {
197+ value : signal ( [ 'Apple' ] ) ,
198+ readonly : signal ( true ) ,
199+ multi : signal ( false ) ,
200+ selectionMode : signal ( 'follow' ) ,
201+ } ) ;
202+
203+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 0 ) ;
204+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
205+
206+ listbox . onKeydown ( down ( ) ) ;
207+ expect ( listbox . inputs . activeIndex ( ) ) . toBe ( 1 ) ;
208+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
209+ } ) ;
181210 } ) ;
182211
183212 describe ( 'explicit focus & single select' , ( ) => {
@@ -207,6 +236,17 @@ describe('Listbox Pattern', () => {
207236 listbox . onKeydown ( enter ( ) ) ;
208237 expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apricot' ] ) ;
209238 } ) ;
239+
240+ it ( 'should not be able to change selection when in readonly mode' , ( ) => {
241+ const readonly = listbox . inputs . readonly as WritableSignal < boolean > ;
242+ readonly . set ( true ) ;
243+ listbox . onKeydown ( space ( ) ) ;
244+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
245+
246+ listbox . onKeydown ( down ( ) ) ;
247+ listbox . onKeydown ( enter ( ) ) ;
248+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
249+ } ) ;
210250 } ) ;
211251
212252 describe ( 'explicit focus & multi select' , ( ) => {
@@ -277,6 +317,29 @@ describe('Listbox Pattern', () => {
277317 listbox . onKeydown ( end ( { control : true , shift : true } ) ) ;
278318 expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Cantaloupe' , 'Cherry' , 'Clementine' , 'Cranberry' ] ) ;
279319 } ) ;
320+
321+ it ( 'should not be able to change selection when in readonly mode' , ( ) => {
322+ const readonly = listbox . inputs . readonly as WritableSignal < boolean > ;
323+ readonly . set ( true ) ;
324+ listbox . onKeydown ( space ( ) ) ;
325+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
326+
327+ listbox . onKeydown ( down ( ) ) ;
328+ listbox . onKeydown ( enter ( ) ) ;
329+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
330+
331+ listbox . onKeydown ( up ( { shift : true } ) ) ;
332+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
333+
334+ listbox . onKeydown ( down ( { shift : true } ) ) ;
335+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
336+
337+ listbox . onKeydown ( end ( { control : true , shift : true } ) ) ;
338+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
339+
340+ listbox . onKeydown ( home ( { control : true , shift : true } ) ) ;
341+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ ] ) ;
342+ } ) ;
280343 } ) ;
281344
282345 describe ( 'follows focus & multi select' , ( ) => {
@@ -361,6 +424,19 @@ describe('Listbox Pattern', () => {
361424 listbox . onKeydown ( end ( { control : true , shift : true } ) ) ;
362425 expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Cantaloupe' , 'Cherry' , 'Clementine' , 'Cranberry' ] ) ;
363426 } ) ;
427+
428+ it ( 'should not be able to change selection when in readonly mode' , ( ) => {
429+ const readonly = listbox . inputs . readonly as WritableSignal < boolean > ;
430+ readonly . set ( true ) ;
431+ listbox . onKeydown ( down ( ) ) ;
432+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
433+
434+ listbox . onKeydown ( up ( ) ) ;
435+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
436+
437+ listbox . onKeydown ( space ( { control : true } ) ) ;
438+ expect ( listbox . inputs . value ( ) ) . toEqual ( [ 'Apple' ] ) ;
439+ } ) ;
364440 } ) ;
365441 } ) ;
366442} ) ;
0 commit comments