mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
chore: add typecheck script and fix pre-existing TypeScript errors
- Add `typecheck` script (`tsc --noEmit`) to package.json - Remove conflicting `declare global` from test/setup.ts (superseded by @cloudflare/workers-types); use `globalThis as any` for test globals and declare minimal `require` locally to avoid pulling in @types/node - Cast `createMockEnv()` and `deleteRes.json()` results in admin.test.ts to silence strict `unknown` / MockKV-vs-KVNamespace errors Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -10,7 +10,8 @@
|
|||||||
"deploy": "wrangler deploy --env production",
|
"deploy": "wrangler deploy --env production",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"test:coverage": "vitest run --coverage"
|
"test:coverage": "vitest run --coverage",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ describe("Admin Routes", () => {
|
|||||||
let loginAndGetCookie: () => Promise<string>;
|
let loginAndGetCookie: () => Promise<string>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockEnv = createMockEnv();
|
mockEnv = createMockEnv() as unknown as Env;
|
||||||
testApp = new Hono();
|
testApp = new Hono();
|
||||||
testApp.route("/admin", app);
|
testApp.route("/admin", app);
|
||||||
request = (path, init = {}) => testApp.request(path, init, mockEnv);
|
request = (path, init = {}) => Promise.resolve(testApp.request(path, init, mockEnv));
|
||||||
loginAndGetCookie = async () => {
|
loginAndGetCookie = async () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("password", "test-password");
|
formData.append("password", "test-password");
|
||||||
@@ -161,8 +161,8 @@ describe("Admin Routes", () => {
|
|||||||
"json",
|
"json",
|
||||||
);
|
);
|
||||||
expect(feedConfig).toBeTruthy();
|
expect(feedConfig).toBeTruthy();
|
||||||
expect(feedConfig.title).toBe("Test Feed");
|
expect((feedConfig as any).title).toBe("Test Feed");
|
||||||
expect(feedConfig.description).toBe("Test Description");
|
expect((feedConfig as any).description).toBe("Test Description");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should reject feed creation with missing title", async () => {
|
it("should reject feed creation with missing title", async () => {
|
||||||
@@ -297,7 +297,7 @@ describe("Admin Routes", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(deleteRes.status).toBe(200);
|
expect(deleteRes.status).toBe(200);
|
||||||
const payload = await deleteRes.json();
|
const payload = (await deleteRes.json()) as any;
|
||||||
expect(payload.ok).toBe(true);
|
expect(payload.ok).toBe(true);
|
||||||
expect(payload.feedId).toBe(feedId);
|
expect(payload.feedId).toBe(feedId);
|
||||||
});
|
});
|
||||||
@@ -419,7 +419,7 @@ describe("Admin Routes", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(deleteRes.status).toBe(200);
|
expect(deleteRes.status).toBe(200);
|
||||||
const payload = await deleteRes.json();
|
const payload = (await deleteRes.json()) as any;
|
||||||
expect(payload.ok).toBe(true);
|
expect(payload.ok).toBe(true);
|
||||||
expect(payload.emailKey).toBe(emailKey);
|
expect(payload.emailKey).toBe(emailKey);
|
||||||
|
|
||||||
|
|||||||
+24
-31
@@ -1,26 +1,10 @@
|
|||||||
import { beforeAll, afterAll, afterEach } from "vitest";
|
import { beforeAll, afterAll, afterEach } from "vitest";
|
||||||
import { setupServer } from "msw/node";
|
import { setupServer } from "msw/node";
|
||||||
|
|
||||||
/**
|
// Minimal Node.js built-ins used only in this test setup file.
|
||||||
* Mock implementation of Cloudflare Workers runtime environment
|
// Declared locally to avoid pulling in the full @types/node package,
|
||||||
* Based on: https://developers.cloudflare.com/workers/testing/
|
// which would conflict with @cloudflare/workers-types globals.
|
||||||
*/
|
declare function require(id: string): any;
|
||||||
|
|
||||||
// Define Cloudflare Workers runtime globals
|
|
||||||
declare global {
|
|
||||||
// CF Worker specific globals
|
|
||||||
var caches: CacheStorage;
|
|
||||||
var crypto: Crypto;
|
|
||||||
var Response: typeof Response;
|
|
||||||
var Request: typeof Request;
|
|
||||||
var URLSearchParams: typeof URLSearchParams;
|
|
||||||
var URL: typeof URL;
|
|
||||||
var Headers: typeof Headers;
|
|
||||||
var FormData: typeof FormData;
|
|
||||||
var Blob: typeof Blob;
|
|
||||||
var atob: (data: string) => string;
|
|
||||||
var btoa: (data: string) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock KV namespace implementation
|
* Mock KV namespace implementation
|
||||||
@@ -122,36 +106,45 @@ beforeAll(() => {
|
|||||||
// Setup MSW server
|
// Setup MSW server
|
||||||
server.listen({ onUnhandledRequest: "error" });
|
server.listen({ onUnhandledRequest: "error" });
|
||||||
|
|
||||||
|
// Type-safe access to Node's global object for setting Workers-like globals in tests
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const g = globalThis as any;
|
||||||
|
|
||||||
// Mock Cloudflare Workers runtime globals
|
// Mock Cloudflare Workers runtime globals
|
||||||
global.caches = {
|
g.caches = {
|
||||||
default: new MockCache(),
|
default: new MockCache(),
|
||||||
open: async () => new MockCache(),
|
open: async () => new MockCache(),
|
||||||
} as unknown as CacheStorage;
|
} as unknown as CacheStorage;
|
||||||
|
|
||||||
// Mock crypto for generating random values
|
// Mock crypto for generating random values
|
||||||
if (!global.crypto) {
|
if (!g.crypto) {
|
||||||
global.crypto = require("crypto").webcrypto;
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
g.crypto = require("crypto").webcrypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure other required globals are available
|
// Ensure other required globals are available
|
||||||
if (!global.FormData) {
|
if (!g.FormData) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const { FormData } = require("undici");
|
const { FormData } = require("undici");
|
||||||
global.FormData = FormData;
|
g.FormData = FormData;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global.Headers) {
|
if (!g.Headers) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const { Headers } = require("undici");
|
const { Headers } = require("undici");
|
||||||
global.Headers = Headers;
|
g.Headers = Headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global.Request) {
|
if (!g.Request) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const { Request } = require("undici");
|
const { Request } = require("undici");
|
||||||
global.Request = Request;
|
g.Request = Request;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global.Response) {
|
if (!g.Response) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const { Response } = require("undici");
|
const { Response } = require("undici");
|
||||||
global.Response = Response;
|
g.Response = Response;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user