Skip to content

Commit

Permalink
feat: fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
whilefoo committed Jun 24, 2024
1 parent 7e51e56 commit 2b150a1
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 29 deletions.
Binary file modified bun.lockb
Binary file not shown.
19 changes: 19 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// jest.config.js
/** @type {import('jest').Config} */
module.exports = {
testEnvironment: "node",
roots: ["./tests"],
coveragePathIgnorePatterns: ["node_modules", "mocks"],
collectCoverage: true,
coverageReporters: ["json", "lcov", "text", "clover", "json-summary"],
reporters: ["default", "jest-junit"],
coverageDirectory: "coverage",
verbose: true,
transformIgnorePatterns: [],
transform: {
"^.+\\.[j|t]s$": "@swc/jest",
},
moduleNameMapper: {
"@octokit/webhooks-methods": "<rootDir>/node_modules/@octokit/webhooks-methods/dist-node/index.js",
},
};
10 changes: 0 additions & 10 deletions jest.config.json

This file was deleted.

17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
"proxy": "tsx src/proxy.ts",
"knip": "knip --config .github/knip.ts",
"knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts",
"test": "jest test",
"test": "jest --coverage",
"plugin:hello-world": "tsx tests/__mocks__/hello-world-plugin.ts",
"setup-kv": "bun --env-file=.dev.vars deploy/setup_kv_namespace.ts"
"setup-kv": "bun --env-file=.dev.vars deploy/setup_kv_namespace.ts",
"sdk:build": "tsup src/sdk/index.ts --format cjs,esm"
},
"keywords": [
"typescript",
Expand All @@ -43,6 +44,7 @@
"@octokit/plugin-throttling": "^9.3.0",
"@octokit/types": "^13.5.0",
"@octokit/webhooks": "^13.2.7",
"@octokit/webhooks-methods": "^5.1.0",
"@octokit/webhooks-types": "^7.5.1",
"@sinclair/typebox": "^0.32.5",
"dotenv": "^16.4.4",
Expand All @@ -52,6 +54,10 @@
"yaml": "^2.4.1"
},
"devDependencies": {
"@swc/core": "^1.6.5",
"@swc/jest": "^0.2.36",
"tsup": "^8.1.0",
"esbuild-jest": "^0.5.0",
"@jest/globals": "^29.7.0",
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
Expand All @@ -70,7 +76,7 @@
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
"cspell": "^8.4.0",
"esbuild": "^0.20.1",
"esbuild": "^0.21.5",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
Expand All @@ -83,7 +89,7 @@
"toml": "3.0.0",
"tomlify-j0.4": "3.0.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"typescript": "~5.5.0",
"wrangler": "3.58.0"
},
"lint-staged": {
Expand All @@ -99,6 +105,5 @@
"extends": [
"@commitlint/config-conventional"
]
},
"packageManager": "bun@1.1.0"
}
}
4 changes: 2 additions & 2 deletions src/sdk/context.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks";
import { Octokit } from "@octokit/rest";
import { customOctokit } from "./octokit";

