Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/docs-build-pr.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: PR Build
name: PR Build & Test

on:
pull_request:
Expand All @@ -7,6 +7,7 @@ on:
- "src/**"
- "content/**"
- "scripts/**"
- "test/**"
- "package.json"
- "next.config.ts"
- ".github/workflows/docs-build-pr.yml"
Expand All @@ -32,5 +33,8 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build
run: bun run build
- name: Build (Next + Cloudflare)
run: bun run build:cf

- name: Test
run: bun test
5 changes: 5 additions & 0 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@next/mdx": "^16.0.1",
"@opennextjs/cloudflare": "^1.11.0",
"@tailwindcss/postcss": "^4.1.5",
"@types/bun": "^1.3.3",
"@types/fs-extra": "^11.0.4",
"@types/mdx": "^2.0.13",
"@types/node": "22.14.1",
Expand Down Expand Up @@ -617,6 +618,8 @@

"@tsconfig/node18": ["@tsconfig/[email protected]", "", {}, "sha512-RbwvSJQsuN9TB04AQbGULYfOGE/RnSFk/FLQ5b0NmDf5Kx2q/lABZbHQPKCO1vZ6Fiwkplu+yb9pGdLy1iGseQ=="],

"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],

"@types/debug": ["@types/[email protected]", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],

"@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
Expand Down Expand Up @@ -711,6 +714,8 @@

"buffer-from": ["[email protected]", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],

"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],

"bytes": ["[email protected]", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],

"call-bind": ["[email protected]", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"dev:next": "next dev --turbo -p 8293",
"clear:cache": "tsx scripts/clear-cache.ts",
"start": "next start",
"download:references": "bun scripts/download-references.ts"
"download:references": "bun scripts/download-references.ts",
"test:dev-server": "bun test test/dev-server.test.ts"
},
"dependencies": {
"@radix-ui/react-dialog": "^1.1.11",
Expand Down Expand Up @@ -53,6 +54,7 @@
"@next/mdx": "^16.0.1",
"@opennextjs/cloudflare": "^1.11.0",
"@tailwindcss/postcss": "^4.1.5",
"@types/bun": "^1.3.3",
"@types/fs-extra": "^11.0.4",
"@types/mdx": "^2.0.13",
"@types/node": "22.14.1",
Expand Down
15 changes: 14 additions & 1 deletion scripts/download-references.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { $ } from 'bun';
import { existsSync, mkdirSync } from 'fs';
import { existsSync, mkdirSync, unlinkSync } from 'fs';
import { join } from 'path';

const repositories = [
Expand Down Expand Up @@ -54,6 +54,19 @@ for (const repo of repositories) {
console.error(`✗ Failed to clone ${repo.name}:`, error);
}
}

// Remove test file from react-native repository
if (repo.name === 'react-native') {
const testFilePath = join(repoPath, 'src', '__tests__', 'index.test.tsx');
if (existsSync(testFilePath)) {
try {
unlinkSync(testFilePath);
console.log(`✓ Removed ${testFilePath}`);
} catch (error) {
console.error(`✗ Failed to remove ${testFilePath}:`, error);
}
}
}
}

console.log('\nAll repositories have been processed!');
51 changes: 51 additions & 0 deletions test/cf-preview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// test/cf-preview.test.ts
import { test, expect } from "bun:test";
import { spawn } from "child_process";

const PORT = 8790;
const BASE_URL = `http://127.0.0.1:${PORT}`;

function waitForServer(url: string, timeoutMs = 60000) {
const start = Date.now();
return new Promise<void>((resolve, reject) => {
const tick = async () => {
try {
const res = await fetch(url, { signal: AbortSignal.timeout(2000) });
if (res.ok) return resolve();
} catch {
// ignore
}

if (Date.now() - start > timeoutMs) {
reject(new Error(`CF preview server didn't become ready at ${url}`));
} else {
setTimeout(tick, 500);
}
};
tick();
});
}

test("Cloudflare preview runs and serves /docs/home", async () => {
// Assumes `bun run build:cf` has already run in CI
const server = spawn(
"bunx",
["opennextjs-cloudflare", "preview", "--port", String(PORT)],
{
stdio: "inherit",
}
);

try {
await waitForServer(`${BASE_URL}/docs/home`, 60000);
const res = await fetch(`${BASE_URL}/docs/home`);
expect(res.status).toBe(200);

const html = await res.text();
expect(html).toContain("Superwall");
expect(html).toContain("Welcome");
} finally {
// SIGINT is usually enough to bring down wrangler/preview
server.kill("SIGINT");
}
});
46 changes: 46 additions & 0 deletions test/next-start.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// test/next-start.test.ts
import { test, expect } from "bun:test";
import { spawn } from "child_process";

const PORT = 8293;
const BASE_URL = `http://localhost:${PORT}`;

function waitForServer(url: string, timeoutMs = 20000) {
const start = Date.now();
return new Promise<void>((resolve, reject) => {
const tick = async () => {
try {
const res = await fetch(url, { signal: AbortSignal.timeout(2000) });
if (res.ok) return resolve();
} catch {
// ignore
}

if (Date.now() - start > timeoutMs) {
reject(new Error(`Server didn't become ready at ${url}`));
} else {
setTimeout(tick, 300);
}
};
tick();
});
}

test("next build/start runs and serves /docs/home", async () => {
// Assumes `bun run build` has already run in CI
const server = spawn("bunx", ["next", "start", "-p", String(PORT)], {
stdio: "inherit",
});

try {
await waitForServer(`${BASE_URL}/docs/home`);
const res = await fetch(`${BASE_URL}/docs/home`);
expect(res.status).toBe(200);

const html = await res.text();
expect(html).toContain("Superwall");
expect(html).toContain("Welcome");
} finally {
server.kill("SIGTERM");
}
});
7 changes: 7 additions & 0 deletions test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["bun"]
},
"include": ["**/*.ts", "**/*.tsx"]
}
Loading