@camunda/e2e-test-suite 0.0.531 → 0.0.533

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Auth0 smoke tests — HTTP-level integration check for the auth0 ci-test
4
+ // scenario. Each Camunda 8 component on the platform is fronted by an OIDC
5
+ // client; this suite asserts the chart wiring is correct end-to-end without
6
+ // needing a browser, an Auth0 user, or a token exchange.
7
+ //
8
+ // HTTP-only by design: the Auth0 ci-test scenario does not deploy Keycloak,
9
+ // so the browser-driven setupKeycloakUser flow used by the SM smokes is not
10
+ // applicable. This suite validates chart-to-IDP wiring only — it does not
11
+ // drive a real user session.
12
+ //
13
+ // Two flavours of test, one per component family:
14
+ //
15
+ // 1. Spring-server components (orchestration, identity, optimize) expose
16
+ // /<component>/oauth2/authorization/oidc as the canonical login entry.
17
+ // Hitting it unauthenticated walks a redirect chain that must terminate
18
+ // at AUTH0_ISSUER/authorize carrying the right client_id, redirect_uri,
19
+ // and response_type. We trace the chain ourselves so we can assert on
20
+ // every hop.
21
+ //
22
+ // 2. SPA components (webModeler, console) render a client-side login page
23
+ // and do the OIDC redirect from JS, so a server-side trace stops at the
24
+ // SPA shell. Instead, hit a backend API that demands a Bearer token —
25
+ // a 401 with a WWW-Authenticate header proves the chart wired the
26
+ // component to require an OIDC token at all.
27
+ //
28
+ // Plus a sanity test that AUTH0_ISSUER/.well-known/openid-configuration
29
+ // resolves and points at the right issuer; if that breaks, every other
30
+ // failure is downstream noise.
31
+ const test_1 = require("@playwright/test");
32
+ const ingressHost = process.env.TEST_INGRESS_HOST;
33
+ const auth0Issuer = (process.env.AUTH0_ISSUER_URL || '').replace(/\/+$/, '');
34
+ const MAX_HOPS = 10;
35
+ // Spring-server components: each redirect-chain terminates at Auth0 /authorize.
36
+ const springComponents = [
37
+ // [logical-name, oauth2-entry-path, expected client_id env var]
38
+ [
39
+ 'orchestration',
40
+ '/orchestration/oauth2/authorization/oidc',
41
+ 'AUTH0_ORCHESTRATION_CLIENT_ID',
42
+ ],
43
+ ['identity', '/identity/oauth2/authorization/oidc', 'AUTH0_IDENTITY_CLIENT_ID'],
44
+ ['optimize', '/optimize/oauth2/authorization/oidc', 'AUTH0_OPTIMIZE_CLIENT_ID'],
45
+ ];
46
+ // SPA components: assert a protected backend API returns 401.
47
+ const spaComponents = [
48
+ ['webModeler', '/modeler/api/v1/info'],
49
+ ['console', '/api/v1/clusters'],
50
+ ];
51
+ test_1.test.describe('Auth0 OIDC smoke', () => {
52
+ test_1.test.beforeAll(() => {
53
+ (0, test_1.expect)(ingressHost, 'TEST_INGRESS_HOST must be set by the test runner').toBeTruthy();
54
+ (0, test_1.expect)(auth0Issuer, 'AUTH0_ISSUER_URL must be set by the test runner').toBeTruthy();
55
+ });
56
+ for (const [name, urlPath, clientIdVar] of springComponents) {
57
+ (0, test_1.test)(`${name}: ${urlPath} redirects to Auth0 /authorize`, async ({ request, }) => {
58
+ const expectedClientId = process.env[clientIdVar];
59
+ (0, test_1.expect)(expectedClientId, `${clientIdVar} must be set by the test runner`).toBeTruthy();
60
+ const start = `https://${ingressHost}${urlPath}`;
61
+ const chain = await traceRedirectChain(request, start);
62
+ const authorizeHop = chain.find((u) => u.origin === auth0Issuer && u.pathname === '/authorize');
63
+ (0, test_1.expect)(authorizeHop, `chain did not reach ${auth0Issuer}/authorize:\n${chain
64
+ .map((u) => ' → ' + u.toString())
65
+ .join('\n')}`).toBeTruthy();
66
+ const params = authorizeHop.searchParams;
67
+ (0, test_1.expect)(params.get('client_id'), `client_id must match ${expectedClientId}`).toBe(expectedClientId);
68
+ (0, test_1.expect)(params.get('response_type'), 'response_type must be code').toBe('code');
69
+ (0, test_1.expect)(params.get('redirect_uri'), 'redirect_uri must be present').toBeTruthy();
70
+ (0, test_1.expect)(params.get('scope'), 'scope must include openid').toContain('openid');
71
+ });
72
+ }
73
+ for (const [name, urlPath] of spaComponents) {
74
+ (0, test_1.test)(`${name}: ${urlPath} requires authentication (401)`, async ({ request, }) => {
75
+ const url = `https://${ingressHost}${urlPath}`;
76
+ const response = await request.get(url, { maxRedirects: 0 });
77
+ (0, test_1.expect)(response.status(), `${url} returned ${response.status()} ${response.statusText()}; expected 401 from a protected backend route`).toBe(401);
78
+ });
79
+ }
80
+ (0, test_1.test)('Auth0 well-known OIDC config is reachable', async ({ request }) => {
81
+ const url = `${auth0Issuer}/.well-known/openid-configuration`;
82
+ const response = await request.get(url, { maxRedirects: 0 });
83
+ (0, test_1.expect)(response.status(), `${url} returned ${response.status()}`).toBe(200);
84
+ const body = await response.json();
85
+ (0, test_1.expect)(body.issuer, 'issuer claim must match AUTH0_ISSUER_URL').toBe(auth0Issuer + '/');
86
+ (0, test_1.expect)(body.authorization_endpoint, 'authorization_endpoint must be present').toMatch(/\/authorize$/);
87
+ (0, test_1.expect)(body.jwks_uri, 'jwks_uri must be present').toMatch(/\/jwks\.json$/);
88
+ });
89
+ });
90
+ // traceRedirectChain follows Location headers manually so the test can
91
+ // inspect every URL in the chain — Playwright's APIRequestContext follows
92
+ // redirects transparently otherwise and we'd lose intermediate hops.
93
+ async function traceRedirectChain(request, startUrl) {
94
+ const chain = [new URL(startUrl)];
95
+ let current = startUrl;
96
+ for (let hop = 0; hop < MAX_HOPS; hop++) {
97
+ const response = await request.get(current, { maxRedirects: 0 });
98
+ const status = response.status();
99
+ if (![301, 302, 303, 307, 308].includes(status)) {
100
+ return chain;
101
+ }
102
+ const location = response.headers()['location'];
103
+ if (!location) {
104
+ return chain;
105
+ }
106
+ // Resolve relative redirects against the current URL.
107
+ const next = new URL(location, current);
108
+ chain.push(next);
109
+ current = next.toString();
110
+ }
111
+ return chain;
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.531",
3
+ "version": "0.0.533",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",