Skip to content

Commit 5e5b9a6

Browse files
danilsomsikovDevtools-frontend LUCI CQ
authored andcommitted
Use the view function in the unit tests
Bug: 407749531 Change-Id: Ib0cf3f79aafe0447d5cd034d8036f7850248d147 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7228243 Commit-Queue: Simon Zünd <[email protected]> Auto-Submit: Danil Somsikov <[email protected]> Reviewed-by: Simon Zünd <[email protected]>
1 parent 2bb1872 commit 5e5b9a6

File tree

3 files changed

+72
-84
lines changed

3 files changed

+72
-84
lines changed

front_end/panels/application/AppManifestView.test.ts

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import * as Common from '../../core/common/common.js';
65
import * as Platform from '../../core/platform/platform.js';
76
import * as SDK from '../../core/sdk/sdk.js';
87
import type * as Protocol from '../../generated/protocol.js';
98
import {getCleanTextContentFromElements, renderElementIntoDOM} from '../../testing/DOMHelpers.js';
109
import {createTarget, stubNoopSettings} from '../../testing/EnvironmentHelpers.js';
1110
import {describeWithMockConnection} from '../../testing/MockConnection.js';
11+
import {createViewFunctionStub, type ViewFunctionStub} from '../../testing/ViewFunctionHelpers.js';
1212
import * as UI from '../../ui/legacy/legacy.js';
1313

