1/* 2 * Copyright (C) 2022 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 {CommonModule} from '@angular/common'; 17import {NO_ERRORS_SCHEMA} from '@angular/core'; 18import {ComponentFixture, TestBed} from '@angular/core/testing'; 19import {FormsModule} from '@angular/forms'; 20import {MatButtonModule} from '@angular/material/button'; 21import {MatFormFieldModule} from '@angular/material/form-field'; 22import {MatIconModule} from '@angular/material/icon'; 23import {MatInputModule} from '@angular/material/input'; 24import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 25import {assertDefined} from 'common/assert_utils'; 26import {Download} from 'common/download'; 27import {ConnectionState} from 'trace_collection/connection_state'; 28import {WinscopeProxySetupComponent} from './winscope_proxy_setup_component'; 29 30describe('WinscopeProxySetupComponent', () => { 31 let fixture: ComponentFixture<WinscopeProxySetupComponent>; 32 let component: WinscopeProxySetupComponent; 33 let htmlElement: HTMLElement; 34 35 beforeEach(async () => { 36 await TestBed.configureTestingModule({ 37 imports: [ 38 CommonModule, 39 MatIconModule, 40 MatFormFieldModule, 41 MatInputModule, 42 BrowserAnimationsModule, 43 MatButtonModule, 44 FormsModule, 45 ], 46 declarations: [WinscopeProxySetupComponent], 47 schemas: [NO_ERRORS_SCHEMA], 48 }).compileComponents(); 49 fixture = TestBed.createComponent(WinscopeProxySetupComponent); 50 component = fixture.componentInstance; 51 htmlElement = fixture.nativeElement; 52 component.state = ConnectionState.CONNECTING; 53 }); 54 55 it('can be created', () => { 56 expect(component).toBeTruthy(); 57 }); 58 59 it('correct connecting message', () => { 60 fixture.detectChanges(); 61 expect( 62 htmlElement.querySelector('.connecting-message')?.textContent, 63 ).toContain('Connecting...'); 64 }); 65 66 it('correct icon and message displays if no proxy', () => { 67 component.state = ConnectionState.NOT_FOUND; 68 fixture.detectChanges(); 69 expect( 70 htmlElement.querySelector('.further-adb-info-text')?.textContent, 71 ).toContain('Launch the Winscope ADB Connect proxy'); 72 }); 73 74 it('correct icon and message displays if invalid proxy', () => { 75 component.state = ConnectionState.INVALID_VERSION; 76 fixture.detectChanges(); 77 expect( 78 htmlElement.querySelector('.further-adb-info-text')?.textContent, 79 ).toContain( 80 `Your local proxy version is incompatible with Winscope. Please update the proxy to version ${component.proxyVersion}.`, 81 ); 82 expect(htmlElement.querySelector('.adb-icon')?.textContent).toEqual( 83 'update', 84 ); 85 }); 86 87 it('correct icon and message displays if unauthorized proxy', () => { 88 component.state = ConnectionState.UNAUTH; 89 fixture.detectChanges(); 90 expect(htmlElement.querySelector('.adb-info')?.textContent).toEqual( 91 'Proxy authorization required.', 92 ); 93 expect(htmlElement.querySelector('.adb-icon')?.textContent).toEqual('lock'); 94 }); 95 96 it('download proxy button downloads proxy', () => { 97 component.state = ConnectionState.NOT_FOUND; 98 fixture.detectChanges(); 99 const spy = spyOn(Download, 'fromUrl'); 100 const button = assertDefined( 101 htmlElement.querySelector<HTMLButtonElement>('.download-proxy-btn'), 102 ); 103 button.click(); 104 fixture.detectChanges(); 105 expect(spy).toHaveBeenCalledWith( 106 component.downloadProxyUrl, 107 'winscope_proxy.py', 108 ); 109 }); 110 111 it('retry button emits event', () => { 112 component.state = ConnectionState.NOT_FOUND; 113 fixture.detectChanges(); 114 115 const spy = spyOn(assertDefined(component.retryConnection), 'emit'); 116 const button = assertDefined( 117 htmlElement.querySelector<HTMLButtonElement>('.retry'), 118 ); 119 button.click(); 120 fixture.detectChanges(); 121 expect(spy).toHaveBeenCalledWith(''); 122 }); 123 124 it('input proxy token saved as expected', () => { 125 const spy = spyOn(assertDefined(component.retryConnection), 'emit'); 126 component.state = ConnectionState.UNAUTH; 127 fixture.detectChanges(); 128 129 const button = assertDefined( 130 htmlElement.querySelector<HTMLButtonElement>('.retry'), 131 ); 132 button.click(); 133 fixture.detectChanges(); 134 expect(spy).not.toHaveBeenCalled(); 135 136 const proxyTokenInput = assertDefined( 137 htmlElement.querySelector<HTMLInputElement>( 138 '.proxy-token-input-field input', 139 ), 140 ); 141 proxyTokenInput.value = '12345'; 142 proxyTokenInput.dispatchEvent(new Event('input')); 143 fixture.detectChanges(); 144 145 assertDefined( 146 htmlElement.querySelector<HTMLButtonElement>('.retry'), 147 ).click(); 148 fixture.detectChanges(); 149 expect(spy).toHaveBeenCalledWith('12345'); 150 }); 151 152 it('emits event on enter key', () => { 153 const spy = spyOn(assertDefined(component.retryConnection), 'emit'); 154 component.state = ConnectionState.UNAUTH; 155 fixture.detectChanges(); 156 157 const proxyTokenInputField = assertDefined( 158 htmlElement.querySelector('.proxy-token-input-field'), 159 ); 160 const proxyTokenInput = assertDefined( 161 proxyTokenInputField.querySelector<HTMLInputElement>('input'), 162 ); 163 164 proxyTokenInput.value = '12345'; 165 proxyTokenInput.dispatchEvent(new Event('input')); 166 proxyTokenInputField.dispatchEvent( 167 new KeyboardEvent('keydown', {key: 'Enter'}), 168 ); 169 fixture.detectChanges(); 170 expect(spy).toHaveBeenCalledWith('12345'); 171 }); 172}); 173