/** * SmartAuth E2E — Enterprise SAML/OIDC * Tests IdP configuration, email domain lookup, and SSO login flows. */ import { test, expect } from '@playwright/test'; test.describe('SmartAuth: Enterprise SSO', () => { test.beforeEach(async ({ page }) => { await page.route('**/api/auth/me', route => route.fulfill({ status: 200, body: JSON.stringify({ id: 'usr_admin', email: 'admin@bytelyst.com', role: 'super_admin', displayName: 'Super Admin', }), }) ); }); test('should lookup IdP by email domain', async ({ page }) => { await page.route('**/api/auth/enterprise/lookup?email=*', route => route.fulfill({ status: 200, body: JSON.stringify({ found: true, idp: { id: 'idp_acme_saml_abc123', orgId: 'org_acme', protocol: 'saml', name: 'Acme Corp SAML', emailDomains: ['acme.com'], }, }), }) ); await page.goto('/settings/security'); const response = await page.evaluate(async () => { const res = await fetch('/api/auth/enterprise/lookup?email=user@acme.com'); return res.json(); }); expect(response.found).toBe(true); expect(response.idp.protocol).toBe('saml'); }); test('should return not found for unknown domain', async ({ page }) => { await page.route('**/api/auth/enterprise/lookup?email=*', route => route.fulfill({ status: 200, body: JSON.stringify({ found: false, idp: null }), }) ); await page.goto('/settings/security'); const response = await page.evaluate(async () => { const res = await fetch('/api/auth/enterprise/lookup?email=user@unknown.com'); return res.json(); }); expect(response.found).toBe(false); }); test('should create IdP config (admin)', async ({ page }) => { await page.route('**/api/auth/enterprise/idps', route => { if (route.request().method() === 'POST') { route.fulfill({ status: 200, body: JSON.stringify({ id: 'idp_acme_oidc_def456', orgId: 'org_acme', protocol: 'oidc', name: 'Acme OIDC', emailDomains: ['acme.com'], enabled: true, }), }); } else { route.fulfill({ status: 200, body: '[]' }); } }); await page.goto('/settings/security'); const response = await page.evaluate(async () => { const res = await fetch('/api/auth/enterprise/idps', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ orgId: 'org_acme', protocol: 'oidc', name: 'Acme OIDC', emailDomains: ['acme.com'], oidc: { issuer: 'https://login.acme.com', clientId: 'client123', clientSecret: 'secret456', authorizationUrl: 'https://login.acme.com/authorize', tokenUrl: 'https://login.acme.com/token', }, }), }); return res.json(); }); expect(response.id).toMatch(/^idp_/); expect(response.protocol).toBe('oidc'); }); test('should handle SAML callback', async ({ page }) => { await page.route('**/api/auth/saml/callback', route => route.fulfill({ status: 200, body: JSON.stringify({ accessToken: 'at_test', refreshToken: 'rt_test', user: { id: 'usr_saml', email: 'user@acme.com', displayName: 'SAML User' }, }), }) ); await page.goto('/'); const response = await page.evaluate(async () => { const samlResponse = btoa('user@acme.com'); const res = await fetch('/api/auth/saml/callback', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ SAMLResponse: samlResponse }), }); return res.json(); }); expect(response).toHaveProperty('accessToken'); expect(response.user.email).toBe('user@acme.com'); }); });