Skip to content

Commit a71d89f

Browse files
authored
Merge branch 'main' into dbajpeyi/fix/animate-export-once
2 parents 702544f + a418217 commit a71d89f

File tree

214 files changed

+10421
-1221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

214 files changed

+10421
-1221
lines changed

injected/integration-test/broker-protection.spec.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,46 @@ test.describe('Broker Protection communications', () => {
469469
await page.waitForURL((url) => url.hash === '#no', { timeout: 2000 });
470470
});
471471

472+
test('clicking selectors that do not exists should fail', async ({ page }, workerInfo) => {
473+
const dbp = BrokerProtectionPage.create(page, workerInfo.project.use);
474+
await dbp.enabled();
475+
await dbp.navigatesTo('clicks.html');
476+
await dbp.receivesAction('click-nonexistent-selector.json');
477+
const response = await dbp.collector.waitForMessage('actionCompleted');
478+
479+
dbp.isErrorMessage(response);
480+
});
481+
482+
test('clicking buttons that are disabled should fail', async ({ page }, workerInfo) => {
483+
const dbp = BrokerProtectionPage.create(page, workerInfo.project.use);
484+
await dbp.enabled();
485+
await dbp.navigatesTo('clicks.html');
486+
await dbp.receivesAction('click-disabled-button.json');
487+
const response = await dbp.collector.waitForMessage('actionCompleted');
488+
489+
dbp.isErrorMessage(response);
490+
});
491+
492+
test('clicking selectors that do not exist when failSilently is enabled should not fail', async ({ page }, workerInfo) => {
493+
const dbp = BrokerProtectionPage.create(page, workerInfo.project.use);
494+
await dbp.enabled();
495+
await dbp.navigatesTo('clicks.html');
496+
await dbp.receivesAction('click-nonexistent-selector-failSilently.json');
497+
const response = await dbp.collector.waitForMessage('actionCompleted');
498+
499+
dbp.isSuccessMessage(response);
500+
});
501+
502+
test('clicking buttons that are disabled when failSilently is enabled should not fail', async ({ page }, workerInfo) => {
503+
const dbp = BrokerProtectionPage.create(page, workerInfo.project.use);
504+
await dbp.enabled();
505+
await dbp.navigatesTo('clicks.html');
506+
await dbp.receivesAction('click-disabled-button-failSilently.json');
507+
const response = await dbp.collector.waitForMessage('actionCompleted');
508+
509+
dbp.isSuccessMessage(response);
510+
});
511+
472512
test('getCaptchaInfo', async ({ page }, workerInfo) => {
473513
const dbp = BrokerProtectionPage.create(page, workerInfo.project.use);
474514
await dbp.enabled();
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { test, expect } from '@playwright/test';
2+
import { ResultsCollector } from './page-objects/results-collector.js';
3+
import { readOutgoingMessages } from '@duckduckgo/messaging/lib/test-utils.mjs';
4+
5+
const ENABLED_CONFIG = 'integration-test/test-pages/message-bridge/config/message-bridge-enabled.json';
6+
const DISABLED_CONFIG = 'integration-test/test-pages/message-bridge/config/message-bridge-disabled.json';
7+
const ENABLED_HTML = '/message-bridge/pages/enabled.html';
8+
const DISABLED_HTML = '/message-bridge/pages/disabled.html';
9+
10+
test('message bridge when enabled (android)', async ({ page }, testInfo) => {
11+
const pageWorld = ResultsCollector.create(page, testInfo.project.use);
12+
13+
// seed the request->re
14+
pageWorld.withMockResponse({
15+
sampleData: /** @type {any} */ ({
16+
ghi: 'jkl',
17+
}),
18+
});
19+
20+
pageWorld.withUserPreferences({
21+
messageSecret: 'ABC',
22+
javascriptInterface: 'javascriptInterface',
23+
messageCallback: 'messageCallback',
24+
});
25+
26+
// now load the page
27+
await pageWorld.load(ENABLED_HTML, ENABLED_CONFIG);
28+
29+
// simulate a push event
30+
await pageWorld.simulateSubscriptionMessage('exampleFeature', 'onUpdate', { abc: 'def' });
31+
32+
// get all results
33+
const results = await pageWorld.results();
34+
expect(results['Creating the bridge']).toStrictEqual([
35+
{ name: 'bridge.notify', result: 'function', expected: 'function' },
36+
{ name: 'bridge.request', result: 'function', expected: 'function' },
37+
{ name: 'bridge.subscribe', result: 'function', expected: 'function' },
38+
{ name: 'data', result: [{ abc: 'def' }, { ghi: 'jkl' }], expected: [{ abc: 'def' }, { ghi: 'jkl' }] },
39+
]);
40+
41+
// verify messaging calls
42+
const calls = await page.evaluate(readOutgoingMessages);
43+
expect(calls.length).toBe(2);
44+
const pixel = calls[0].payload;
45+
const request = calls[1].payload;
46+
47+
expect(pixel).toStrictEqual({
48+
context: 'contentScopeScripts',
49+
featureName: 'exampleFeature',
50+
method: 'pixel',
51+
params: {},
52+
});
53+
54+
const { id, ...rest } = /** @type {import("@duckduckgo/messaging").RequestMessage} */ (request);
55+
56+
expect(rest).toStrictEqual({
57+
context: 'contentScopeScripts',
58+
featureName: 'exampleFeature',
59+
method: 'sampleData',
60+
params: {},
61+
});
62+
63+
if (!('id' in request)) throw new Error('unreachable');
64+
65+
expect(typeof request.id).toBe('string');
66+
expect(request.id.length).toBeGreaterThan(10);
67+
});
68+
69+
test('message bridge when disabled (android)', async ({ page }, testInfo) => {
70+
const pageWorld = ResultsCollector.create(page, testInfo.project.use);
71+
72+
// now load the main page
73+
await pageWorld.load(DISABLED_HTML, DISABLED_CONFIG);
74+
75+
// verify no outgoing calls were made
76+
const calls = await page.evaluate(readOutgoingMessages);
77+
expect(calls).toHaveLength(0);
78+
79+
// get all results
80+
const results = await pageWorld.results();
81+
expect(results['Creating the bridge, but it is unavailable']).toStrictEqual([
82+
{ name: 'error', result: 'Did not install Message Bridge', expected: 'Did not install Message Bridge' },
83+
]);
84+
});

injected/integration-test/page-objects/duckplayer-overlays.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ export class DuckplayerOverlays {
8080
},
8181
sendDuckPlayerPixel: {},
8282
});
83+
this.collector.withUserPreferences({
84+
messageSecret: 'ABC',
85+
javascriptInterface: 'javascriptInterface',
86+
messageCallback: 'messageCallback',
87+
});
8388
page.on('console', (msg) => {
8489
console.log(msg.type(), msg.text());
8590
});

