Skip to content

Commit 33bd81b

Browse files
Piotr PaulskiDevtools-frontend LUCI CQ
authored andcommitted
Refactor BounceTrackingMitigationsView's tests
Finish fixing UI Engineering Vision violations in the tests by separating view and presenter tests. Bug: 407749385 Change-Id: I0017a1adb303524b113d26ba375515048d1cba48 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7229143 Reviewed-by: Danil Somsikov <[email protected]> Auto-Submit: Piotr Paulski <[email protected]> Commit-Queue: Piotr Paulski <[email protected]>
1 parent 6af9930 commit 33bd81b

File tree

2 files changed

+98
-99
lines changed

2 files changed

+98
-99
lines changed

front_end/panels/application/components/BounceTrackingMitigationsView.test.ts

Lines changed: 97 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,154 +2,153 @@
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 {getValuesOfAllBodyRows} from '../../../testing/DataGridHelpers.js';
65
import {
76
assertScreenshot,
8-
dispatchClickEvent,
97
renderElementIntoDOM,
108
} from '../../../testing/DOMHelpers.js';
119
import {createTarget} from '../../../testing/EnvironmentHelpers.js';
1210
import {
1311
describeWithMockConnection,
1412
setMockConnectionResponseHandler,
1513
} from '../../../testing/MockConnection.js';
16-
import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
14+
import {createViewFunctionStub} from '../../../testing/ViewFunctionHelpers.js';
1715

1816
import * as ApplicationComponents from './components.js';
19-
20-
async function renderBounceTrackingMitigationsView():
21-
Promise<ApplicationComponents.BounceTrackingMitigationsView.BounceTrackingMitigationsView> {
22-
const element = document.createElement('div');
23-
element.style.display = 'block';
24-
element.style.width = '640px';
25-
element.style.height = '480px';
26-
const component = new ApplicationComponents.BounceTrackingMitigationsView.BounceTrackingMitigationsView(element);
27-
renderElementIntoDOM(component);
28-
29-
await component.updateComplete;
30-
// The data-grid's renderer is scheduled, so we need to wait until the coordinator
31-
// is done before we can test against it.
32-
await RenderCoordinator.done();
33-
34-
return component;
35-
}
36-
37-
function getInternalDataGridShadowRoot(
38-
component: ApplicationComponents.BounceTrackingMitigationsView.BounceTrackingMitigationsView): ShadowRoot {
39-
const dataGrid = component.element.shadowRoot!.querySelector('devtools-data-grid')!;
40-
assert.isNotNull(dataGrid.shadowRoot);
41-
return dataGrid.shadowRoot;
42-
}
17+
const {BounceTrackingMitigationsView, DEFAULT_VIEW, ScreenStatusType} =
18+
ApplicationComponents.BounceTrackingMitigationsView;
4319

