feat:Fix the bootstrap to be deploy key application
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { TARGETS, url } from '../targets';
|
||||
|
||||
const t = TARGETS.find((x) => x.name === 'authentik')!;
|
||||
|
||||
// Authentik: the real signal. A healthy pod does NOT prove OIDC/redirect/session
|
||||
// work — only a completed sign-in does. Credentials come from env (injected from
|
||||
// the secret store in-cluster), never hardcoded.
|
||||
const USER = process.env.AK_ADMIN_USER ?? 'akadmin';
|
||||
const PASS = process.env.AK_ADMIN_PASSWORD;
|
||||
|
||||
test('authentik admin can sign in', async ({ page }) => {
|
||||
test.skip(!PASS, 'AK_ADMIN_PASSWORD not set — provide via secret to run the login flow');
|
||||
|
||||
await page.goto(url(t), { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Authentik identification stage: username, Enter/continue, then password.
|
||||
const uid = page.locator('input[name="uidField"], input[type="text"], input[type="email"]').first();
|
||||
await expect(uid).toBeVisible();
|
||||
await uid.fill(USER);
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
const pw = page.locator('input[type="password"]').first();
|
||||
await expect(pw).toBeVisible();
|
||||
await pw.fill(PASS!);
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
// Landed on the user dashboard — no auth error banner.
|
||||
await expect(page).toHaveURL(/\/if\/user|\/if\/admin|\/library/i, { timeout: 20_000 });
|
||||
await expect(page.getByText(/invalid|incorrect|failed/i)).toHaveCount(0);
|
||||
await page.screenshot({ path: 'test-results/authentik-dashboard.png', fullPage: true });
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { OAUTH_TARGETS, url, BASE_DOMAIN } from '../targets';
|
||||
import { completeAuthentikLogin } from '../helpers/authentik';
|
||||
|
||||
// OIDC/OAuth federation flow — the real SSO integration signal. A healthy app pod
|
||||
// does NOT prove SSO works: client mis-registration, redirect-URI mismatch, issuer
|
||||
// cert, or a broken Authentik provider all fail HERE, not at the pod. Each test:
|
||||
// 1. open the app,
|
||||
// 2. click its "sign in via Authentik" control,
|
||||
// 3. complete the Authentik login on the redirect,
|
||||
// 4. assert we return to the app authenticated.
|
||||
const USER = process.env.AK_ADMIN_USER ?? 'akadmin';
|
||||
const PASS = process.env.AK_ADMIN_PASSWORD;
|
||||
|
||||
for (const t of OAUTH_TARGETS) {
|
||||
test(`${t.name} SSO login via Authentik`, async ({ page }) => {
|
||||
test.skip(!PASS, 'AK_ADMIN_PASSWORD not set — provide via secret to run OAuth flows');
|
||||
|
||||
await page.goto(url(t), { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Click the SSO control.
|
||||
const b = t.ssoButton;
|
||||
const btn = b.selector
|
||||
? page.locator(b.selector).first()
|
||||
: page.getByRole((b.role as any) ?? 'link', { name: b.name! }).first();
|
||||
await expect(btn, `${t.name}: SSO login control not found`).toBeVisible();
|
||||
await btn.click();
|
||||
|
||||
// We should be redirected to the Authentik domain (or already have a session).
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
if (page.url().includes(`.${BASE_DOMAIN}`) && /authentik|\/if\/flow/i.test(page.url())) {
|
||||
await completeAuthentikLogin(page, USER, PASS!);
|
||||
} else {
|
||||
// Not obviously on Authentik — still attempt, in case creds render inline.
|
||||
await completeAuthentikLogin(page, USER, PASS!).catch(() => {});
|
||||
}
|
||||
|
||||
// Back in the app, authenticated.
|
||||
const s = t.success;
|
||||
if (s.urlRe) await expect(page).toHaveURL(s.urlRe, { timeout: 25_000 });
|
||||
if (s.selector) await expect(page.locator(s.selector).first()).toBeVisible({ timeout: 25_000 });
|
||||
if (s.text) await expect(page.getByText(s.text).first()).toBeVisible({ timeout: 25_000 });
|
||||
|
||||
await expect(page.getByText(/invalid|unauthorized|access denied|redirect_uri/i)).toHaveCount(0);
|
||||
await page.screenshot({ path: `test-results/oauth-${t.name}.png`, fullPage: true });
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { TARGETS, url } from '../targets';
|
||||
|
||||
const t = TARGETS.find((x) => x.name === 'portainer')!;
|
||||
|
||||
// Portainer: prove the login UI renders over real ingress+TLS in Safari's engine.
|
||||
// (Full authenticated flow needs an initial-admin password; add once seeded.)
|
||||
test('portainer login page renders', async ({ page }) => {
|
||||
const resp = await page.goto(url(t), { waitUntil: 'domcontentloaded' });
|
||||
expect(resp?.status(), 'ingress did not serve portainer').toBeLessThan(400);
|
||||
|
||||
await expect(page.locator('input[type="password"]').first()).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/portainer-login.png', fullPage: true });
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { TARGETS, url } from '../targets';
|
||||
|
||||
// Core assertion the user asked for: once ingress-nginx is up and the app is
|
||||
// ready, NAME-APP.<domain> must be VIEWABLE in Safari's engine — not just return
|
||||
// a status code. We navigate, assert a real 2xx/3xx (not nginx 404/503 default
|
||||
// backend), and assert the app's own UI actually rendered.
|
||||
|
||||
// Only apps without a dedicated flow spec (auth logins live in their own file).
|
||||
const smokeTargets = TARGETS.filter((t) => !t.dedicated);
|
||||
|
||||
for (const t of smokeTargets) {
|
||||
test(`${t.name} is viewable at ${url(t)}`, async ({ page }) => {
|
||||
const resp = await page.goto(url(t), { waitUntil: 'domcontentloaded' });
|
||||
|
||||
expect(resp, 'no response from ingress').toBeTruthy();
|
||||
const status = resp!.status();
|
||||
expect(status, `unexpected HTTP status ${status}`).toBeLessThan(400);
|
||||
|
||||
// Not the nginx default backend / error page.
|
||||
await expect(page.locator('body')).not.toContainText(/default backend - 404|503 Service Temporarily/i);
|
||||
|
||||
// App's own UI rendered.
|
||||
const r = t.ready;
|
||||
if (r.selector) {
|
||||
await expect(page.locator(r.selector).first()).toBeVisible();
|
||||
} else if (r.role && r.name) {
|
||||
await expect(page.getByRole(r.role as any, { name: r.name }).first()).toBeVisible();
|
||||
} else if (r.text) {
|
||||
await expect(page.getByText(r.text).first()).toBeVisible();
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user