Skip to content

Commit 952373e

Browse files
authored
test(cloudflare): Add test for hono cloudflare (#16360)
Adding a test to check that the build and types work (just like with cloudflare-wokers).
1 parent 48f1a4f commit 952373e

File tree

9 files changed

+190
-0
lines changed

9 files changed

+190
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "cloudflare-hono",
3+
"scripts": {
4+
"dev": "wrangler dev",
5+
"build": "wrangler deploy --dry-run --var E2E_TEST_DSN=$E2E_TEST_DSN",
6+
"test": "vitest",
7+
"typecheck": "tsc --noEmit",
8+
"cf-typegen": "wrangler types --env-interface CloudflareBindings",
9+
"test:build": "pnpm install && pnpm build",
10+
"//": "Just checking if it builds correctly and types don't break",
11+
"test:assert": "pnpm typecheck"
12+
},
13+
"dependencies": {
14+
"@sentry/cloudflare": "latest || *",
15+
"hono": "4.7.10"
16+
},
17+
"devDependencies": {
18+
"@cloudflare/vitest-pool-workers": "^0.8.31",
19+
"@cloudflare/workers-types": "^4.20250521.0",
20+
"vitest": "3.1.0",
21+
"wrangler": "^4.16.0"
22+
},
23+
"volta": {
24+
"extends": "../../package.json"
25+
},
26+
"sentryTest": {
27+
"optional": true
28+
}
29+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Generated by Wrangler on Mon Jul 29 2024 21:44:31 GMT-0400 (Eastern Daylight Time)
2+
// by running `wrangler types`
3+
4+
interface Env {
5+
E2E_TEST_DSN: '';
6+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Hono } from 'hono';
2+
import * as Sentry from '@sentry/cloudflare';
3+
4+
const app = new Hono();
5+
6+
app.get('/', ctx => {
7+
return ctx.json({ message: 'Welcome to Hono API' });
8+
});
9+
10+
app.get('/hello/:name', ctx => {
11+
const name = ctx.req.param('name');
12+
return ctx.json({ message: `Hello, ${name}!` });
13+
});
14+
15+
app.get('/error', () => {
16+
throw new Error('This is a test error');
17+
});
18+
19+
app.onError((err, ctx) => {
20+
console.error(`Error occured: ${err.message}`);
21+
return ctx.json({ error: err.message }, 500);
22+
});
23+
24+
app.notFound(ctx => {
25+
return ctx.json({ message: 'Not Found' }, 404);
26+
});
27+
28+
export default Sentry.withSentry(
29+
(env: Env) => ({
30+
dsn: env?.E2E_TEST_DSN,
31+
tracesSampleRate: 1.0,
32+
}),
33+
app,
34+
);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare module 'cloudflare:test' {
2+
// ProvidedEnv controls the type of `import("cloudflare:test").env`
3+
interface ProvidedEnv extends Env {}
4+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { describe, expect, it } from 'vitest';
2+
import app from '../src/index';
3+
import { SELF, createExecutionContext, env, waitOnExecutionContext } from 'cloudflare:test';
4+
5+
describe('Hono app on Cloudflare Workers', () => {
6+
describe('Unit Tests', () => {
7+
it('should return welcome message', async () => {
8+
const res = await app.request('/', {}, env);
9+
expect(res.status).toBe(200);
10+
const data = await res.json();
11+
expect(data).toEqual({ message: 'Welcome to Hono API' });
12+
});
13+
14+
it('should greet a user with their name', async () => {
15+
const res = await app.request('/hello/tester', {}, env);
16+
expect(res.status).toBe(200);
17+
const data = await res.json();
18+
expect(data).toEqual({ message: 'Hello, tester!' });
19+
});
20+
21+
it('should handle errors with custom error handler', async () => {
22+
const res = await app.request('/error', {}, env);
23+
expect(res.status).toBe(500);
24+
const data = await res.json();
25+
expect(data).toHaveProperty('error', 'This is a test error');
26+
});
27+
28+
it('should handle 404 with custom not found handler', async () => {
29+
const res = await app.request('/non-existent-route', {}, env);
30+
expect(res.status).toBe(404);
31+
const data = await res.json();
32+
expect(data).toEqual({ message: 'Not Found' });
33+
});
34+
});
35+
36+
// Integration test style with worker.fetch
37+
describe('Integration Tests', () => {
38+
it('should fetch the root endpoint', async () => {
39+
// Create request and context
40+
const request = new Request('http://localhost/');
41+
const ctx = createExecutionContext();
42+
43+
const response = await app.fetch(request, env, ctx);
44+
45+
await waitOnExecutionContext(ctx);
46+
47+
expect(response.status).toBe(200);
48+
const data = await response.json();
49+
expect(data).toEqual({ message: 'Welcome to Hono API' });
50+
});
51+
52+
it('should handle a parameter route', async () => {
53+
// Create request and context
54+
const request = new Request('http://localhost/hello/cloudflare');
55+
const ctx = createExecutionContext();
56+
57+
const response = await app.fetch(request, env, ctx);
58+
59+
await waitOnExecutionContext(ctx);
60+
61+
expect(response.status).toBe(200);
62+
const data = await response.json();
63+
expect(data).toEqual({ message: 'Hello, cloudflare!' });
64+
});
65+
66+
it('should handle errors gracefully', async () => {
67+
const response = await SELF.fetch('http://localhost/error');
68+
69+
expect(response.status).toBe(500);
70+
const data = await response.json();
71+
expect(data).toHaveProperty('error', 'This is a test error');
72+
});
73+
});
74+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"types": ["@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers"]
5+
},
6+
"include": ["./**/*.ts", "../src/env.d.ts"],
7+
"exclude": []
8+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ESNext",
4+
"module": "ESNext",
5+
"moduleResolution": "Bundler",
6+
"strict": true,
7+
"skipLibCheck": true,
8+
"lib": [
9+
"ESNext"
10+
],
11+
"jsx": "react-jsx",
12+
"jsxImportSource": "hono/jsx"
13+
},
14+
"include": ["src/**/*"],
15+
"exclude": ["test", "node_modules"]
16+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config'
2+
3+
export default defineWorkersProject(() => {
4+
return {
5+
test: {
6+
globals: true,
7+
poolOptions: {
8+
workers: { wrangler: { configPath: './wrangler.toml' } },
9+
},
10+
},
11+
}
12+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name = "cloudflare-hono"
2+
main = "src/index.ts"
3+
compatibility_date = "2023-10-30"
4+
compatibility_flags = ["nodejs_compat"]
5+
6+
# [vars]
7+
# E2E_TEST_DSN = ""

0 commit comments

Comments
 (0)