1414
import * as Application from './application.js';
@@ -21,18 +21,15 @@ describeWithMockConnection('AppManifestView', () => {
2121
const FIXTURES_640X320_URL = `${new URL('./fixtures/640x320.png', import.meta.url)}`;
2222

2323
let target: SDK.Target.Target;
24-
let emptyView: UI.EmptyWidget.EmptyWidget;
25-
let reportView: UI.ReportView.ReportView;
26-
let throttler: Common.Throttler.Throttler;
2724
let view: Application.AppManifestView.AppManifestView;
25+
let viewFunction: ViewFunctionStub<typeof Application.AppManifestView.AppManifestView>;
26+
2827
beforeEach(() => {
2928
stubNoopSettings();
3029
const tabTarget = createTarget({type: SDK.Target.Type.TAB});
3130
createTarget({parentTarget: tabTarget, subtype: 'prerender'});
3231
target = createTarget({parentTarget: tabTarget});
33-
emptyView = new UI.EmptyWidget.EmptyWidget('', '');
34-
reportView = new UI.ReportView.ReportView('');
35-
throttler = new Common.Throttler.Throttler(0);
32+
viewFunction = createViewFunctionStub(Application.AppManifestView.AppManifestView);
3633
});
3734

3835
afterEach(() => {
@@ -51,28 +48,22 @@ describeWithMockConnection('AppManifestView', () => {
5148
sinon.stub(resourceTreeModel, 'getInstallabilityErrors').resolves([]);
5249
sinon.stub(resourceTreeModel, 'getAppId').resolves({} as Protocol.Page.GetAppIdResponse);
5350

54-
view = new Application.AppManifestView.AppManifestView(emptyView, reportView, throttler);
51+
view = new Application.AppManifestView.AppManifestView(viewFunction);
5552
renderElementIntoDOM(view);
5653

57-
await new Promise(resolve => {
58-
view.addEventListener(Application.AppManifestView.Events.MANIFEST_DETECTED, resolve, {once: true});
59-
});
60-
assert.isTrue(emptyView.isShowing());
61-
assert.isFalse(reportView.isShowing());
54+
await viewFunction.nextInput;
55+
assert.isTrue(viewFunction.input.emptyView.isShowing());
56+
assert.isFalse(viewFunction.input.reportView.isShowing());
6257

6358
resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.DOMContentLoaded, 42);
64-
await new Promise(resolve => {
65-
view.addEventListener(Application.AppManifestView.Events.MANIFEST_DETECTED, resolve, {once: true});
66-
});
67-
assert.isTrue(emptyView.isShowing());
68-
assert.isFalse(reportView.isShowing());
59+
await viewFunction.nextInput;
60+
assert.isTrue(viewFunction.input.emptyView.isShowing());
61+
assert.isFalse(viewFunction.input.reportView.isShowing());
6962

7063
resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.DOMContentLoaded, 42);
71-
await new Promise(resolve => {
72-
view.addEventListener(Application.AppManifestView.Events.MANIFEST_DETECTED, resolve, {once: true});
73-
});
74-
assert.isFalse(emptyView.isShowing());
75-
assert.isTrue(reportView.isShowing());
64+
await viewFunction.nextInput;
65+
assert.isFalse(viewFunction.input.emptyView.isShowing());
66+
assert.isTrue(viewFunction.input.reportView.isShowing());
7667
});
7768

7869
it('shows pwa wco if available', async () => {
@@ -86,21 +77,17 @@ describeWithMockConnection('AppManifestView', () => {
8677
sinon.stub(resourceTreeModel, 'getInstallabilityErrors').resolves([]);
8778
sinon.stub(resourceTreeModel, 'getAppId').resolves({} as Protocol.Page.GetAppIdResponse);
8879

89-
view = new Application.AppManifestView.AppManifestView(emptyView, reportView, throttler);
80+
view = new Application.AppManifestView.AppManifestView(viewFunction);
9081
renderElementIntoDOM(view);
9182

9283
resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.DOMContentLoaded, 42);
93-
await new Promise(resolve => {
94-
view.addEventListener(Application.AppManifestView.Events.MANIFEST_RENDERED, resolve, {once: true});
95-
});
84+
const {windowControlsData} = await viewFunction.nextInput;
9685

97-
const manifestSections = view.getStaticSections();
98-
const values = getCleanTextContentFromElements(manifestSections[4].getFieldElement(), '.wco');
99-
assert.deepEqual(values, ['window-controls-overlay']);
86+
assert.isTrue(windowControlsData?.hasWco);
10087
});
10188

10289
it('can parse ‘sizes’-field', async () => {
103-
view = new Application.AppManifestView.AppManifestView(emptyView, reportView, throttler);
90+
view = new Application.AppManifestView.AppManifestView(viewFunction);
10491
const parsed =
10592
view.parseSizes('512x512', 'Icon' as Platform.UIString.LocalizedString, 'https://web.dev/image.html', []);
10693
const expected = [{
@@ -112,7 +99,7 @@ describeWithMockConnection('AppManifestView', () => {
11299
});
113100

114101
it('can handle missing ‘sizes’-field', async () => {
115-
view = new Application.AppManifestView.AppManifestView(emptyView, reportView, throttler);
102+
view = new Application.AppManifestView.AppManifestView(viewFunction);
116103
const parsed = view.parseSizes(
117104
undefined as unknown as string, 'Icon' as Platform.UIString.LocalizedString, 'https://web.dev/image.html', []);
118105
assert.deepEqual(parsed, []);
@@ -141,18 +128,12 @@ describeWithMockConnection('AppManifestView', () => {
141128
}
142129
});
143130

144-
view = new Application.AppManifestView.AppManifestView(emptyView, reportView, throttler);
131+
view = new Application.AppManifestView.AppManifestView(viewFunction);
145132
renderElementIntoDOM(view);
146133

147-
await new Promise(resolve => {
148-
view.addEventListener(Application.AppManifestView.Events.MANIFEST_RENDERED, resolve, {once: true});
149-
});
134+
const {warnings, errors, imageErrors} = await viewFunction.nextInput;
150135

151-
const warningSection = reportView.element.shadowRoot?.querySelector('.report-section');
152-
assert.exists(warningSection);
153-
const warnings = warningSection.querySelectorAll<HTMLDivElement>('.report-row');
154-
assert.exists(warnings);
155-
return Array.from(warnings).map(warning => warning.textContent || '');
136+
return [...warnings ?? [], ...errors?.map(error => error.message) ?? [], ...imageErrors ?? []];
156137
}
157138

158139
it('displays warnings for too many shortcuts and not enough screenshots', async () => {
@@ -307,21 +288,38 @@ describeWithMockConnection('AppManifestView', () => {
307288
});
308289

309290
it('displays "form-factor", "platform" and "label" properties for screenshots', async () => {
310-
await renderWithWarnings(`{
311-
"screenshots": [
312-
{
313-
"src": "${FIXTURES_320X320_URL}",
314-
"type": "image/png",
315-
"sizes": "320x320",
316-
"form_factor": "wide",
317-
"label": "Dummy Screenshot",
318-
"platform": "windows"
291+
const emptyView = new UI.EmptyWidget.EmptyWidget('', '');
292+
const reportView = new UI.ReportView.ReportView('');
293+
const viewInput = {
294+
reportView,
295+
emptyView,
296+
screenshotsSections: [],
297+
screenshotsData: {
298+
screenshots: [{
299+
screenshot: {
300+
src: FIXTURES_320X320_URL,
301+
type: 'image/png',
302+
sizes: '320x320',
303+
form_factor: 'wide',
304+
label: 'Dummy Screenshot',
305+
platform: 'windows'
306+
},
307+
processedImage: {
308+
imageResourceErrors: [],
309+
squareSizedIconAvailable: true,
310+
naturalWidth: 320,
311+
naturalHeight: 320,
312+
title: '320×320px\nimage/png',
313+
imageSrc: '',
314+
imageUrl: FIXTURES_320X320_URL,
319315
}
320-
]
321-
}`);
322-
323-
const screenshotSection =
324-
reportView.element.shadowRoot?.querySelectorAll<HTMLDivElement>('.report-section')[7] || null;
316+
}],
317+
imageResourceErrors: [],
318+
warnings: [],
319+
}
320+
};
321+
Application.AppManifestView.DEFAULT_VIEW(viewInput, undefined, viewInput.reportView.element);
322+
const screenshotSection = reportView.element.shadowRoot?.querySelector<HTMLDivElement>('.report-section') || null;
325323
assert.instanceOf(screenshotSection, HTMLDivElement);
326324
assert.deepEqual(
327325
getCleanTextContentFromElements(screenshotSection, '.report-field-name').slice(0, 3),

front_end/panels/application/AppManifestView.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ import appManifestViewStyles from './appManifestView.css.js';
2222
import * as ApplicationComponents from './components/components.js';
2323

2424
const UIStrings = {
25+
/**
26+
* @description Text in App Manifest View of the Application panel
27+
*/
28+
noManifestDetected: 'No manifest detected',
29+
/**
30+
* @description Description text on manifests in App Manifest View of the Application panel which describes the app manifest view tab
31+
*/
32+
manifestDescription:
33+
'A manifest defines how your app appears on phone’s home screens and what the app looks like on launch.',
34+
/**
35+
* @description Text in App Manifest View of the Application panel
36+
*/
37+
appManifest: 'Manifest',
2538
/**
2639
* @description Text in App Manifest View of the Application panel
2740
*/
@@ -1047,7 +1060,7 @@ interface ViewInput {
10471060

10481061
type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
10491062

1050-
const DEFAULT_VIEW: View = (input, _output, _target) => {
1063+
export const DEFAULT_VIEW: View = (input, _output, _target) => {
10511064
const {
10521065
reportView,
10531066
errorsSection,
@@ -1117,7 +1130,6 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
11171130
private readonly protocolHandlersSection: UI.ReportView.Section;
11181131
private readonly shortcutSections: UI.ReportView.Section[];
11191132
private readonly screenshotsSections: UI.ReportView.Section[];
1120-
private readonly throttler: Common.Throttler.Throttler;
11211133
private registeredListeners: Common.EventTarget.EventDescriptor[];
11221134
private target?: SDK.Target.Target;
11231135
private resourceTreeModel?: SDK.ResourceTreeModel.ResourceTreeModel|null;
@@ -1132,9 +1144,7 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
11321144
private wcoToolbarEnabled = false;
11331145
private readonly view: View;
11341146

1135-
constructor(
1136-
emptyView: UI.EmptyWidget.EmptyWidget, reportView: UI.ReportView.ReportView,
1137-
throttler: Common.Throttler.Throttler, view: View = DEFAULT_VIEW) {
1147+
constructor(view: View = DEFAULT_VIEW) {
11381148
super({
11391149
jslog: `${VisualLogging.pane('manifest')}`,
11401150
useShadowDom: true,
@@ -1144,13 +1154,14 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
11441154

11451155
this.contentElement.classList.add('manifest-container');
11461156

1147-
this.emptyView = emptyView;
1157+
this.emptyView = new UI.EmptyWidget.EmptyWidget(
1158+
i18nString(UIStrings.noManifestDetected), i18nString(UIStrings.manifestDescription));
11481159
this.emptyView.link = 'https://web.dev/add-manifest/' as Platform.DevToolsPath.UrlString;
11491160

11501161
this.emptyView.show(this.contentElement);
11511162
this.emptyView.hideWidget();
11521163

1153-
this.reportView = reportView;
1164+
this.reportView = new UI.ReportView.ReportView(i18nString(UIStrings.appManifest));
11541165
this.reportView.registerRequiredCSS(appManifestViewStyles);
11551166
this.reportView.element.classList.add('manifest-view-header');
11561167
this.reportView.show(this.contentElement);
@@ -1173,7 +1184,6 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
11731184
this.shortcutSections = [];
11741185
this.screenshotsSections = [];
11751186

1176-
this.throttler = throttler;
11771187
SDK.TargetManager.TargetManager.instance().observeTargets(this);
11781188
this.registeredListeners = [];
11791189

@@ -1357,8 +1367,6 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
13571367
onToggleWcoToolbar,
13581368
},
13591369
undefined, this.contentElement);
1360-
1361-
this.dispatchEventToListeners(Events.MANIFEST_RENDERED);
13621370
}
13631371

13641372
private stringProperty(parsedManifest: Manifest, name: keyof Manifest): string {
@@ -1765,10 +1773,8 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
17651773

17661774
export const enum Events {
17671775
MANIFEST_DETECTED = 'ManifestDetected',
1768-
MANIFEST_RENDERED = 'ManifestRendered',
17691776
}
17701777

17711778
export interface EventTypes {
17721779
[Events.MANIFEST_DETECTED]: boolean;
1773-
[Events.MANIFEST_RENDERED]: void;
17741780
}

front_end/panels/application/ApplicationPanelSidebar.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,6 @@ const UIStrings = {
176176
* @description Text that appears on a button for the manifest resource type filter.
177177
*/
178178
manifest: 'Manifest',
179-
/**
180-
* @description Text in App Manifest View of the Application panel
181-
*/
182-
noManifestDetected: 'No manifest detected',
183-
/**
184-
* @description Description text on manifests in App Manifest View of the Application panel which describes the app manifest view tab
185-
*/
186-
manifestDescription:
187-
'A manifest defines how your app appears on phone’s home screens and what the app looks like on launch.',
188-
/**
189-
* @description Text in App Manifest View of the Application panel
190-
*/
191-
appManifest: 'Manifest',
192179
/**
193180
* @description Text in Application Panel Sidebar of the Application panel
194181
*/
@@ -1156,10 +1143,7 @@ export class AppManifestTreeElement extends ApplicationPanelTreeElement {
11561143
const icon = createIcon('document');
11571144
this.setLeadingIcons([icon]);
11581145
self.onInvokeElement(this.listItemElement, this.onInvoke.bind(this));
1159-
const emptyView = new UI.EmptyWidget.EmptyWidget(
1160-
i18nString(UIStrings.noManifestDetected), i18nString(UIStrings.manifestDescription));
1161-
const reportView = new UI.ReportView.ReportView(i18nString(UIStrings.appManifest));
1162-
this.view = new AppManifestView(emptyView, reportView, new Common.Throttler.Throttler(1000));
1146+
this.view = new AppManifestView();
11631147
UI.ARIAUtils.setLabel(this.listItemElement, i18nString(UIStrings.onInvokeManifestAlert));
11641148
const handleExpansion = (hasManifest: boolean): void => {
11651149
this.setExpandable(hasManifest);

0 commit comments

Comments
 (0)