export interface Context<TConfig = unknown, TEnv = unknown, TSupportedEvents extends WebhookEventName = WebhookEventName> {
eventName: TSupportedEvents;
payload: {
[K in TSupportedEvents]: K extends WebhookEventName ? WebhookEvent<K> : never;
}[TSupportedEvents]["payload"];
octokit: InstanceType<typeof Octokit>;
octokit: InstanceType<typeof customOctokit>;
config: TConfig;
env: TEnv;
logger: {
Expand Down
27 changes: 27 additions & 0 deletions src/sdk/octokit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Octokit } from "@octokit/core";
import { RequestOptions } from "@octokit/types";
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
import { retry } from "@octokit/plugin-retry";
import { throttling } from "@octokit/plugin-throttling";

const defaultOptions = {
throttle: {
onAbuseLimit: (retryAfter: number, options: RequestOptions, octokit: Octokit) => {
octokit.log.warn(`Abuse limit hit with "${options.method} ${options.url}", retrying in ${retryAfter} seconds.`);
return true;
},
onRateLimit: (retryAfter: number, options: RequestOptions, octokit: Octokit) => {
octokit.log.warn(`Rate limit hit with "${options.method} ${options.url}", retrying in ${retryAfter} seconds.`);
return true;
},
onSecondaryRateLimit: (retryAfter: number, options: RequestOptions, octokit: Octokit) => {
octokit.log.warn(`Secondary rate limit hit with "${options.method} ${options.url}", retrying in ${retryAfter} seconds.`);
return true;
},
},
};

export const customOctokit = Octokit.plugin(throttling, retry, paginateRest, restEndpointMethods).defaults((instanceOptions: object) => {
return Object.assign({}, defaultOptions, instanceOptions);
});
11 changes: 8 additions & 3 deletions src/sdk/server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";
import { Context } from "./context";
import { customOctokit } from "../github/github-client";
import { customOctokit } from "./octokit";
import { EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks";
import { verifySignature } from "./signature";
import { UBIQUIBOT_KERNEL_PUBLIC_KEY } from "./constants";
Expand Down Expand Up @@ -32,10 +32,16 @@ export async function createPlugin<TConfig = unknown, TEnv = unknown, TSupported
const signature = payload.signature;
delete payload.signature;
if (!(await verifySignature(options?.ubiquibotKernelPublicKey || UBIQUIBOT_KERNEL_PUBLIC_KEY, payload, signature))) {
console.error("Invalid signature");
throw new HTTPException(400, { message: "Invalid signature" });
}

try {
new customOctokit({ auth: payload.authToken });
} catch (error) {
console.error("SDK ERROR", error);
throw new HTTPException(500, { message: "Unexpected error" });
}

const context: Context<TConfig, TEnv, TSupportedEvents> = {
eventName: payload.eventName,
payload: payload.payload,
Expand All @@ -52,7 +58,6 @@ export async function createPlugin<TConfig = unknown, TEnv = unknown, TSupported
};

try {
console.log("CALLING HANDLER");
const result = await handler(context);
return ctx.json({ stateId: payload.stateId, output: result });
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion src/sdk/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export async function verifySignature(publicKeyPem: string, payload: unknown, si

const publicKey = await crypto.subtle.importKey(
"spki",
binaryDer.buffer,
binaryDer,
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
Expand Down
3 changes: 3 additions & 0 deletions src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default {
pluginChainState: new CloudflareKV(env.PLUGIN_CHAIN_STATE),
});
bindHandlers(eventHandler);
console.log("CALLING verifyAndReceive");
await eventHandler.webhooks.verifyAndReceive({ id, name: eventName, payload: await request.text(), signature: signatureSHA256 });
return new Response("ok\n", { status: 200, headers: { "content-type": "text/plain" } });
} catch (error) {
Expand All @@ -36,6 +37,8 @@ function handleUncaughtError(error: unknown) {
const err = error.errors[0];
errorMessage = err.message ? `${err.name}: ${err.message}` : `Error: ${errorMessage}`;
status = typeof err.status !== "undefined" ? err.status : 500;
} else {
errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : `Error: ${error}`;
}
return new Response(JSON.stringify({ error: errorMessage }), { status: status, headers: { "content-type": "application/json" } });
}
Expand Down
1 change: 1 addition & 0 deletions tests/__mocks__/webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export class WebhooksMocked {
constructor(_: unknown) {}
verifyAndReceive(_: unknown) {
console.log("verifyAndReceive");
return Promise.resolve();
}
onAny(_: unknown) {}
Expand Down
4 changes: 2 additions & 2 deletions tests/configuration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterAll, afterEach, beforeAll, describe, expect, it, mock } from "bun:test";
import { afterAll, afterEach, beforeAll, describe, expect, it, jest } from "@jest/globals";
import { config } from "dotenv";
import { server } from "./__mocks__/node";
import { WebhooksMocked } from "./__mocks__/webhooks";
Expand All @@ -8,7 +8,7 @@ import { GitHubEventHandler } from "../src/github/github-event-handler";

config({ path: ".dev.vars" });

void mock.module("@octokit/webhooks", () => ({
void jest.mock("@octokit/webhooks", () => ({
Webhooks: WebhooksMocked,
}));

Expand Down
6 changes: 3 additions & 3 deletions tests/events.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods";
import { afterAll, afterEach, beforeAll, describe, expect, it, mock, spyOn } from "bun:test";
import { afterAll, afterEach, beforeAll, describe, expect, it, jest } from "@jest/globals";
import { config } from "dotenv";
import { GitHubContext } from "../src/github/github-context";
import { GitHubEventHandler } from "../src/github/github-event-handler";
import issueCommentCreated from "../src/github/handlers/issue-comment-created";
import { server } from "./__mocks__/node";
import { WebhooksMocked } from "./__mocks__/webhooks";

void mock.module("@octokit/webhooks", () => ({
void jest.mock("@octokit/webhooks", () => ({
Webhooks: WebhooksMocked,
}));

Expand All @@ -30,7 +30,7 @@ describe("Event related tests", () => {
return params;
},
};
const spy = spyOn(issues, "createComment");
const spy = jest.spyOn(issues, "createComment");
await issueCommentCreated({
id: "",
key: "issue_comment.created",
Expand Down
1 change: 1 addition & 0 deletions tests/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe("Worker tests", () => {
PRIVATE_KEY: "private-key",
PLUGIN_CHAIN_STATE: {} as KVNamespace,
});
expect(await res.text()).toEqual("ok\n");
expect(res.status).toEqual(200);
});

Expand Down
2 changes: 1 addition & 1 deletion tests/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe("SDK tests", () => {
const data = {
...issueCommented,
stateId: "stateId",
authToken: process.env.GITHUB_TOKEN,
authToken: "test",
settings: {
shouldFail: false,
},
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": ["@cloudflare/workers-types/2023-07-01", "bun"] /* Specify type package names to be included without being referenced in a source file. */,
"types": ["@cloudflare/workers-types/2023-07-01"] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
Expand Down
9 changes: 9 additions & 0 deletions tsup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from "tsup";

export default defineConfig({
entry: ["src/sdk/index.ts"],
splitting: false,
sourcemap: true,
clean: true,
dts: true,
});

0 comments on commit 2b150a1

Please sign in to comment.