1- import { beforeEach , describe , expect , it , vi } from 'vitest' ;
2- import { SimpleChange } from '@angular/core' ;
3- import { ComponentFixture , TestBed } from '@angular/core/testing' ;
4- import { MatButtonModule } from '@angular/material/button' ;
5- import { MatIconModule } from '@angular/material/icon' ;
6- import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' ;
7- import { Observable , Subject , of , throwError } from 'rxjs' ;
8- import { PeerProgressIndicator } from 'src/app/api/models/peer-progress-indicator' ;
9- import { Task } from 'src/app/api/models/task' ;
10- import { TaskDefinition } from 'src/app/api/models/task-definition' ;
1+ import { beforeEach , describe , expect , it , vi } from 'vitest' ;
2+ import { SimpleChange } from '@angular/core' ;
3+ import { ComponentFixture , TestBed } from '@angular/core/testing' ;
4+ import { MatButtonModule } from '@angular/material/button' ;
5+ import { MatIconModule } from '@angular/material/icon' ;
6+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' ;
7+ import { Observable , Subject , of , throwError } from 'rxjs' ;
8+ import { PeerProgressIndicator } from 'src/app/api/models/peer-progress-indicator' ;
9+ import { Task } from 'src/app/api/models/task' ;
10+ import { TaskDefinition } from 'src/app/api/models/task-definition' ;
1111import {
1212 DISABLED_STATE ,
1313 NORMAL_STATE ,
@@ -16,24 +16,24 @@ import {
1616 UNAVAILABLE_STATE ,
1717 ZERO_PERCENT_STATE ,
1818} from 'src/app/api/services/mock' ;
19- import { PeerProgressIndicatorService } from 'src/app/api/services/peer-progress-indicator.service' ;
20- import { PpiWidgetComponent } from './ppi-widget.component' ;
19+ import { PeerProgressIndicatorService } from 'src/app/api/services/peer-progress-indicator.service' ;
20+ import { PpiWidgetComponent } from './ppi-widget.component' ;
2121
2222describe ( 'PpiWidgetComponent' , ( ) => {
2323 let component : PpiWidgetComponent ;
2424 let fixture : ComponentFixture < PpiWidgetComponent > ;
2525 let getIndicator : ReturnType < typeof vi . fn > ;
2626
27- const mockTask = { project : { unit : { id : 1 } , targetGrade : 2 } } as unknown as Task ;
28- const mockTaskDef = { id : 99 } as unknown as TaskDefinition ;
27+ const mockTask = { project : { unit : { id : 1 } , targetGrade : 2 } } as unknown as Task ;
28+ const mockTaskDef = { id : 99 } as unknown as TaskDefinition ;
2929
3030 beforeEach ( async ( ) => {
3131 getIndicator = vi . fn ( ) ;
3232
3333 await TestBed . configureTestingModule ( {
3434 declarations : [ PpiWidgetComponent ] ,
3535 imports : [ MatIconModule , MatProgressSpinnerModule , MatButtonModule ] ,
36- providers : [ { provide : PeerProgressIndicatorService , useValue : { getIndicator} } ] ,
36+ providers : [ { provide : PeerProgressIndicatorService , useValue : { getIndicator } } ] ,
3737 } ) . compileComponents ( ) ;
3838
3939 fixture = TestBed . createComponent ( PpiWidgetComponent ) ;
@@ -44,7 +44,7 @@ describe('PpiWidgetComponent', () => {
4444
4545 function load ( response$ : Observable < PeerProgressIndicator > ) {
4646 getIndicator . mockReturnValue ( response$ ) ;
47- component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
47+ component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
4848 fixture . detectChanges ( ) ;
4949 }
5050
@@ -97,7 +97,7 @@ describe('PpiWidgetComponent', () => {
9797 const subject : Subject < PeerProgressIndicator > = new Subject ( ) ;
9898 getIndicator . mockReturnValue ( subject . asObservable ( ) ) ;
9999
100- component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
100+ component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
101101 expect ( component . view . state ) . toBe ( 'loading' ) ;
102102
103103 subject . next ( NORMAL_STATE ) ;
@@ -108,7 +108,7 @@ describe('PpiWidgetComponent', () => {
108108 const subject : Subject < PeerProgressIndicator > = new Subject ( ) ;
109109 getIndicator . mockReturnValue ( subject . asObservable ( ) ) ;
110110
111- component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
111+ component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
112112 expect ( component . view . state ) . toBe ( 'loading' ) ;
113113
114114 subject . error ( new Error ( 'network down' ) ) ;
@@ -133,13 +133,36 @@ describe('PpiWidgetComponent', () => {
133133 . mockReturnValueOnce ( first . asObservable ( ) )
134134 . mockReturnValueOnce ( second . asObservable ( ) ) ;
135135
136- component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
137- component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
136+ component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
137+ component . ngOnChanges ( { task : new SimpleChange ( null , mockTask , true ) } ) ;
138138
139139 first . next ( NORMAL_STATE ) ;
140140 expect ( component . view . state ) . toBe ( 'loading' ) ;
141141
142142 second . next ( SUPPRESSED_STATE ) ;
143143 expect ( component . view . state ) . toBe ( 'hidden' ) ;
144144 } ) ;
145+
146+ it ( 'hides decorative icons from screen readers' , ( ) => {
147+ load ( throwError ( ( ) => new Error ( 'network down' ) ) ) ;
148+ fixture . detectChanges ( ) ;
149+
150+ const icons = fixture . nativeElement . querySelectorAll ( 'mat-icon' ) ;
151+
152+ icons . forEach ( ( icon : HTMLElement ) => {
153+ expect ( icon . getAttribute ( 'aria-hidden' ) ) . toBe ( 'true' ) ;
154+ } ) ;
155+ } ) ;
156+
157+ it ( 'provides an accessible name for the peer progress value' , ( ) => {
158+ load ( of ( NORMAL_STATE ) ) ;
159+ fixture . detectChanges ( ) ;
160+
161+ const value = fixture . nativeElement . querySelector (
162+ '.ppi-widget:not(.ppi-widget--muted) span[aria-label="Peer submission progress"]' ,
163+ ) ;
164+
165+ expect ( value ) . toBeTruthy ( ) ;
166+ expect ( value . textContent ) . toContain ( '42%' ) ;
167+ } ) ;
145168} ) ;
0 commit comments