Files
caddy-proxy-manager/tests/e2e/functional/ssl-redirect.spec.ts
fuomag9 9c60d11c2c feat: improve UI contrast, dark mode, dialog sizing, color coherence, and add table sorting
- Fix dialog scrollability (flex layout + max-h-[90dvh]) and increase L4 dialog to lg width
- Add styled enable card to L4 dialog matching proxy host pattern
- Unify section colors across proxy host and L4 dialogs (cyan=LB, emerald=DNS, violet=upstream DNS, rose=geo, amber=mTLS)
- Improve light mode contrast: muted-foreground oklch 0.552→0.502, remove opacity modifiers on secondary text
- Improve dark mode: boost muted-foreground to 0.85, increase border opacity 10%→16%, input 15%→20%
- Add bg-card to DataTable wrapper and bg-muted/40 to table headers for surface hierarchy
- Add semantic badge variants (success, warning, info, muted) and StatusChip dark mode fix
- Add server-side sortable columns to Proxy Hosts and L4 Proxy Hosts (name, upstream, status, protocol, listen)
- Add sortKey to DataTable Column type with clickable sort headers (ArrowUp/Down indicators, URL param driven)
- Fix E2E test selectors for shadcn UI (label associations, combobox roles, dropdown menus, mobile drawer)
- Add htmlFor/id to proxy host form fields and aria-labels to select triggers for accessibility
- Add sorting E2E tests for both proxy host pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:17:56 +01:00

64 lines
2.5 KiB
TypeScript

/**
* Functional tests: HTTP→HTTPS redirect when ssl_forced is enabled.
*
* Creates a proxy host with ssl_forced=true (the default when the form
* field is present without the ssl_forced_present bypass) and verifies
* that plain HTTP requests receive a 308 permanent redirect to HTTPS.
*
* Domain: func-ssl.test
*/
import { test, expect } from '@playwright/test';
import { httpGet, waitForRoute } from '../../helpers/http';
import { injectFormFields } from '../../helpers/http';
const DOMAIN = 'func-ssl.test';
test.describe.serial('SSL Redirect (ssl_forced)', () => {
test('setup: create proxy host with ssl_forced=true', async ({ page }) => {
// Navigate to proxy-hosts and open the create dialog manually so we can
// inject ssl_forced=true without the ssl_forced_present bypass.
await page.goto('/proxy-hosts');
await page.getByRole('button', { name: /create host/i }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await page.getByLabel('Name').fill('Functional SSL Redirect Test');
await page.getByLabel(/domains/i).fill(DOMAIN);
await page.getByPlaceholder('10.0.0.5:8080').fill('echo-server:8080');
// Inject ssl_forced=true (default form behavior — no override)
await injectFormFields(page, {
ssl_forced_present: 'on',
ssl_forced: 'on', // checkbox checked → ssl_forced = true
});
await page.getByRole('button', { name: /^create$/i }).click();
await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 15_000 });
await expect(page.getByRole('table').getByText('Functional SSL Redirect Test')).toBeVisible({ timeout: 10_000 });
await waitForRoute(DOMAIN);
});
test('HTTP request receives 308 redirect to HTTPS', async () => {
const res = await httpGet(DOMAIN, '/');
// Caddy redirects HTTP→HTTPS when ssl_forced=true
expect(res.status).toBe(308);
});
test('redirect Location header points to HTTPS', async () => {
const res = await httpGet(DOMAIN, '/');
expect(res.status).toBe(308);
const location = res.headers['location'];
const locationStr = Array.isArray(location) ? location[0] : (location ?? '');
expect(locationStr).toMatch(/^https:\/\//);
expect(locationStr).toContain(DOMAIN);
});
test('redirect preserves the request path', async () => {
const res = await httpGet(DOMAIN, '/some/path');
expect(res.status).toBe(308);
const location = res.headers['location'];
const locationStr = Array.isArray(location) ? location[0] : (location ?? '');
expect(locationStr).toContain('/some/path');
});
});