• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {NO_ERRORS_SCHEMA} from '@angular/core';
17import {ComponentFixture, TestBed} from '@angular/core/testing';
18import {MatButtonModule} from '@angular/material/button';
19import {MatCardModule} from '@angular/material/card';
20import {MatDividerModule} from '@angular/material/divider';
21import {MatIconModule} from '@angular/material/icon';
22import {MatListModule} from '@angular/material/list';
23import {MatProgressBarModule} from '@angular/material/progress-bar';
24import {MatSnackBar, MatSnackBarModule} from '@angular/material/snack-bar';
25import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
26import {AdbProxyComponent} from './adb_proxy_component';
27import {CollectTracesComponent} from './collect_traces_component';
28import {TraceConfigComponent} from './trace_config_component';
29import {WebAdbComponent} from './web_adb_component';
30
31describe('CollectTracesComponent', () => {
32  let fixture: ComponentFixture<CollectTracesComponent>;
33  let component: CollectTracesComponent;
34  let htmlElement: HTMLElement;
35
36  beforeEach(async () => {
37    await TestBed.configureTestingModule({
38      imports: [
39        MatIconModule,
40        MatCardModule,
41        MatListModule,
42        MatButtonModule,
43        MatDividerModule,
44        MatProgressBarModule,
45        BrowserAnimationsModule,
46        MatSnackBarModule,
47      ],
48      providers: [MatSnackBar],
49      declarations: [
50        CollectTracesComponent,
51        AdbProxyComponent,
52        WebAdbComponent,
53        TraceConfigComponent,
54      ],
55      schemas: [NO_ERRORS_SCHEMA],
56    }).compileComponents();
57    fixture = TestBed.createComponent(CollectTracesComponent);
58    component = fixture.componentInstance;
59    htmlElement = fixture.nativeElement;
60    component.isAdbProxy = true;
61  });
62
63  it('can be created', () => {
64    expect(component).toBeTruthy();
65  });
66
67  it('renders the expected card title', () => {
68    fixture.detectChanges();
69    expect(htmlElement.querySelector('.title')?.innerHTML).toContain('Collect Traces');
70  });
71
72  it('displays connecting message', () => {
73    component.connect.isConnectingState = jasmine.createSpy().and.returnValue(true);
74    fixture.detectChanges();
75    expect(htmlElement.querySelector('.connecting-message')?.innerHTML).toContain('Connecting...');
76  });
77
78  it('displays adb set up', async () => {
79    component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false);
80    fixture.detectChanges();
81    fixture.whenStable().then(() => {
82      expect(htmlElement.querySelector('.set-up-adb')).toBeTruthy();
83      const proxyTab: HTMLButtonElement | null = htmlElement.querySelector('.proxy-tab');
84      expect(proxyTab).toBeInstanceOf(HTMLButtonElement);
85      const webTab: HTMLButtonElement | null = htmlElement.querySelector('.web-tab');
86      expect(webTab).toBeInstanceOf(HTMLButtonElement);
87    });
88  });
89
90  it('displays adb proxy element', async () => {
91    component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false);
92    component.isAdbProxy = true;
93    fixture.detectChanges();
94    fixture.whenStable().then(() => {
95      expect(htmlElement.querySelector('adb-proxy')).toBeTruthy();
96      expect(htmlElement.querySelector('web-adb')).toBeFalsy();
97    });
98  });
99
100  it('displays web adb element', async () => {
101    component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false);
102    component.isAdbProxy = false;
103    fixture.detectChanges();
104    fixture.whenStable().then(() => {
105      expect(htmlElement.querySelector('adb-proxy')).toBeFalsy();
106      expect(htmlElement.querySelector('web-adb')).toBeTruthy();
107    });
108  });
109
110  it('changes to adb workflow tab', async () => {
111    component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false);
112    component.isAdbProxy = true;
113    fixture.detectChanges();
114    fixture.whenStable().then(() => {
115      const webTab: HTMLButtonElement | null = htmlElement.querySelector('.web-tab');
116      expect(webTab).toBeInstanceOf(HTMLButtonElement);
117      webTab?.dispatchEvent(new Event('click'));
118      fixture.whenStable().then(() => {
119        expect(component.displayWebAdbTab).toHaveBeenCalled();
120      });
121    });
122  });
123
124  it('displays no connected devices', async () => {
125    component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true);
126    component.connect.devices = jasmine.createSpy().and.returnValue({});
127    fixture.detectChanges();
128    fixture.whenStable().then(() => {
129      const el = htmlElement.querySelector('.devices-connecting');
130      expect(el).toBeTruthy();
131      expect(el?.innerHTML).toContain('No devices detected');
132    });
133  });
134
135  it('displays connected authorised devices', async () => {
136    component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true);
137    component.connect.devices = jasmine
138      .createSpy()
139      .and.returnValue({'35562': {model: 'Pixel 6', authorised: true}});
140    fixture.detectChanges();
141    fixture.whenStable().then(() => {
142      const el = htmlElement.querySelector('.devices-connecting');
143      expect(el).toBeTruthy();
144      expect(el?.innerHTML).toContain('Connected devices:');
145      expect(el?.innerHTML).toContain('Pixel 6');
146      expect(el?.innerHTML).toContain('smartphone');
147    });
148  });
149
150  it('displays connected unauthorised devices', async () => {
151    component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true);
152    component.connect.devices = jasmine
153      .createSpy()
154      .and.returnValue({'35562': {model: 'Pixel 6', authorised: false}});
155    fixture.detectChanges();
156    fixture.whenStable().then(() => {
157      const el = htmlElement.querySelector('.devices-connecting');
158      expect(el).toBeTruthy();
159      expect(el?.innerHTML).toContain('Connected devices:');
160      expect(el?.innerHTML).toContain('unauthorised');
161      expect(el?.innerHTML).toContain('screen_lock_portrait');
162    });
163  });
164
165  it('displays trace collection config elements', async () => {
166    component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true);
167    const mock = {model: 'Pixel 6', authorised: true};
168    component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock});
169    component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock);
170    fixture.detectChanges();
171
172    fixture.whenStable().then(() => {
173      const el = htmlElement.querySelector('.trace-collection-config');
174      expect(el).toBeTruthy();
175      expect(el?.innerHTML).toContain('smartphone');
176      expect(el?.innerHTML).toContain('Pixel 6');
177      expect(el?.innerHTML).toContain('35562');
178
179      const traceSection = htmlElement.querySelector('.trace-section');
180      expect(traceSection).toBeTruthy();
181
182      const dumpSection = htmlElement.querySelector('.dump-section');
183      expect(dumpSection).toBeTruthy();
184    });
185  });
186
187  it('start trace button works as expected', async () => {
188    component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true);
189    const mock = {model: 'Pixel 6', authorised: true};
190    component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock});
191    component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock);
192    fixture.detectChanges();
193
194    fixture.whenStable().then(() => {
195      const start: HTMLButtonElement | null = htmlElement.querySelector('.start-btn');
196      expect(start).toBeInstanceOf(HTMLButtonElement);
197      start?.dispatchEvent(new Event('click'));
198      fixture.whenStable().then(() => {
199        expect(component.startTracing).toHaveBeenCalled();
200        expect(component.connect.startTrace).toHaveBeenCalled();
201      });
202    });
203  });
204
205  it('dump state button works as expected', async () => {
206    component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true);
207    const mock = {model: 'Pixel 6', authorised: true};
208    component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock});
209    component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock);
210    fixture.detectChanges();
211
212    fixture.whenStable().then(() => {
213      const dump: HTMLButtonElement | null = htmlElement.querySelector('.dump-btn');
214      expect(dump).toBeInstanceOf(HTMLButtonElement);
215      dump?.dispatchEvent(new Event('click'));
216      fixture.whenStable().then(() => {
217        expect(component.dumpState).toHaveBeenCalled();
218        expect(component.connect.dumpState).toHaveBeenCalled();
219      });
220    });
221  });
222
223  it('change device button works as expected', async () => {
224    component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true);
225    const mock = {model: 'Pixel 6', authorised: true};
226    component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock});
227    component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock);
228    fixture.detectChanges();
229
230    fixture.whenStable().then(() => {
231      const change: HTMLButtonElement | null = htmlElement.querySelector('.change-btn');
232      expect(change).toBeInstanceOf(HTMLButtonElement);
233      change?.dispatchEvent(new Event('click'));
234      fixture.whenStable().then(() => {
235        expect(component.connect.resetLastDevice).toHaveBeenCalled();
236      });
237    });
238  });
239
240  it('displays unknown error message', () => {
241    component.connect.isErrorState = jasmine.createSpy().and.returnValue(true);
242    component.connect.proxy!.errorText = 'bad things are happening';
243    fixture.detectChanges();
244    fixture.whenStable().then(() => {
245      const el = htmlElement.querySelector('.unknown-error');
246      expect(el?.innerHTML).toContain('Error:');
247      expect(el?.innerHTML).toContain('bad things are happening');
248      const retry: HTMLButtonElement | null = htmlElement.querySelector('.retry-btn');
249      expect(retry).toBeInstanceOf(HTMLButtonElement);
250      retry?.dispatchEvent(new Event('click'));
251      fixture.whenStable().then(() => {
252        expect(component.connect.restart).toHaveBeenCalled();
253      });
254    });
255  });
256
257  it('displays end tracing elements', () => {
258    component.connect.isEndTraceState = jasmine.createSpy().and.returnValue(true);
259    fixture.detectChanges();
260    fixture.whenStable().then(() => {
261      const el = htmlElement.querySelector('.end-tracing');
262      expect(el?.innerHTML).toContain('Tracing...');
263      expect(htmlElement.querySelector('mat-progress-bar')).toBeTruthy();
264
265      const end: HTMLButtonElement | null = htmlElement.querySelector('.end');
266      expect(end).toBeInstanceOf(HTMLButtonElement);
267      end?.dispatchEvent(new Event('click'));
268      fixture.whenStable().then(() => {
269        expect(component.endTrace).toHaveBeenCalled();
270        expect(component.connect.endTrace).toHaveBeenCalled();
271      });
272    });
273  });
274
275  it('displays loading data elements', () => {
276    component.connect.isLoadDataState = jasmine.createSpy().and.returnValue(true);
277    fixture.detectChanges();
278    fixture.whenStable().then(() => {
279      expect(htmlElement.querySelector('.load-data')?.innerHTML).toContain('Loading data...');
280      expect(htmlElement.querySelector('mat-progress-bar')).toBeTruthy();
281    });
282  });
283});
284