1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16import {Component, Inject} from '@angular/core'; 17import {ComponentFixture, TestBed} from '@angular/core/testing'; 18import {MatButtonModule} from '@angular/material/button'; 19import {MatCheckboxModule} from '@angular/material/checkbox'; 20import { 21 MatDialog, 22 MatDialogModule, 23 MatDialogRef, 24} from '@angular/material/dialog'; 25import {MatIconModule} from '@angular/material/icon'; 26import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 27import {assertDefined} from 'common/assert_utils'; 28import { 29 WarningDialogComponent, 30 WarningDialogData, 31 WarningDialogResult, 32} from './warning_dialog_component'; 33 34describe('WarningDialogComponent', () => { 35 let fixture: ComponentFixture<TestHostComponent>; 36 let component: TestHostComponent; 37 let htmlElement: HTMLElement; 38 39 beforeEach(async () => { 40 await TestBed.configureTestingModule({ 41 imports: [ 42 MatIconModule, 43 MatDialogModule, 44 MatCheckboxModule, 45 MatButtonModule, 46 BrowserAnimationsModule, 47 ], 48 declarations: [TestHostComponent, WarningDialogComponent], 49 }).compileComponents(); 50 fixture = TestBed.createComponent(TestHostComponent); 51 component = fixture.componentInstance; 52 htmlElement = fixture.nativeElement; 53 fixture.detectChanges(); 54 }); 55 56 it('can be created', () => { 57 expect(document.querySelector('warning-dialog')).toBeNull(); 58 openAndReturnDialog(); 59 }); 60 61 it('renders warning message, action boxes and buttons', () => { 62 const dialog = openAndReturnDialog(); 63 64 const content = assertDefined(dialog.querySelector('.warning-content')); 65 expect(content.querySelector('.warning-message')?.textContent).toContain( 66 'test message', 67 ); 68 69 const actionBoxContainer = assertDefined( 70 content.querySelector('.warning-action-boxes'), 71 ); 72 expect(actionBoxContainer.textContent).toContain('option1'); 73 expect(actionBoxContainer.textContent).toContain('option2'); 74 75 const actionButtonContainer = assertDefined( 76 content.querySelector('.warning-action-buttons'), 77 ); 78 expect(actionButtonContainer.textContent).toContain('action1'); 79 expect(actionButtonContainer.textContent).toContain('action2'); 80 expect(actionButtonContainer.textContent).toContain('close message'); 81 }); 82 83 it('provides action text and selected options as dialog result on close', async () => { 84 const dialog = openAndReturnDialog(); 85 86 const actionButton = assertDefined( 87 dialog.querySelector('.warning-action-buttons button'), 88 ) as HTMLElement; 89 actionButton.click(); 90 fixture.detectChanges(); 91 await fixture.whenStable(); 92 93 expect(component.dialogResult).toEqual({ 94 closeActionText: 'action1', 95 selectedOptions: [], 96 }); 97 }); 98 99 it('provides close text and selected options as dialog result on close', async () => { 100 const dialog = openAndReturnDialog(); 101 102 const buttons = assertDefined( 103 dialog.querySelectorAll('.warning-action-buttons button'), 104 ); 105 (buttons.item(buttons.length - 1) as HTMLElement).click(); 106 fixture.detectChanges(); 107 await fixture.whenStable(); 108 109 expect(component.dialogResult).toEqual({ 110 closeActionText: 'close message', 111 selectedOptions: [], 112 }); 113 }); 114 115 it('updates selected options and provides selected options in dialog result', async () => { 116 const dialog = openAndReturnDialog(); 117 118 const option = assertDefined( 119 dialog.querySelector('.warning-action-boxes mat-checkbox input'), 120 ) as HTMLInputElement; 121 option.checked = true; 122 option.click(); 123 fixture.detectChanges(); 124 125 const buttons = assertDefined( 126 dialog.querySelectorAll('.warning-action-buttons button'), 127 ); 128 (buttons.item(buttons.length - 1) as HTMLElement).click(); 129 fixture.detectChanges(); 130 await fixture.whenStable(); 131 132 expect(component.dialogResult).toEqual({ 133 closeActionText: 'close message', 134 selectedOptions: ['option1'], 135 }); 136 }); 137 138 function openAndReturnDialog(): HTMLElement { 139 htmlElement.querySelector('button')?.click(); 140 fixture.detectChanges(); 141 return assertDefined( 142 document.querySelector('warning-dialog'), 143 ) as HTMLElement; 144 } 145 146 @Component({ 147 selector: 'host-component', 148 template: ` 149 <button (click)="onClick()"></button> 150 `, 151 }) 152 class TestHostComponent { 153 dialogRef: MatDialogRef<WarningDialogComponent> | undefined; 154 dialogResult: WarningDialogResult | undefined; 155 156 constructor(@Inject(MatDialog) public dialog: MatDialog) {} 157 158 onClick() { 159 const data: WarningDialogData = { 160 message: 'test message', 161 actions: ['action1', 'action2'], 162 options: ['option1', 'option2'], 163 closeText: 'close message', 164 }; 165 this.dialogRef = this.dialog.open(WarningDialogComponent, {data}); 166 this.dialogRef 167 .afterClosed() 168 .subscribe(async (result: WarningDialogResult) => { 169 this.dialogResult = result; 170 }); 171 } 172 } 173}); 174