4420
describeWithMockConnection('BounceTrackingMitigationsView', () => {
4521
it('shows no message or table if the force run button has not been clicked', async () => {
4622
createTarget();
4723
setMockConnectionResponseHandler('SystemInfo.getFeatureState', () => ({featureEnabled: true}));
4824
setMockConnectionResponseHandler('Storage.runBounceTrackingMitigations', () => ({deletedSites: []}));
4925

50-
const component = await renderBounceTrackingMitigationsView();
51-
await RenderCoordinator.done();
52-
await component.updateComplete;
53-
54-
const nullGridElement = component.element.shadowRoot!.querySelector('devtools-data-grid');
55-
assert.isNull(nullGridElement);
56-
57-
await assertScreenshot('application/bounce-tracking-mitigations-view-initial.png');
26+
const view = createViewFunctionStub(BounceTrackingMitigationsView);
27+
new BounceTrackingMitigationsView(undefined, view);
5828

59-
const sections = component.element.shadowRoot!.querySelectorAll('devtools-report-section');
60-
const sectionsText = Array.from(sections).map(section => section.textContent?.trim());
61-
const expected = [
62-
'Force run',
63-
'Learn more: Bounce Tracking Mitigations',
64-
];
29+
await view.nextInput;
6530

66-
assert.deepEqual(sectionsText, expected);
31+
assert.strictEqual(view.input.screenStatus, ScreenStatusType.RESULT);
32+
assert.isFalse(view.input.seenButtonClick);
33+
assert.lengthOf(view.input.trackingSites, 0);
6734
});
6835

6936
it('shows a message indicating that Bounce Tracking Mitigations are disabled', async () => {
7037
createTarget();
7138
setMockConnectionResponseHandler('SystemInfo.getFeatureState', () => ({featureEnabled: false}));
7239

73-
const component = await renderBounceTrackingMitigationsView();
74-
await RenderCoordinator.done();
75-
await component.updateComplete;
76-
77-
const nullGridElement = component.element.shadowRoot!.querySelector('devtools-data-grid');
78-
assert.isNull(nullGridElement);
79-
80-
await assertScreenshot('application/bounce-tracking-mitigations-view-disabled.png');
40+
const view = createViewFunctionStub(BounceTrackingMitigationsView);
41+
new BounceTrackingMitigationsView(undefined, view);
8142

82-
const sections = component.element.shadowRoot!.querySelectorAll('devtools-report-section');
83-
const sectionsText = Array.from(sections).map(section => section.textContent?.trim());
84-
const expected = [
85-
'Bounce tracking mitigations are disabled.',
86-
];
43+
await view.nextInput;
8744

88-
assert.deepEqual(sectionsText, expected);
45+
assert.strictEqual(view.input.screenStatus, ScreenStatusType.DISABLED);
46+
assert.isFalse(view.input.seenButtonClick);
47+
assert.lengthOf(view.input.trackingSites, 0);
8948
});
9049

91-
it('hides deleted sites table and shows explanation message when there are no deleted tracking sites', async () => {
50+
async function testForceRunClick(deletedSites: string[]) {
51+
const {promise: lock, resolve: freeLock} = Promise.withResolvers();
9252
createTarget();
9353
setMockConnectionResponseHandler('SystemInfo.getFeatureState', () => ({featureEnabled: true}));
9454
const runBounceTrackingMitigationsPromise = new Promise(resolve => {
95-
setMockConnectionResponseHandler('Storage.runBounceTrackingMitigations', () => {
55+
setMockConnectionResponseHandler('Storage.runBounceTrackingMitigations', async () => {
56+
await lock;
9657
resolve(undefined);
97-
return {deletedSites: []};
58+
return {deletedSites};
9859
});
9960
});
10061

101-
const component = await renderBounceTrackingMitigationsView();
102-
await RenderCoordinator.done();
103-
await component.updateComplete;
62+
const view = createViewFunctionStub(BounceTrackingMitigationsView);
63+
new BounceTrackingMitigationsView(undefined, view);
10464

105-
const forceRunButton = component.element.shadowRoot!.querySelector('[aria-label="Force run"]');
106-
assert.instanceOf(forceRunButton, HTMLElement);
107-
dispatchClickEvent(forceRunButton);
108-
await runBounceTrackingMitigationsPromise;
65+
await view.nextInput;
10966

110-
await RenderCoordinator.done();
111-
await component.updateComplete;
67+
assert.isFunction(view.input.runMitigations);
11268

113-
await assertScreenshot('application/bounce-tracking-mitigations-view-empty.png');
69+
const runMitigationsPromise = view.input.runMitigations();
70+
await view.nextInput;
71+
72+
assert.strictEqual(view.input.screenStatus, ScreenStatusType.RUNNING);
11473

115-
const nullGridElement = component.element.shadowRoot!.querySelector('devtools-data-grid');
116-
assert.isNull(nullGridElement);
74+
freeLock(undefined);
75+
await Promise.all([runMitigationsPromise, runBounceTrackingMitigationsPromise]);
76+
await view.nextInput;
11777

118-
const sections = component.element.shadowRoot!.querySelectorAll('devtools-report-section');
119-
const sectionsText = Array.from(sections).map(section => section.textContent?.trim());
120-
const expected = [
121-
'Force run',
122-
'State was not cleared for any potential bounce tracking sites. Either none were identified or third-party cookies are not blocked.',
123-
'Learn more: Bounce Tracking Mitigations',
124-
];
78+
assert.strictEqual(view.input.screenStatus, ScreenStatusType.RESULT);
79+
assert.isTrue(view.input.seenButtonClick);
80+
assert.deepEqual(view.input.trackingSites, deletedSites);
81+
}
12582

126-
assert.deepEqual(sectionsText, expected);
83+
it('hides deleted sites table and shows explanation message when there are no deleted tracking sites', async () => {
84+
await testForceRunClick([]);
12785
});
12886

12987
it('renders deleted sites in a table', async () => {
130-
createTarget();
131-
setMockConnectionResponseHandler('SystemInfo.getFeatureState', () => ({featureEnabled: true}));
132-
setMockConnectionResponseHandler(
133-
'Storage.runBounceTrackingMitigations', () => ({deletedSites: ['tracker-1.example', 'tracker-2.example']}));
88+
await testForceRunClick(['tracker-1.example', 'tracker-2.example']);
89+
});
13490

135-
const component = await renderBounceTrackingMitigationsView();
136-
await RenderCoordinator.done();
137-
await component.updateComplete;
91+
const createElement = () => {
92+
const element = document.createElement('div');
93+
element.style.display = 'block';
94+
element.style.width = '640px';
95+
element.style.height = '480px';
96+
renderElementIntoDOM(element);
97+
98+
return element;
99+
};
100+
101+
const INITIAL_INPUT = {
102+
screenStatus: ScreenStatusType.INITIALIZING,
103+
trackingSites: [],
104+
seenButtonClick: false,
105+
runMitigations: () => Promise.resolve(),
106+
};
107+
108+
it('renders initial state', async () => {
109+
DEFAULT_VIEW(
110+
{
111+
...INITIAL_INPUT,
112+
screenStatus: ScreenStatusType.RESULT,
113+
},
114+
undefined, createElement());
138115

139-
const forceRunButton = component.element.shadowRoot!.querySelector('[aria-label="Force run"]');
140-
assert.instanceOf(forceRunButton, HTMLElement);
141-
dispatchClickEvent(forceRunButton);
116+
await assertScreenshot('application/bounce-tracking-mitigations-view-initial.png');
117+
});
142118

143-
await RenderCoordinator.done({waitForWork: true});
144-
await component.updateComplete;
119+
it('renders disabled state', async () => {
120+
DEFAULT_VIEW(
121+
{
122+
...INITIAL_INPUT,
123+
screenStatus: ScreenStatusType.DISABLED,
124+
},
125+
undefined, createElement());
145126

146-
await assertScreenshot('application/bounce-tracking-mitigations-view-populated.png');
127+
await assertScreenshot('application/bounce-tracking-mitigations-view-disabled.png');
128+
});
147129

148-
const dataGridShadowRoot = getInternalDataGridShadowRoot(component);
149-
const rowValues = getValuesOfAllBodyRows(dataGridShadowRoot);
150-
assert.deepEqual(rowValues, [
151-
['tracker-1.example'],
152-
['tracker-2.example'],
153-
]);
130+
it('renders empty state', async () => {
131+
DEFAULT_VIEW(
132+
{
133+
...INITIAL_INPUT,
134+
screenStatus: ScreenStatusType.RESULT,
135+
seenButtonClick: true,
136+
},
137+
undefined, createElement());
138+
139+
await assertScreenshot('application/bounce-tracking-mitigations-view-empty.png');
140+
});
141+
142+
it('renders populated state', async () => {
143+
DEFAULT_VIEW(
144+
{
145+
...INITIAL_INPUT,
146+
screenStatus: ScreenStatusType.RESULT,
147+
trackingSites: ['tracker-1.example', 'tracker-2.example'],
148+
seenButtonClick: true,
149+
},
150+
undefined, createElement());
151+
152+
await assertScreenshot('application/bounce-tracking-mitigations-view-populated.png');
154153
});
155154
});

front_end/panels/application/components/BounceTrackingMitigationsView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const UIStrings = {
5757
const str_ = i18n.i18n.registerUIStrings('panels/application/components/BounceTrackingMitigationsView.ts', UIStrings);
5858
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
5959

60-
const enum ScreenStatusType {
60+
export const enum ScreenStatusType {
6161
INITIALIZING = 'Initializing',
6262
RUNNING = 'Running',
6363
RESULT = 'Result',

0 commit comments

Comments
 (0)