-
Notifications
You must be signed in to change notification settings - Fork 0
DC-4635 Add Tests #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a CI workflow and Vitest-based test infrastructure; introduces unit and integration tests for claim-db-worker and create-db; exports two utility functions from create-db; and updates package scripts and devDependencies to support testing. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant ClaimPage
participant API as /api/auth/url
participant Browser
User->>ClaimPage: Click "Claim database"
ClaimPage->>API: POST { projectID }
API-->>ClaimPage: 200 { authUrl }
ClaimPage->>Browser: window.open(authUrl, "_blank")
note over ClaimPage,Browser: Button disabled during request, re-enabled after
sequenceDiagram
autonumber
participant Provider as OAuth Provider
participant Callback as /api/auth/callback
participant Auth as auth-utils
participant Project as project-transfer
participant Resp as response-utils
participant PostHog as Telemetry
Provider->>Callback: GET ?code=...&state=projectID
alt missing state
Callback->>Resp: redirectToError("Missing State Parameter", ...)
else state present
Callback->>Auth: exchangeCodeForToken(code, projectID)
alt exchange fails
Callback->>Resp: redirectToError("Authentication Failed", error)
else token ok
Callback->>Auth: validateProject(projectID)
Callback->>Project: transferProject(projectID, token)
alt transfer failure
Callback->>Resp: redirectToError("Transfer Failed", reason)
else transfer success
Callback->>PostHog: fetch(POST event "create_db:claim_successful")
Callback->>Resp: redirectToSuccess(request, projectID)
end
end
end
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🔇 Additional comments (1)
Comment |
Deploying with
|
Status | Name | Latest Commit | Preview URL | Updated (UTC) |
---|---|---|---|---|
✅ Deployment successful! View logs |
claim-db-worker | 90b0f22 | Commit Preview URL Branch Preview URL |
Sep 16 2025, 06:26 PM |
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr58
npx create-pg@pr58
npx create-postgres@$pr58 Worker URLs
|
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr58
npx create-pg@pr58
npx create-postgres@$pr58 Worker URLs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
create-db/index.js (2)
76-106
: Handle NaN/invalid coordinates ingetRegionClosestToLocation
.If
latitude/longitude
are missing or unparsable,parseFloat
yieldsNaN
, and the Haversine math propagates it. Early-returnnull
when inputs are invalid.Apply this diff:
export function getRegionClosestToLocation(userLocation) { if (!userLocation) return null; - const userLat = parseFloat(userLocation.latitude); - const userLng = parseFloat(userLocation.longitude); + const userLat = parseFloat(userLocation.latitude); + const userLng = parseFloat(userLocation.longitude); + if (!Number.isFinite(userLat) || !Number.isFinite(userLng)) return null;
754-755
: Do not execute the CLI on import; guardmain()
for ESM.Tests import named exports from this file; unconditional
main()
causes side effects andprocess.exit
, terminating the test runner.Apply this diff:
+import { pathToFileURL } from "url"; @@ -main(); +// Only run when executed directly: `node index.js` or via the installed bin. +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + void main(); +}create-db/__tests__/create.test.js (1)
1-32
: Tests hit production APIs and don’t varyprocess.argv[1]
; mock the worker and wrap the entry to exercise all command aliases.Current tests call real endpoints (
/health
,/regions
,/create
) and will flake/rate-limit. They also setnpm_package_name
which the CLI doesn’t read, so command variants aren’t actually exercised.Apply this diff to:
- Start a local HTTP server that mocks the worker,
- Force region to skip geo lookup,
- Use per-command wrapper entry files so
process.argv[1]
containscreate-db|create-postgres|create-pg
.-import { describe, it, expect } from "vitest"; -import { execa } from "execa"; -import { fileURLToPath } from "url"; -import path from "path"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const CLI_PATH = path.resolve(__dirname, "../index.js"); - -const runCli = async (args = [], options = {}) => { - return execa("node", [CLI_PATH, ...args], { - ...options, - env: { ...process.env, ...options.env }, - reject: false, - timeout: 15000, // 15 second timeout - }); -}; - -describe("database creation", () => { - ["create-db", "create-postgres", "create-pg"].forEach((command) => { - it(`creates database with ${command}`, async () => { - const { stdout } = await runCli([], { - env: { - ...process.env, - npm_package_name: command, - }, - }); - - expect(stdout).toContain("Database created successfully!"); - }, 20000); - }); -}); +import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { execa } from "execa"; +import { fileURLToPath } from "url"; +import path from "path"; +import fs from "fs"; +import os from "os"; +import http from "http"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const CLI_PATH = path.resolve(__dirname, "../index.js"); + +let server; +let baseUrl; +const wrappers = []; + +function createWrapper(command) { + // Name contains the command so getCommandName() sees it. + const file = path.join(os.tmpdir(), `.cli-${command}.mjs`); + fs.writeFileSync(file, `import "${CLI_PATH.replace(/\\/g, "\\\\")}";\n`); + wrappers.push(file); + return file; +} + +const runCli = async (scriptPath, args = [], env = {}) => { + return execa("node", [scriptPath, ...args], { + env: { ...process.env, ...env }, + reject: false, + timeout: 20000, + }); +}; + +beforeAll(async () => { + server = http.createServer((req, res) => { + const url = new URL(req.url || "/", "http://localhost"); + if (req.method === "GET" && url.pathname === "/health") { + res.writeHead(200).end("ok"); + return; + } + if (req.method === "GET" && url.pathname === "/regions") { + res.setHeader("Content-Type", "application/json"); + res.end( + JSON.stringify([ + { id: "us-east-1", status: "available" }, + { id: "eu-central-1", status: "available" }, + ]) + ); + return; + } + if (req.method === "POST" && url.pathname === "/create") { + let body = ""; + req.on("data", (c) => (body += c)); + req.on("end", () => { + res.setHeader("Content-Type", "application/json"); + res.end( + JSON.stringify({ + data: { + id: "proj_123", + database: { + name: "db1", + region: { id: "us-east-1" }, + connectionString: "postgresql://prisma", + apiKeys: [ + { + directConnection: { + user: "u", + pass: "p", + host: "localhost", + port: 5432, + database: "postgres", + }, + }, + ], + }, + }, + }) + ); + }); + return; + } + if (req.method === "POST" && url.pathname === "/analytics") { + res.writeHead(204).end(); + return; + } + res.writeHead(404).end(); + }); + await new Promise((r) => server.listen(0, r)); + const { port } = server.address(); + baseUrl = `http://127.0.0.1:${port}`; +}); + +afterAll(async () => { + await new Promise((r) => server.close(r)); + for (const file of wrappers) { + try { + fs.unlinkSync(file); + } catch {} + } +}); + +describe("database creation", () => { + ["create-db", "create-postgres", "create-pg"].forEach((command) => { + it( + `creates database with ${command}`, + async () => { + const script = createWrapper(command); + const { stdout, stderr, exitCode } = await runCli( + script, + ["-r", "us-east-1"], + { + CREATE_DB_WORKER_URL: baseUrl, + CLAIM_DB_WORKER_URL: baseUrl, + } + ); + // Useful for debugging on CI failures. + // console.log({ exitCode, stdout, stderr }); + expect(stdout).toContain("Database created successfully!"); + expect(exitCode).toBe(0); + }, + 20000 + ); + }); +});
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
.github/workflows/tests.yml
(1 hunks)claim-db-worker/__tests__/callback-api.test.ts
(1 hunks)claim-db-worker/__tests__/claim.test.tsx
(1 hunks)claim-db-worker/__tests__/success.test.tsx
(1 hunks)claim-db-worker/package.json
(2 hunks)claim-db-worker/tsconfig.json
(2 hunks)claim-db-worker/vitest-setup.ts
(1 hunks)claim-db-worker/vitest.config.mts
(1 hunks)create-db/__tests__/create.test.js
(1 hunks)create-db/__tests__/regions.test.js
(1 hunks)create-db/__tests__/utils.test.js
(1 hunks)create-db/index.js
(2 hunks)create-db/package.json
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
create-db/__tests__/create.test.js (1)
create-db/index.js (1)
args
(212-212)
create-db/__tests__/regions.test.js (1)
create-db/index.js (8)
validateRegion
(352-370)regions
(109-109)regions
(179-179)regions
(342-342)regions
(353-353)regions
(388-388)getRegions
(325-350)getRegionClosestToLocation
(76-105)
claim-db-worker/__tests__/success.test.tsx (1)
claim-db-worker/app/success/page.tsx (1)
SuccessPage
(77-83)
create-db/__tests__/utils.test.js (1)
create-db/index.js (1)
getCommandName
(142-147)
claim-db-worker/__tests__/claim.test.tsx (1)
claim-db-worker/app/claim/page.tsx (1)
ClaimPage
(89-95)
claim-db-worker/__tests__/callback-api.test.ts (3)
claim-db-worker/lib/auth-utils.ts (2)
exchangeCodeForToken
(7-33)validateProject
(35-57)claim-db-worker/lib/project-transfer.ts (1)
transferProject
(4-36)claim-db-worker/lib/response-utils.ts (2)
redirectToSuccess
(27-38)redirectToError
(8-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: claim-db-worker
- GitHub Check: Workers Builds: create-db-worker
🔇 Additional comments (1)
claim-db-worker/vitest.config.mts (1)
4-15
: Vitest config looks solidjsdom + globals + setup file and tsconfig paths are appropriate for these tests.
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr58
npx create-pg@pr58
npx create-postgres@$pr58 Worker URLs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (4)
claim-db-worker/tsconfig.json (1)
24-24
: Move Node typings to a test-only tsconfig to avoid leaking Node APIs into app code.Including
"node"
in the maintypes
can mask accidental Node API usage in edge/worker/client code. Keep app tsconfig lean and add a Vitest-only tsconfig with Node + Vitest globals.Apply this minimal diff here:
- "types": ["./cloudflare-env.d.ts", "node"] + "types": ["./cloudflare-env.d.ts"]Add a test-only tsconfig:
// claim-db-worker/tsconfig.vitest.json { "extends": "./tsconfig.json", "compilerOptions": { "types": ["vitest/globals", "node"] } }Then point Vitest to it (ensure this already aligns with your setup):
// claim-db-worker/vitest.config.mts export default defineConfig({ test: { environment: "jsdom", globals: true, setupFiles: "./vitest-setup.ts", + typecheck: { + tsconfig: "./tsconfig.vitest.json" + } }, });claim-db-worker/__tests__/claim.test.tsx (3)
7-9
: Fix typo in comment.
"funtioning" → "functioning".-// so long as the Management API is funtioning properly, this should be as well. +// so long as the Management API is functioning properly, this should be as well.
11-18
: Restore global mocks after tests to prevent leakage.
Capture originals and restore inafterAll
.const mockFetch = vi.fn(); -global.fetch = mockFetch; +const originalFetch = global.fetch; +global.fetch = mockFetch as any; const mockWindowOpen = vi.fn(); -Object.defineProperty(window, "open", { - writable: true, - value: mockWindowOpen, -}); +const originalWindowOpen = window.open; +Object.defineProperty(window, "open", { writable: true, value: mockWindowOpen }); + +afterAll(() => { + global.fetch = originalFetch as any; + Object.defineProperty(window, "open", { writable: true, value: originalWindowOpen }); +});
25-36
: Recreate URLSearchParams per test to avoid shared state across specs.
Initialize insidebeforeEach
.describe("claim page", () => { - const mockSearchParams = new URLSearchParams(); + let mockSearchParams: URLSearchParams; const mockPush = vi.fn(); beforeEach(() => { vi.clearAllMocks(); - vi.mocked(useSearchParams).mockReturnValue(mockSearchParams as any); + mockSearchParams = new URLSearchParams(); + vi.mocked(useSearchParams).mockReturnValue(mockSearchParams as any); vi.mocked(useRouter).mockReturnValue({ push: mockPush, } as any);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
.github/workflows/tests.yml
(1 hunks)claim-db-worker/__tests__/claim.test.tsx
(1 hunks)claim-db-worker/tsconfig.json
(1 hunks)create-db/__tests__/utils.test.js
(1 hunks)create-db/package.json
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
create-db/__tests__/utils.test.js (1)
create-db/index.js (1)
getCommandName
(142-147)
claim-db-worker/__tests__/claim.test.tsx (1)
claim-db-worker/app/claim/page.tsx (1)
ClaimPage
(89-95)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: claim-db-worker
- GitHub Check: Workers Builds: create-db-worker
🔇 Additional comments (3)
create-db/package.json (1)
50-53
: Good catch adding execa for tests.
execa
in devDependencies unblocks CLI spawn tests and matches Node 20 in CI.create-db/__tests__/utils.test.js (1)
1-3
: LGTM — tests isolate getCommandName and restore process.argv; verify ESM main-guard
The test isolates getCommandName and restores process.argv correctly. Verification script returned no output; confirm create-db/index.js exists and contains an import.meta.url-based main guard (or equivalent) so importing it in tests doesn't execute CLI code..github/workflows/tests.yml (1)
30-37
: No action required — workspace root lockfile is present.Repository has pnpm-workspace.yaml and a root pnpm-lock.yaml, so running
pnpm install --frozen-lockfile
from./claim-db-worker
and./create-db
will use the workspace lockfile and should not fail. See .github/workflows/tests.yml install steps.Likely an incorrect or invalid review comment.
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr58
npx create-pg@pr58
npx create-postgres@$pr58 Worker URLs
|
Summary by CodeRabbit
New Features
Tests
Chores