injected/integration-test/page-objects/results-collector.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export class ResultsCollector {
172172
messagingContext: this.messagingContext('n/a'),
173173
responses: this.#mockResponses,
174174
messageCallback: 'messageCallback',
175+
javascriptInterface: this.#userPreferences.javascriptInterface,
175176
});
176177

177178
const wrapFn = this.build.switch({
@@ -234,6 +235,8 @@ export class ResultsCollector {
234235
name,
235236
payload,
236237
injectName: this.build.name,
238+
messageCallback: this.#userPreferences.messageCallback,
239+
messageSecret: this.#userPreferences.messageSecret,
237240
});
238241
}
239242

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"state": {
3+
"action": {
4+
"actionType": "click",
5+
"id": "1",
6+
"elements": [
7+
{
8+
"type": "button",
9+
"selector": ".btn",
10+
"failSilently": true
11+
}
12+
]
13+
}
14+
}
15+
}
16+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"state": {
3+
"action": {
4+
"actionType": "click",
5+
"id": "1",
6+
"elements": [
7+
{
8+
"type": "button",
9+
"selector": ".btn"
10+
}
11+
]
12+
}
13+
}
14+
}
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"state": {
3+
"action": {
4+
"actionType": "click",
5+
"id": "1",
6+
"elements": [
7+
{
8+
"type": "button",
9+
"selector": ".test",
10+
"failSilently": true
11+
}
12+
]
13+
}
14+
}
15+
}
16+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"state": {
3+
"action": {
4+
"actionType": "click",
5+
"id": "1",
6+
"elements": [
7+
{
8+
"type": "button",
9+
"selector": ".test"
10+
}
11+
]
12+
}
13+
}
14+
}
15+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width">
6+
<title>Broker Protection</title>
7+
</head>
8+
<body>
9+
<div class="result">
10+
<div class="name">John Doe</div>
11+
<div class="age">32</div>
12+
<div class="locations" data-id="1">
13+
<span>New York, NY</span>
14+
<span>Los Angeles, CA</span>
15+
<a href="#" class="view-more">View More</a>
16+
</div>
17+
<button disabled class="btn">View More</button>
18+
</div>
19+
</body>
20+
</html>

injected/integration-test/type-helpers.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export class Build {
6262
apple: () => '../Sources/ContentScopeScripts/dist/contentScope.js',
6363
'apple-isolated': () => '../Sources/ContentScopeScripts/dist/contentScopeIsolated.js',
6464
'android-autofill-password-import': () => '../build/android/autofillPasswordImport.js',
65+
'android-broker-protection': () => '../build/android/brokerProtection.js',
6566
});
6667
return readFileSync(path, 'utf8');
6768
}

0 commit comments

Comments
 (0)