Skip to content

Commit

Permalink
test: add some simple test
Browse files Browse the repository at this point in the history
  • Loading branch information
oustn committed Nov 15, 2024
1 parent 5cbcf3a commit fa4c452
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 36 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Test
on:
push:
branches:
- main
- dev

jobs:
test:
if: github.repository == 'oustn/cloudflare-bark-server'
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run test
run: npm run test
61 changes: 61 additions & 0 deletions tests/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { createExecutionContext, waitOnExecutionContext, SELF } from 'cloudflare:test';
import { describe, it, expect, vi } from 'vitest';
import worker from '../src/index';
import { env, serverlessEnv } from "./helpers/env"
import * as middleware from "../src/middlewares"

const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;

describe('Basic info routes', () => {
// 1. test info endpoint
it('ping (unit style)', async () => {
const dbMiddlewareSpy = vi.spyOn(middleware, 'dbMiddleware');
const request = new IncomingRequest('https://example.com/ping');
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
expect(dbMiddlewareSpy).not.toHaveBeenCalled();
expect(await response.json()).toMatchObject({ message: 'pong' });
});

it('ping (integration style)', async () => {
const response = await SELF.fetch('https://example.com/ping');
expect(await response.json()).toMatchObject({ message: 'pong' });
});

// 2. test healthz endpoint
it('responds with ok (unit style)', async () => {
const request = new IncomingRequest('https://example.com/healthz');
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
expect(await response.text()).toBe('ok');
});

it('responds with ok (integration style)', async () => {
const response = await SELF.fetch('https://example.com/healthz');
expect(await response.text()).toBe('ok');
});

// 3. test info endpoint
it('responds with info (unit style)', async () => {
const request = new IncomingRequest('https://example.com/info');
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
expect(await response.json()).toMatchObject({ serverless: false });
});

it('responds with serverless info (unit style)', async () => {
const request = new IncomingRequest('https://example.com/info');
const ctx = createExecutionContext();
const response = await worker.fetch(request, serverlessEnv, ctx);
await waitOnExecutionContext(ctx);
expect(await response.json()).toMatchObject({ serverless: true });
})

it('responds with info (integration style)', async () => {
const response = await SELF.fetch('https://example.com/info');
expect(await response.json()).toMatchObject({ serverless: false });
});
});
5 changes: 5 additions & 0 deletions tests/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module "cloudflare:test" {
interface ProvidedEnv {
DB: D1Database;
}
}
8 changes: 8 additions & 0 deletions tests/helpers/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const env = {
DB: true
}

export const serverlessEnv = {
KEY: "key",
DEVICE_TOKEN: "token"
}
37 changes: 3 additions & 34 deletions tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,21 @@ import { env, createExecutionContext, waitOnExecutionContext, SELF } from 'cloud
import { describe, it, expect } from 'vitest';
import worker from '../src/index';

// For now, you'll need to do something like this to get a correctly-typed
// `Request` to pass to `worker.fetch()`.
const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;

const swaggerUI = `"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content="SwaggerIU"/>
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui.css" integrity="sha256-QBcPDuhZ0X+SExunBzKaiKBw5PZodNETZemnfSMvYRc=" crossorigin="anonymous">
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlMb//2ux//9or///ZKz//wlv5f8JcOf/CnXv/why7/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2vi/wZo3/9ytf//b7P//2uw//+BvP//DHbp/w568P8Md+//CnXv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApv4/8HbOH/lMf//3W3//9ytf//brL//w946v8SfvH/EHzw/w558P8AAAAAAAAAAAAAAAAAAAAAAAAAABF56f8Ndef/C3Dj/whs4f98u///eLn//3W3//+Evv//FoPx/xSA8f8SfvD/EHvw/wAAAAAAAAAAAAAAAA1EeF0WgOz/EXrp/w515v8LceT/lsn//3+9//97u///eLj//xaB7f8YhfL/FoLx/xSA8f8JP/deAAAAAAAAAAAgjfH/HIjw/xeB7P8Te+n/AAAAAAAAAACGwf//gr///369//+Iwf//HIny/xqH8v8YhfL/FYLx/wAAAAAnlfPlJJLy/yGO8v8cifD/GILt/wAAAAAAAAAAmMz//4nD//+Fwf//gb///xyJ8P8ejPP/HIny/xmH8v8XhPLnK5r0/yiW8/8lk/P/IpDy/wAAAAAAAAAAAAAAAAAAAACPx///jMX//4jD//+MxP//IpD0/yCO8/8di/P/G4ny/y6e9f8sm/T/KZj0/yaV8/8AAAAAAAAAAAAAAAAAAAAAlsz//5LJ//+Px///lMn//yaV9P8kkvT/IZD0/x+O8/8yo/blMKD1/y2d9f8qmfT/KJbz/wAAAAAAAAAAqdb//53Q//+Zzv//lsv//yiY8/8qmvX/KJf1/yWV9P8jkvTQAAAAADSl9v8xofX/Lp71/yyb9P8AAAAAAAAAAKfW//+k1P//oNL//6rW//8wofb/Lp72/yuc9f8pmfX/AAAAAAAAAAAcVHtcNab2/zKj9v8voPX/LZz0/7vh//+u2///qtj//6fW//8wofT/NKX3/zKj9/8voPb/F8/6XgAAAAAAAAAAAAAAADmr9/82qPf/M6T2/zCg9f+44f//td///7Hd//++4v//Oqz4/ziq+P81p/f/M6X3/wAAAAAAAAAAAAAAAAAAAAAAAAAAOqz4/zep9//M6///v+X//7vj//+44f//OKn1/z6x+f88rvn/Oaz4/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6x+f8qmfP/yOv//8bq///C5///z+z//0O3+v9Ctfr/QLP5/z2x+f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0u///8jr///I6///yOv//zmq9f9Dt/r/Q7f6/0O3+v8AAAAAAAAAAAAAAAAAAAAA8A8AAOAHAADgBwAAwAMAAMADAACGAQAABgAAAA8AAAAPAAAABgAAAIYBAADAAwAAwAMAAOAHAADgBwAA8A8AAA==" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui-bundle.js" integrity="sha256-wuSp7wgUSDn/R8FCAgY+z+TlnnCk5xVKJr1Q2IDIi6E=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui-standalone-preset.js" integrity="sha256-M7em9a/KxJAv35MoG+LS4S2xXyQdOEYG5ubRd0W3+G8=" crossorigin="anonymous"></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '/openapi.json',
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis
]
});
};
</script>
</body>
</html>"`

