Files
backspace/packages/server/test/federation-by-home-id.test.ts
T
TheZwiss c7d88481ad test: give federation integration suites a realistic per-test timeout (#7)
The three test/ files boot real federated instances and drive S2S over HTTP,
with several tests deliberately waiting on log matchers (e.g. logMatched(...,
1_000) per remote). Vitest's 5s default per-test timeout is meant for unit tests
and is too tight here: under CI load the multi-remote fan-out tests in
federation-identity-deletion intermittently timed out (observed on the post-merge
main run), producing a flaky red check.

Set a file-level testTimeout of 30s in each of the three harness-based suites via
vi.setConfig. Scoped per-file so unit tests keep the strict 5s default; a genuine
hang still trips the 30s ceiling well before the 90s hook budget. No test logic
changed.
2026-07-10 00:51:18 +02:00

80 lines
3.3 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
import { bootTwoInstances, type TwoInstanceHarness } from './helpers/twoInstanceHarness.js';
import { peerInstances } from './helpers/seedPeer.js';
import { registerLocal } from './helpers/testUsers.js';
import { buildHeadersForOrigin } from './helpers/hmacSign.js';
// Boots real federated instances and drives S2S over HTTP; the 5s unit-test
// default is too tight under CI load. See federation-identity-deletion.test.ts
// for the rationale. A genuine hang still trips this ceiling.
vi.setConfig({ testTimeout: 30_000 });
let harness: TwoInstanceHarness;
let sharedSecret: string;
beforeAll(async () => {
harness = await bootTwoInstances();
sharedSecret = await peerInstances(harness.home, harness.remote);
}, 90_000);
afterAll(async () => {
await harness.cleanup();
});
describe('POST /api/federation/users/by-home-id', () => {
it('returns canonical username + profile for a native user when looked up by homeUserId', async () => {
const target = await registerLocal(harness.remote, 'lookup_target');
const body = JSON.stringify({ homeUserId: target.id });
const headers = buildHeadersForOrigin(body, sharedSecret, `https://${harness.home.domain}`);
const res = await fetch(`${harness.remote.origin}/api/federation/users/by-home-id`, {
method: 'POST',
headers,
body,
});
expect(res.status).toBe(200);
const json = await res.json() as { found: boolean; user?: { homeUserId: string; username: string; profile: { displayName: string | null } } };
expect(json.found).toBe(true);
expect(json.user!.homeUserId).toBe(target.id);
expect(json.user!.username).toBe(target.username);
});
it('returns { found: false } on unknown homeUserId', async () => {
const body = JSON.stringify({ homeUserId: 'definitely-not-a-real-id' });
const headers = buildHeadersForOrigin(body, sharedSecret, `https://${harness.home.domain}`);
const res = await fetch(`${harness.remote.origin}/api/federation/users/by-home-id`, {
method: 'POST',
headers,
body,
});
expect(res.status).toBe(200);
const json = await res.json() as { found: boolean };
expect(json.found).toBe(false);
});
it('rejects unsigned requests with 401', async () => {
const res = await fetch(`${harness.remote.origin}/api/federation/users/by-home-id`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ homeUserId: 'anything' }),
});
expect(res.status).toBe(401);
});
it('rejects non-native targets (replicated stubs) with { found: false }', async () => {
// Pre-existing stub on remote whose homeInstance is non-null. Use the
// first registered native user as a sanity comparison: a homeUserId that
// doesn't match a native non-deleted row → not found.
const stubLikeBody = JSON.stringify({ homeUserId: 'no-such-stub-id' });
const headers = buildHeadersForOrigin(stubLikeBody, sharedSecret, `https://${harness.home.domain}`);
const res = await fetch(`${harness.remote.origin}/api/federation/users/by-home-id`, {
method: 'POST',
headers,
body: stubLikeBody,
});
expect(res.status).toBe(200);
const json = await res.json() as { found: boolean };
expect(json.found).toBe(false);
});
});