Skip to content

Commit

Permalink
Merge branch 'main' into for-of-regressions
Browse files Browse the repository at this point in the history
  • Loading branch information
sidvishnoi authored Jan 31, 2025
2 parents a5b8b93 + b8ce782 commit 600c9b1
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 145 deletions.
8 changes: 1 addition & 7 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,9 @@ if (!process.env.CI) {
export default defineConfig({
testDir,
outputDir: path.join(testDir, 'test-results'),
// We don't want this set to true as that would make tests in each file to run
// in parallel, which will cause conflicts with the "global state". With this
// set to false and workers > 1, multiple test files can run in parallel, but
// tests within a file are run at one at a time. We make extensive use of
// worker-scope fixtures and beforeAll hooks to achieve best performance.
fullyParallel: false,
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [
['list'],
[
Expand Down
2 changes: 1 addition & 1 deletion src/pages/popup/components/Settings/Budget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const BudgetAmount = ({
if (!interval) {
if (changed.recurring && !recurring) {
interval = undefined;
} else if ((changed.recurring && recurring) || changed.amount) {
} else if ((changed.recurring || changed.amount) && recurring) {
interval = `R/${new Date().toISOString()}/P1M`;
} else if (grants.recurring?.interval) {
interval = grants.recurring.interval;
Expand Down
5 changes: 0 additions & 5 deletions tests/e2e/connect.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
/// <reference types="chrome"/>
import { test, expect } from './fixtures/base';
import { connectWallet, disconnectWallet } from './pages/popup';

test.beforeEach(async ({ popup }) => {
await popup.reload();
});

test('connects with correct details provided', async ({
persistentContext,
background,
Expand Down
25 changes: 10 additions & 15 deletions tests/e2e/fixtures/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,22 @@ import { getLastCallArg } from '../helpers/common';
import { openPopup, type Popup } from '../pages/popup';
import type { DeepPartial, Storage } from '@/shared/types';

type BaseScopeWorker = {
type Fixtures = {
persistentContext: BrowserContext;
background: Background;
i18n: BrowserIntl;
/**
* IMPORTANT: This is created once per test file. Mutating/closing could
* impact other tests in same file.
*/
popup: Popup;
i18n: BrowserIntl;
page: Page;
};

export const test = base.extend<{ page: Page }, BaseScopeWorker>({
// Extensions only work with a persistent context.
// Ideally we wanted this fixture to be named "context", but it's already defined in default base context under the scope "test".
export const test = base.extend<Fixtures>({
persistentContext: [
async ({ browserName, channel }, use, workerInfo) => {
const context = await loadContext({ browserName, channel }, workerInfo);
async ({ browserName, channel }, use, testInfo) => {
const context = await loadContext({ browserName, channel }, testInfo);
await use(context);
await context.close();
},
{ scope: 'worker', timeout: 5_000 },
{ scope: 'test', timeout: 5_000 },
],

// This is the background service worker in Chrome, and background script
Expand All @@ -47,15 +42,15 @@ export const test = base.extend<{ page: Page }, BaseScopeWorker>({
const background = await getBackground(browserName, context);
await use(background);
},
{ scope: 'worker', timeout: 5_000 },
{ scope: 'test', timeout: 5_000 },
],

i18n: [
async ({ browserName }, use) => {
const i18n = new BrowserIntl(browserName);
await use(i18n);
},
{ scope: 'worker' },
{ scope: 'test' },
],

popup: [
Expand All @@ -65,7 +60,7 @@ export const test = base.extend<{ page: Page }, BaseScopeWorker>({
await use(popup);
await popup.close();
},
{ scope: 'worker', timeout: 5_000 },
{ scope: 'test', timeout: 5_000 },
],

page: async ({ persistentContext: context }, use) => {
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/fixtures/connected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ export const test = base.extend<{ page: Page }, { popup: Popup }>({
amount: '10',
recurring: false,
});
await popup.reload({ waitUntil: 'networkidle' });
await popup.reload();

await use(popup);

await disconnectWallet(popup);
},
{ scope: 'worker', timeout: 20_000 },
{ scope: 'test', timeout: 20_000 },
],
});

Expand Down
205 changes: 98 additions & 107 deletions tests/e2e/not-monetized.spec.ts
Original file line number Diff line number Diff line change
@@ -1,133 +1,124 @@
import { pathToFileURL } from 'node:url';
import { test, expect } from './fixtures/connected';
import type { Locator } from '@playwright/test';
import { setupPlayground } from './helpers/common';

const walletAddressUrl = process.env.TEST_WALLET_ADDRESS_URL;

test.beforeEach(async ({ popup, page }) => {
await popup.reload();
await page.bringToFront();
});

test('shows not monetized on empty tabs', async ({
popup,
i18n,
persistentContext: context,
}) => {
const warning = popup.getByTestId('not-monetized-message');
const msg = i18n.getMessage('notMonetized_text_newTab');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);

await context.newPage().then((page) => page.bringToFront());
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
});

test('shows not monetized on internal pages', async ({
page,
// We make extensive use of test.step in this test to reuse the same browser
// instance, as connecting wallet each time for small tests is expensive.
test('shows not-monetized status', async ({
popup,
i18n,
channel,
background,
persistentContext: context,
}) => {
const url = channel === 'msedge' ? 'edge://settings' : 'chrome://settings';
await page.goto(url);

const warning = popup.getByTestId('not-monetized-message');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(
i18n.getMessage('notMonetized_text_internalPage'),
);
});

test.describe('shows not monetized on non-https pages', () => {
let warning: Locator;
let msg: string;

test.beforeAll(async ({ popup, i18n }) => {
warning = popup.getByTestId('not-monetized-message');
msg = i18n.getMessage('notMonetized_text_unsupportedScheme');
});

test.beforeEach(async ({ popup, page }) => {
const msg = {
newTab: i18n.getMessage('notMonetized_text_newTab'),
internalPage: i18n.getMessage('notMonetized_text_internalPage'),
unsupportedScheme: i18n.getMessage('notMonetized_text_unsupportedScheme'),
noLinks: i18n.getMessage('notMonetized_text_noLinks'),
};

const newPage = async () => {
const page = await context.newPage();
await popup.reload();
await page.bringToFront();
});

test('http:// URLs', async ({ page }) => {
await page.goto('http://example.com');
return {
goto: page.goto.bind(page), // so we don't have to call `page.page.goto()` every time
page: page,
[Symbol.asyncDispose]: async () => {
await page.close();
},
};
};

await test.step('shows not monetized on empty tabs', async () => {
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
});

test('navigating from https:// to http://', async ({ page, i18n }) => {
await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(
i18n.getMessage('notMonetized_text_noLinks'),
);
await expect(warning).toHaveText(msg.newTab);

await page.goto('http://example.com');
await using _page = await newPage();
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
await expect(warning).toHaveText(msg.newTab);
});

test('file:// URLs', async ({ page }) => {
await page.goto(pathToFileURL('.').href);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
});
await test.step('shows not monetized on internal pages', async () => {
await using page = await newPage();
const url = channel === 'msedge' ? 'edge://settings' : 'chrome://settings';
await page.goto(url);

test('extension pages', async ({ page, background }) => {
const popupUrl = await background.evaluate(() =>
chrome.action.getPopup({}),
);
await page.goto(popupUrl);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
await expect(warning).toHaveText(msg.internalPage);
});
});

test.describe('shows not monetized on non-monetized pages', () => {
let warning: Locator;
let msg: string;

test.beforeAll(async ({ popup, i18n }) => {
warning = popup.getByTestId('not-monetized-message');
msg = i18n.getMessage('notMonetized_text_noLinks');
await test.step('shows not monetized on non-https pages', async () => {
await test.step('http:// URLs', async () => {
await using page = await newPage();
await page.goto('http://httpforever.com/');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.unsupportedScheme);
});

await test.step('navigating from https:// to http://', async () => {
await using page = await newPage();
await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.noLinks);

await page.goto('http://httpforever.com/');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.unsupportedScheme);
});

await test.step('file:// URLs', async () => {
await using page = await newPage();
await page.goto(pathToFileURL('.').href);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.unsupportedScheme);
});

await test.step('extension pages', async () => {
await using page = await newPage();
const popupUrl = await background.evaluate(() =>
chrome.action.getPopup({}),
);
await page.goto(popupUrl);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.unsupportedScheme);
});
});

test.beforeEach(async ({ page, popup }) => {
await popup.reload();
await page.bringToFront();
});

test('no link tags', async ({ page }) => {
await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
});

test('no enabled link tags', async ({ page }) => {
await page.goto('https://example.com');
await page.evaluate((walletAddressUrl) => {
const link = document.createElement('link');
link.rel = 'monetization';
link.disabled = true;
link.href = walletAddressUrl;
document.head.appendChild(link);
}, walletAddressUrl);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
});

test('navigating from monetized to non-monetized', async ({ page }) => {
await setupPlayground(page, walletAddressUrl);
await expect(warning).not.toBeVisible();

await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg);
await test.step('shows not monetized on non-monetized pages', async () => {
await test.step('no link tags', async () => {
await using page = await newPage();
await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.noLinks);
});

await test.step('no enabled link tags', async () => {
await using page = await newPage();
await page.goto('https://example.com');
await page.page.evaluate((walletAddressUrl) => {
const link = document.createElement('link');
link.rel = 'monetization';
link.disabled = true;
link.href = walletAddressUrl;
document.head.appendChild(link);
}, walletAddressUrl);
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.noLinks);
});

await test.step('navigating from monetized to non-monetized', async () => {
await using page = await newPage();
await setupPlayground(page.page, walletAddressUrl);
await expect(warning).not.toBeVisible();

await page.goto('https://example.com');
await expect(warning).toBeVisible();
await expect(warning).toHaveText(msg.noLinks);
});
});
});
4 changes: 0 additions & 4 deletions tests/e2e/overpaying.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import {
import { sendOneTimePayment } from './pages/popup';
import type { OutgoingPayment } from '@interledger/open-payments';

test.beforeEach(async ({ popup }) => {
await popup.reload();
});

test.afterEach(({ persistentContext: context }) => {
context.removeAllListeners('requestfinished');
});
Expand Down
4 changes: 0 additions & 4 deletions tests/e2e/simple.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { test, expect } from './fixtures/connected';
import { setupPlayground } from './helpers/common';

test.beforeEach(async ({ popup }) => {
await popup.reload();
});

test('should monetize site with single wallet address', async ({
page,
popup,
Expand Down

0 comments on commit 600c9b1

Please sign in to comment.