Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions integration-test/atb.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@ import { test, expect, mockAtb } from './helpers/playwrightHarness';
import backgroundWait, { forSetting } from './helpers/backgroundWait';

test.describe('install workflow', () => {
test('postinstall page: should open the postinstall page correctly', async ({ context, page }) => {
test('postinstall page: should open the postinstall page correctly', async ({ context, page, manifestVersion }) => {
// wait for post install page to open
// we leverage the extension loaded helper, which returns the extension success URL when it is opened
const postInstallOpened = await backgroundWait.forExtensionLoaded(context);
const postInstallURL = new URL(postInstallOpened);
expect(postInstallOpened).toBeTruthy();
expect(postInstallURL.pathname).toBe('/extension-success');
expect(postInstallURL.searchParams.has('atb')).toBe(true);
// This ATB comes from the success page.
expect(postInstallURL.searchParams.get('atb')).not.toEqual(mockAtb.version);

// For MV3, the route handler is set up immediately after context
// creation, so the /atb.js request is mocked and returns the mock ATB.
// For MV2, the route handler is set up later on the background page, so
// the /atb.js request goes to the real network before the mock is ready.
const actualAtb = postInstallURL.searchParams.get('atb');
if (manifestVersion === 3) {
expect(actualAtb).toEqual(mockAtb.version);
} else {
expect(actualAtb).not.toEqual(mockAtb.version);
}
});

test.describe('atb values', () => {
Expand Down
77 changes: 40 additions & 37 deletions integration-test/helpers/playwrightHarness.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@ export const mockAtb = {
version: 'v364-2',
};

const defaultRouteHandler = (route) => {
const url = route.request().url();
if (url.startsWith('https://staticcdn.duckduckgo.com/')) {
return routeLocalResources(route);
}
if (url.startsWith('https://duckduckgo.com/atb.js')) {
// mock ATB endpoint
const params = new URL(url).searchParams;
if (params.has('atb')) {
const version = params.get('atb');
const [majorVersion, minorVersion] = version.slice(1).split('-');
if (majorVersion < 360 && minorVersion > 1) {
return route.fulfill({
body: JSON.stringify({
...mockAtb,
updateVersion: `v${majorVersion}-1`,
}),
});
}
}
return route.fulfill({
body: JSON.stringify(mockAtb),
});
}
if (url.startsWith('https://duckduckgo.com/exti') || url.startsWith('https://improving.duckduckgo.com/')) {
return route.fulfill({
status: 200,
body: '',
});
}
route.continue();
};

// based off example at https://playwright.dev/docs/chrome-extensions#testing
export const test = base.extend({
/**
Expand All @@ -53,6 +86,12 @@ export const test = base.extend({
channel: 'chromium',
args: [`--disable-extensions-except=${pathToExtension}`, `--load-extension=${pathToExtension}`],
});

if (manifestVersion === 3) {
// Serve extension background requests from local cache
await context.route('**/*', defaultRouteHandler);
}

// intercept extension install page and use HAR
context.on('page', (page) => {
// console.log('page', page.url())
Expand All @@ -71,40 +110,6 @@ export const test = base.extend({
* @type {import('@playwright/test').Page | import('@playwright/test').Worker}
*/
async backgroundPage({ context, manifestVersion }, use) {
// let background: Page | Worker
const routeHandler = (route) => {
const url = route.request().url();
if (url.startsWith('https://staticcdn.duckduckgo.com/')) {
return routeLocalResources(route);
}
if (url.startsWith('https://duckduckgo.com/atb.js')) {
// mock ATB endpoint
const params = new URL(url).searchParams;
if (params.has('atb')) {
const version = params.get('atb');
const [majorVersion, minorVersion] = version.slice(1).split('-');
if (majorVersion < 360 && minorVersion > 1) {
return route.fulfill({
body: JSON.stringify({
...mockAtb,
updateVersion: `v${majorVersion}-1`,
}),
});
}
}
return route.fulfill({
body: JSON.stringify(mockAtb),
});
}
if (url.startsWith('https://duckduckgo.com/exti') || url.startsWith('https://improving.duckduckgo.com/')) {
return route.fulfill({
status: 200,
body: '',
});
}
route.continue();
};

if (manifestVersion === 3) {
// See https://playwright.dev/docs/service-workers
const getBackgroundServiceWorker = async () => {
Expand Down Expand Up @@ -154,8 +159,6 @@ export const test = base.extend({
throw new Error("Failed to find extension's background ServiceWorker.");
}

// Serve extension background requests from local cache
await context.route('**/*', routeHandler);
await use(background);
} else {
let [background] = context.backgroundPages();
Expand All @@ -164,7 +167,7 @@ export const test = base.extend({
}

// Serve extension background requests from local cache
await background.route('**/*', routeHandler);
await background.route('**/*', defaultRouteHandler);
await use(background);
}
},
Expand Down
Loading