Files
heygo/tests/multi-env.test.ts
T
Hermes Agent cca4ea2ec3 fix: use my.dev.heygo.cc for dev private host instead of my.dev.junv.cc
junv.cc is reserved for k3s home services, not Cloudflare apps.
Both dev and prod private hosts now live under heygo.cc, sharing
the .heygo.cc cookie domain — no cross-domain auth issues.
2026-06-20 14:32:12 +10:00

126 lines
4.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import worker from '../worker/index';
import { isHeygoPublicHost } from '../worker/routes/redirect';
import { isHeygoPrivateHost } from '../worker/routes/private-redirect';
// Minimal fake D1 that returns no rows. These tests exercise host routing,
// not link data, so an empty database is sufficient.
class EmptyD1 {
prepare(): { bind(): { first(): Promise<null>; all(): Promise<{ results: never[] }> }; first(): Promise<null>; all(): Promise<{ results: never[] }> } {
const stmt = {
bind() {
return stmt;
},
async first() {
return null;
},
async all() {
return { results: [] as never[] };
},
};
return stmt;
}
}
class FakeExecutionContext {
waitUntil(): void {}
passThroughOnException(): void {}
}
type HostVars = {
PUBLIC_HOST: string;
PRIVATE_HOST: string;
APP_BASE_URL: string;
COOKIE_DOMAIN: string;
};
const PROD_VARS: HostVars = {
PUBLIC_HOST: 'heygo.cc',
PRIVATE_HOST: 'my.heygo.cc',
APP_BASE_URL: 'https://heygo.cc',
COOKIE_DOMAIN: '.heygo.cc',
};
const DEV_VARS: HostVars = {
PUBLIC_HOST: 'dev.heygo.cc',
PRIVATE_HOST: 'my.dev.heygo.cc',
APP_BASE_URL: 'https://dev.heygo.cc',
COOKIE_DOMAIN: '.heygo.cc',
};
async function fetchWorker(url: string, vars: HostVars) {
const env = { DB: new EmptyD1() as unknown as D1Database, ...vars };
const ctx = new FakeExecutionContext();
return worker.fetch(
new Request(url) as unknown as Parameters<typeof worker.fetch>[0],
env as unknown as Parameters<typeof worker.fetch>[1],
ctx as unknown as Parameters<typeof worker.fetch>[2],
);
}
describe('isHeygoPublicHost / isHeygoPrivateHost are env-driven', () => {
it('matches only the configured public host, not the prod default', () => {
expect(isHeygoPublicHost('dev.heygo.cc', 'dev.heygo.cc')).toBe(true);
expect(isHeygoPublicHost('heygo.cc', 'dev.heygo.cc')).toBe(false);
expect(isHeygoPublicHost('heygo.cc', 'heygo.cc')).toBe(true);
});
it('matches only the configured private host', () => {
expect(isHeygoPrivateHost('my.dev.heygo.cc', 'my.dev.heygo.cc')).toBe(true);
expect(isHeygoPrivateHost('my.heygo.cc', 'my.dev.heygo.cc')).toBe(false);
expect(isHeygoPrivateHost('my.heygo.cc', 'my.heygo.cc')).toBe(true);
});
});
describe('worker routing with dev environment vars', () => {
it('treats dev.heygo.cc as the public shortlink host', async () => {
// No rows => unknown alias => public 404 HTML (proves it reached the public route).
const response = await fetchWorker('https://dev.heygo.cc/missing', DEV_VARS);
expect(response.status).toBe(404);
expect(response.headers.get('content-type')).toContain('text/html');
await expect(response.text()).resolves.toContain('Not found');
});
it('does NOT treat heygo.cc as public when dev vars are configured', async () => {
// heygo.cc is not the configured public host, so it falls through to the
// generic JSON 404 instead of the public HTML 404.
const response = await fetchWorker('https://heygo.cc/missing', DEV_VARS);
expect(response.status).toBe(404);
expect(response.headers.get('content-type')).toContain('application/json');
await expect(response.json()).resolves.toEqual({ error: 'Not found' });
});
it('treats my.dev.heygo.cc as the private shortlink host (login prompt, no-store)', async () => {
const response = await fetchWorker('https://my.dev.heygo.cc/foo', DEV_VARS);
expect(response.status).toBe(404);
expect(response.headers.get('content-type')).toContain('text/html');
expect(response.headers.get('cache-control')).toBe('no-store');
const body = await response.text();
// Login link must point at the dev APP_BASE_URL, not the prod one.
expect(body).toContain('https://dev.heygo.cc/app/login');
expect(body).not.toContain('https://heygo.cc/app/login');
});
it('does NOT treat my.heygo.cc as private when dev vars are configured', async () => {
const response = await fetchWorker('https://my.heygo.cc/foo', DEV_VARS);
expect(response.status).toBe(404);
expect(response.headers.get('content-type')).toContain('application/json');
await expect(response.json()).resolves.toEqual({ error: 'Not found' });
});
});
describe('worker routing with prod environment vars', () => {
it('routes heygo.cc to the public handler and my.heygo.cc to the private handler', async () => {
const pub = await fetchWorker('https://heygo.cc/missing', PROD_VARS);
expect(pub.status).toBe(404);
expect(pub.headers.get('content-type')).toContain('text/html');
const priv = await fetchWorker('https://my.heygo.cc/foo', PROD_VARS);
expect(priv.status).toBe(404);
expect(priv.headers.get('content-type')).toContain('text/html');
expect(priv.headers.get('cache-control')).toBe('no-store');
const body = await priv.text();
expect(body).toContain('https://heygo.cc/app/login');
});
});