import test, { expect } from '@playwright/test'; import { oidcClients } from './data'; import { cleanupBackend } from './utils/cleanup.util'; import passkeyUtil from './utils/passkey.util'; test.beforeEach(cleanupBackend); test('Authorize existing client', async ({ page }) => { const oidcClient = oidcClients.nextcloud; const urlParams = createUrlParams(oidcClient); await page.goto(`/authorize?${urlParams.toString()}`); // Ignore DNS resolution error as the callback URL is not reachable await page.waitForURL(oidcClient.callbackUrl).catch((e) => { if (!e.message.includes('net::ERR_NAME_NOT_RESOLVED')) { throw e; } }); }); test('Authorize existing client while not signed in', async ({ page }) => { const oidcClient = oidcClients.nextcloud; const urlParams = createUrlParams(oidcClient); await page.context().clearCookies(); await page.goto(`/authorize?${urlParams.toString()}`); await (await passkeyUtil.init(page)).addPasskey(); await page.getByRole('button', { name: 'Sign in' }).click(); // Ignore DNS resolution error as the callback URL is not reachable await page.waitForURL(oidcClient.callbackUrl).catch((e) => { if (!e.message.includes('net::ERR_NAME_NOT_RESOLVED')) { throw e; } }); }); test('Authorize new client', async ({ page }) => { const oidcClient = oidcClients.immich; const urlParams = createUrlParams(oidcClient); await page.goto(`/authorize?${urlParams.toString()}`); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible(); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible(); await page.getByRole('button', { name: 'Sign in' }).click(); // Ignore DNS resolution error as the callback URL is not reachable await page.waitForURL(oidcClient.callbackUrl).catch((e) => { if (!e.message.includes('net::ERR_NAME_NOT_RESOLVED')) { throw e; } }); }); test('Authorize new client while not signed in', async ({ page }) => { const oidcClient = oidcClients.immich; const urlParams = createUrlParams(oidcClient); await page.context().clearCookies(); await page.goto(`/authorize?${urlParams.toString()}`); await (await passkeyUtil.init(page)).addPasskey(); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible(); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible(); await page.getByRole('button', { name: 'Sign in' }).click(); // Ignore DNS resolution error as the callback URL is not reachable await page.waitForURL(oidcClient.callbackUrl).catch((e) => { if (!e.message.includes('net::ERR_NAME_NOT_RESOLVED')) { throw e; } }); }); test('Authorize new client fails with user group not allowed', async ({ page }) => { const oidcClient = oidcClients.immich; const urlParams = createUrlParams(oidcClient); await page.context().clearCookies(); await page.goto(`/authorize?${urlParams.toString()}`); await (await passkeyUtil.init(page)).addPasskey('craig'); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible(); await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible(); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page.getByRole('paragraph').first()).toHaveText("You're not allowed to access this service."); }); function createUrlParams(oidcClient: { id: string; callbackUrl: string }) { return new URLSearchParams({ client_id: oidcClient.id, response_type: 'code', scope: 'openid profile email', redirect_uri: oidcClient.callbackUrl, state: 'nXx-6Qr-owc1SHBa', nonce: 'P1gN3PtpKHJgKUVcLpLjm' }); }