diff --git a/playwright.config.ts b/playwright.config.ts index 13f2f15..94f9353 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -49,6 +49,7 @@ export default defineConfig({ reuseExistingServer: !process.env.CI, stdout: 'pipe', stderr: 'pipe', - timeout: 5 * 60 * 1000, + // the shallow server image sometimes needs several minutes to boot on a slow runner + timeout: 10 * 60 * 1000, }, }) diff --git a/playwright/e2e/oauth-popup.spec.ts b/playwright/e2e/oauth-popup.spec.ts new file mode 100644 index 0000000..df75ffa --- /dev/null +++ b/playwright/e2e/oauth-popup.spec.ts @@ -0,0 +1,52 @@ +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { login } from '@nextcloud/e2e-test-server/playwright' +import { test as base, expect } from '@playwright/test' + +// the test container always has this admin user +const admin = { userId: 'admin', password: 'admin' } + +// Every test also fails on an uncaught exception, or on an unexpected failing request to one of the app's own routes. +// Errors of other apps on the instance are ignored on purpose. +const test = base.extend<{ appErrors: void }>({ + appErrors: [async ({ page }, use) => { + const errors: string[] = [] + page.on('pageerror', (error) => errors.push(`uncaught: ${error.message}`)) + page.on('response', (response) => { + if (response.status() >= 400 && response.url().includes('/integration_onedrive/')) { + errors.push(`${response.status()} ${response.request().method()} ${new URL(response.url()).pathname}`) + } + }) + await use() + expect(errors).toEqual([]) + }, { auto: true }], +}) + +test.beforeEach(async ({ page }) => { + await login(page.request, admin) +}) + +test.describe('OAuth popup', () => { + test('load the page that closes the authentication popup', async ({ page }) => { + // the page runs the popupSuccess bundle, which passes the account name to the window that opened it + const messages: string[] = [] + await page.exposeFunction('reportMessage', (name: string) => messages.push(name)) + await page.addInitScript(() => { + // pretend the page was opened from the settings, the bundle only posts a message then + Object.defineProperty(window, 'opener', { + value: { + postMessage: (data: { username: string }) => (window as unknown as { reportMessage: (name: string) => void }).reportMessage(data.username), + }, + }) + // the bundle closes the popup right after, which would end the test + window.close = () => {} + }) + + await page.goto('apps/integration_onedrive/popup-success?username=jane.doe%40example.com') + + await expect.poll(() => messages).toEqual(['jane.doe@example.com']) + }) +})