stack/apps/e2e/tests/backend/endpoints/api/migration-tests.test.ts
Konsti Wohlwend 3d4c608187
Customizable ports (#962)
<!--
ONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

<!-- RECURSEML_SUMMARY:START -->

## High-level PR Summary

This PR changes the default development ports for several background
services to avoid conflicts. PostgreSQL moves from port `5432` to
`8128`, Inbucket SMTP from `2500` to `8129`, Inbucket POP3 from `1100`
to `8130`, and the OpenTelemetry collector from `4318` to `8131`. All
references across configuration files, Docker Compose setups,
environment files, CI/CD workflows, test files, and documentation have
been updated to reflect these new port assignments. A knowledge base
document has been added to document the new port mappings.

⏱️ Estimated Review Time: 15-30 minutes

<details>
<summary>💡 Review Order Suggestion</summary>

| Order | File Path |
| --- | --- |
| 1 | `claude/CLAUDE-KNOWLEDGE.md` |
| 2 | `apps/dev-launchpad/public/index.html` |
| 3 | `docker/dependencies/docker.compose.yaml` |
| 4 | `docker/emulator/docker.compose.yaml` |
| 5 | `apps/backend/.env` |
| 6 | `apps/backend/.env.development` |
| 7 | `docker/server/.env.example` |
| 8 | `package.json` |
| 9 | `.devcontainer/devcontainer.json` |
| 10 | `apps/e2e/.env.development` |
| 11 | `.github/workflows/check-prisma-migrations.yaml` |
| 12 | `.github/workflows/docker-server-test.yaml` |
| 13 | `.github/workflows/e2e-api-tests.yaml` |
| 14 | `.github/workflows/e2e-source-of-truth-api-tests.yaml` |
| 15 | `.github/workflows/restart-dev-and-test.yaml` |
| 16 |
`apps/e2e/tests/backend/endpoints/api/v1/internal/email-drafts.test.ts`
|
| 17 | `apps/e2e/tests/backend/endpoints/api/v1/internal/email.test.ts`
|
| 18 | `apps/e2e/tests/backend/endpoints/api/v1/send-email.test.ts` |
| 19 |
`apps/e2e/tests/backend/endpoints/api/v1/unsubscribe-link.test.ts` |
| 20 | `apps/e2e/tests/backend/workflows.test.ts` |
| 21 | `docs/templates/others/self-host.mdx` |

</details>

[![Need help? Join our
Discord](https://img.shields.io/badge/Need%20help%3F%20Join%20our%20Discord-5865F2?style=plastic&logo=discord&logoColor=white)](https://discord.gg/n3SsVDAW6U)

[![Analyze latest
changes](21c3d5c362/?repo_owner=stack-auth&repo_name=stack-auth&pr_number=962)

<!-- RECURSEML_SUMMARY:END -->

<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> This PR introduces customizable development ports using
`NEXT_PUBLIC_STACK_PORT_PREFIX`, updating configurations, documentation,
and tests accordingly.
> 
>   - **Behavior**:
> - Default development ports for services are now customizable via
`NEXT_PUBLIC_STACK_PORT_PREFIX`.
> - PostgreSQL port changed from `5432` to
`${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}28`.
> - Inbucket SMTP port changed from `2500` to
`${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}29`.
> - Inbucket POP3 port changed from `1100` to
`${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}30`.
> - OpenTelemetry collector port changed from `4318` to
`${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}31`.
>   - **Configuration**:
> - Updated `docker.compose.yaml` to use new port variables for services
like PostgreSQL, Inbucket, and OpenTelemetry.
> - Environment files in `apps/backend`, `apps/dashboard`, and
`apps/e2e` updated to use `NEXT_PUBLIC_STACK_PORT_PREFIX`.
> - `package.json` scripts updated to reflect new port configurations.
>   - **Documentation**:
>     - Added `CLAUDE-KNOWLEDGE.md` to document new port mappings.
>     - Updated `self-host.mdx` to reflect new port configurations.
>   - **Testing**:
> - Updated test files in `apps/e2e/tests` to use new port
configurations.
>     - Added `helpers/ports.ts` for port-related utilities in tests.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for 76ef55f58f. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>

----


<!-- ELLIPSIS_HIDDEN -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Enable configurable development ports via a
NEXT_PUBLIC_STACK_PORT_PREFIX, allowing parallel local environments with
custom port prefixes.

- **Bug Fixes**
- Updated local service port mappings and CI/workflow settings so
tooling and tests use the new prefixed ports consistently.

- **Documentation**
- Added docs and contributor guidance for running multiple parallel
workspaces with custom port prefixes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: N2D4 <N2D4@users.noreply.github.com>
2025-10-20 15:24:47 -07:00

336 lines
14 KiB
TypeScript

import { describe } from "vitest";
import { it } from "../../../helpers";
import { niceBackendFetch } from "../../backend-helpers";
/*
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
*/
describe("SmartRouteHandler", () => {
describe("v1", () => {
it("should return a 404 error", async ({ expect }) => {
const response = await niceBackendFetch("/api/v1/migration-tests/smart-route-handler");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 404,
"body": deindent\`
404 — this page does not exist in Stack Auth's API.
Please see the API documentation at https://docs.stack-auth.com, or visit the Stack Auth dashboard at https://app.stack-auth.com.
URL: http://localhost:<$NEXT_PUBLIC_STACK_PORT_PREFIX>02/api/v1/migration-tests/smart-route-handler
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
});
describe("v2beta1", () => {
it("should return 200 without queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta1/migration-tests/smart-route-handler");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
The query parameter you passed in is: n/a
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
expect(response.headers.get("x-middleware-rewrite")).toBe(`/api/migrations/v2beta2/migration-tests/smart-route-handler`);
});
it("should return 200 with queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta1/migration-tests/smart-route-handler?queryParam=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
The query parameter you passed in is: 123
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
it("should fail with queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta1/migration-tests/smart-route-handler?queryParamNew=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta1/migration-tests/smart-route-handler:
- query contains unknown properties: queryParamNew
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta1/migration-tests/smart-route-handler:
- query contains unknown properties: queryParamNew
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
});
describe("v2beta2", () => {
it("should return 200 with queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta2/migration-tests/smart-route-handler?queryParam=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
The query parameter you passed in is: 123
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
it("should fail without queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta2/migration-tests/smart-route-handler");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta2/migration-tests/smart-route-handler:
- query.queryParam must be defined
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta2/migration-tests/smart-route-handler:
- query.queryParam must be defined
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
it("should fail with queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta2/migration-tests/smart-route-handler?queryParam=123&queryParamNew=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta2/migration-tests/smart-route-handler:
- query contains unknown properties: queryParamNew
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta2/migration-tests/smart-route-handler:
- query contains unknown properties: queryParamNew
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
});
describe("v2beta3", () => {
it("should return 200 with queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta3/migration-tests/smart-route-handler?queryParamNew=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
The query parameter you passed in is: 123
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
it("should fail without queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta3/migration-tests/smart-route-handler");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta3/migration-tests/smart-route-handler:
- query.queryParamNew must be defined
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta3/migration-tests/smart-route-handler:
- query.queryParamNew must be defined
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
it("should fail with queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta3/migration-tests/smart-route-handler?queryParam=123&queryParamNew=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta3/migration-tests/smart-route-handler:
- query contains unknown properties: queryParam
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta3/migration-tests/smart-route-handler:
- query contains unknown properties: queryParam
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
});
describe("v2beta4", () => {
it("should return 200 with queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta4/migration-tests/smart-route-handler?queryParamNew=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
The query parameter you passed in is: 123
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
it("should return 200 without queryParamNew", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta4/migration-tests/smart-route-handler");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": deindent\`
Welcome to the migration test route for SmartRouteHandler! This route only exists for demonstration purposes and has no practical functionality.
Looks like you didn't pass in the query parameter. That's fine, read on below to see what this route does.
Here's what it does:
- v1: This route does not yet exist; it shows a 404 error.
- v2beta1: Takes an optional query parameter 'queryParam' and displays it. If not given, it defaults to the string "n/a".
- v2beta2: The query parameter is now required.
- v2beta3: The query parameter is now called 'queryParamNew'.
- v2beta4: The query parameter is now optional again (this is not actually a breaking change, so in a real scenario we wouldn't need a new version).
\`,
"headers": Headers { <some fields may have been hidden> },
}
`);
});
it("should fail with queryParam", async ({ expect }) => {
const response = await niceBackendFetch("/api/v2beta4/migration-tests/smart-route-handler?queryParam=123");
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "SCHEMA_ERROR",
"details": {
"message": deindent\`
Request validation failed on GET /api/v2beta4/migration-tests/smart-route-handler:
- query contains unknown properties: queryParam
\`,
},
"error": deindent\`
Request validation failed on GET /api/v2beta4/migration-tests/smart-route-handler:
- query contains unknown properties: queryParam
\`,
},
"headers": Headers {
"x-stack-known-error": "SCHEMA_ERROR",
<some fields may have been hidden>,
},
}
`);
});
});
});