describe('Bark worker', () => {
it('responds with swagger doc (unit style)', async () => {
const request = new IncomingRequest('http://example.com');
const request = new IncomingRequest('https://example.com');
// Create an empty context to pass to `worker.fetch()`.
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
// Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
await waitOnExecutionContext(ctx);
expect(await response.text()).toMatchInlineSnapshot(swaggerUI);
expect(response.status).toBe(404)
});

it('responds with swagger doc (integration style)', async () => {
const response = await SELF.fetch('https://example.com');
expect(await response.text()).toMatchInlineSnapshot(swaggerUI);
expect(response.status).toBe(404)
});
});
2 changes: 1 addition & 1 deletion tests/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"compilerOptions": {
"types": ["@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers"]
},
"include": ["./**/*.ts", "../src/env.d.ts"],
"include": ["./**/*.ts", "../src/env.d.ts", "./env.d.ts"],
"exclude": []
}
7 changes: 6 additions & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.toml" },
wrangler: { configPath: "./wrangler.test.toml" },
miniflare: {
d1Databases: {
DB: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
},
},
},
},
Expand Down
121 changes: 121 additions & 0 deletions wrangler.test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#:schema node_modules/wrangler/config-schema.json
name = "cloudflare-bark-server"
main = "src/index.ts"
compatibility_date = "2024-11-06"
compatibility_flags = ["nodejs_compat"]

# 自定义域名
# route = { pattern = "bark.example.com", custom_domain = true }

# Workers Logs
# Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
# Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
[observability]
enabled = true

# Automatically place your workloads in an optimal location to minimize latency.
# If you are running back-end logic in a Worker, running it closer to your back-end infrastructure
# rather than the end user may result in better performance.
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"

# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
# Docs:
# - https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# Note: Use secrets to store sensitive data.
# - https://developers.cloudflare.com/workers/configuration/secrets/
# [vars]
# 是否保存发送的消息
# PERSIST = true

# Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare’s global network
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai
# [ai]
# binding = "AI"

# Bind an Analytics Engine dataset. Use Analytics Engine to write analytics within your Pages Function.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets
# [[analytics_engine_datasets]]
# binding = "MY_DATASET"

# Bind a headless browser instance running on Cloudflare's global network.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering
# [browser]
# binding = "MY_BROWSER"

# Bind a D1 database. D1 is Cloudflare’s native serverless SQL database.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases
# [[d1_databases]]
# binding = "DB"
# 自定义数据库名称
# database_name = "bark"
# 数据库 ID
# database_id = "64148f6c-4e9c-4089-b78a-03ba6914c760"
# migrations_dir = "src/migrations"

# Bind a dispatch namespace. Use Workers for Platforms to deploy serverless functions programmatically on behalf of your customers.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms
# [[dispatch_namespaces]]
# binding = "MY_DISPATCHER"
# namespace = "my-namespace"

# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
# [[durable_objects.bindings]]
# name = "MY_DURABLE_OBJECT"
# class_name = "MyDurableObject"

# Durable Object migrations.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
# [[migrations]]
# tag = "v1"
# new_classes = ["MyDurableObject"]

# Bind a Hyperdrive configuration. Use to accelerate access to your existing databases from Cloudflare Workers.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive
# [[hyperdrive]]
# binding = "MY_HYPERDRIVE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Bind an mTLS certificate. Use to present a client certificate when communicating with another service.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates
# [[mtls_certificates]]
# binding = "MY_CERTIFICATE"
# certificate_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
# [[queues.producers]]
# binding = "MY_QUEUE"
# queue = "my-queue"

# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
# [[queues.consumers]]
# queue = "my-queue"

# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets
# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"

# Bind another Worker service. Use this binding to call another Worker without network overhead.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"

# Bind a Vectorize index. Use to store and query vector embeddings for semantic search, classification and other vector search use-cases.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes
# [[vectorize]]
# binding = "MY_INDEX"
# index_name = "my-index"

0 comments on commit fa4c452

Please sign in to comment.