74 lines
3.0 KiB
TypeScript
74 lines
3.0 KiB
TypeScript
import { ERROR_CODES } from '@insforge/shared-schemas';
|
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
|
|
// These tests run the real `deno check` (deno binary present in CI/dev). They
|
|
// prove the pre-deploy static check rejects the exact class of error that
|
|
// wedged project 2mn4wunc (issue #1594): a duplicate top-level declaration that
|
|
// builds fine but throws `Identifier '...' has already been declared` at
|
|
// isolate warm-up, surfacing only as the opaque "Event iterator validation
|
|
// failed".
|
|
describe('DenoSubhostingProvider.checkCode (pre-deploy static check)', () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
process.env.DENO_DEPLOY_TOKEN = 't';
|
|
process.env.DENO_DEPLOY_ORG_ID = 'o';
|
|
});
|
|
|
|
afterEach(() => {
|
|
delete process.env.DENO_DEPLOY_TOKEN;
|
|
delete process.env.DENO_DEPLOY_ORG_ID;
|
|
});
|
|
|
|
it('rejects a duplicate top-level declaration with a 400 + the offending identifier', async () => {
|
|
const mod = await import('@/providers/functions/deno-subhosting.provider.js');
|
|
const provider = mod.DenoSubhostingProvider.getInstance();
|
|
|
|
// Reproduces dpo_agent.ts:122 from #1594: KILL_SWITCH_DOC_ID declared twice.
|
|
const code = [
|
|
'const KILL_SWITCH_DOC_ID = "global";',
|
|
'export default function (_req: Request): Response {',
|
|
' return new Response(KILL_SWITCH_DOC_ID);',
|
|
'}',
|
|
'var KILL_SWITCH_DOC_ID = "global";',
|
|
].join('\n');
|
|
|
|
await expect(provider.checkCode(code, 'dpo_agent')).rejects.toMatchObject({
|
|
statusCode: 400,
|
|
code: ERROR_CODES.INVALID_INPUT,
|
|
});
|
|
|
|
// The message must name the identifier AND tell the user how to fix it
|
|
// (rename to another name) — not just surface an opaque compiler error.
|
|
await expect(provider.checkCode(code, 'dpo_agent')).rejects.toThrow(/KILL_SWITCH_DOC_ID/);
|
|
await expect(provider.checkCode(code, 'dpo_agent')).rejects.toThrow(
|
|
/declared more than once.*change one of them to another name/s
|
|
);
|
|
}, 60_000);
|
|
|
|
it('accepts a valid, import-free function', async () => {
|
|
const mod = await import('@/providers/functions/deno-subhosting.provider.js');
|
|
const provider = mod.DenoSubhostingProvider.getInstance();
|
|
|
|
const code = [
|
|
'export default function (_req: Request): Response {',
|
|
' return new Response("ok");',
|
|
'}',
|
|
].join('\n');
|
|
|
|
await expect(provider.checkCode(code, 'ok_fn')).resolves.toBeUndefined();
|
|
}, 60_000);
|
|
|
|
it('is a no-op when Subhosting is not configured (local mode)', async () => {
|
|
delete process.env.DENO_DEPLOY_TOKEN;
|
|
delete process.env.DENO_DEPLOY_ORG_ID;
|
|
const mod = await import('@/providers/functions/deno-subhosting.provider.js');
|
|
const provider = mod.DenoSubhostingProvider.getInstance();
|
|
|
|
// Even syntactically broken code resolves when unconfigured — the check only
|
|
// runs in cloud mode; local dev defers to the runtime.
|
|
await expect(
|
|
provider.checkCode('const x = 1; const x = 2;', 'broken')
|
|
).resolves.toBeUndefined();
|
|
}, 60_000);
|
|
});
|