feat: persist settings and enrich conversation context
This commit is contained in:
1 parent
a36723a325
commit
2c100d72b6
84 files changed
+2248
-644
No files matched your search
@@ -1,5 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { MatrixClient, MatrixRateLimitError } from '../src/services/chat/matrix/client.js';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import {
|
||||
MatrixAuthError,
|
||||
MatrixClient,
|
||||
MatrixRateLimitError,
|
||||
} from '../src/services/chat/matrix/client.js';
|
||||
import { createMockLogger } from './mockLogger.js';
|
||||
|
||||
const creds = {
|
||||
@@ -10,6 +14,31 @@ const creds = {
|
||||
};
|
||||
|
||||
describe('MatrixClient HTTP timeout', () => {
|
||||
it('loads an encoded Matrix user profile with bearer authentication', async () => {
|
||||
let requestedUrl = '';
|
||||
let authorization = '';
|
||||
const fetchImpl = ((url: string | URL | Request, init?: RequestInit) => {
|
||||
requestedUrl = String(url);
|
||||
authorization = new Headers(init?.headers).get('Authorization') ?? '';
|
||||
return Promise.resolve(new Response(JSON.stringify({ displayname: 'MilkyBabe_10' }), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
}));
|
||||
}) as typeof fetch;
|
||||
const client = new MatrixClient(creds, createMockLogger(), {
|
||||
minRequestIntervalMs: 0,
|
||||
fetchImpl,
|
||||
});
|
||||
|
||||
await expect(client.getUserProfile('@t2_26q364ua7n:reddit.com')).resolves.toEqual({
|
||||
displayname: 'MilkyBabe_10',
|
||||
});
|
||||
expect(requestedUrl).toBe(
|
||||
'https://matrix.example.test/_matrix/client/v3/profile/%40t2_26q364ua7n%3Areddit.com',
|
||||
);
|
||||
expect(authorization).toBe('Bearer tok');
|
||||
});
|
||||
|
||||
it('aborts a hanging fetch and surfaces a timeout error rather than blocking forever', async () => {
|
||||
// A fetch impl that never resolves on its own — only the AbortSignal can
|
||||
// end it. If the client lacked an AbortSignal, this test would hang.
|
||||
@@ -64,6 +93,36 @@ describe('MatrixClient HTTP timeout', () => {
|
||||
}, 10_000);
|
||||
});
|
||||
|
||||
describe('MatrixClient authentication classification', () => {
|
||||
it('does not classify a room-level 403 as an expired account token', async () => {
|
||||
const client = new MatrixClient(creds, createMockLogger(), {
|
||||
minRequestIntervalMs: 0,
|
||||
fetchImpl: vi.fn().mockResolvedValue(new Response('', { status: 403 })),
|
||||
});
|
||||
|
||||
const error = await client.getRoomFullState('!left-room:example.test').catch((cause) => cause);
|
||||
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error).not.toBeInstanceOf(MatrixAuthError);
|
||||
expect((error as Error).message).toMatch(/403/);
|
||||
});
|
||||
|
||||
it('still classifies an explicit unknown-token 403 as authentication failure', async () => {
|
||||
const client = new MatrixClient(creds, createMockLogger(), {
|
||||
minRequestIntervalMs: 0,
|
||||
fetchImpl: vi.fn().mockResolvedValue(new Response(JSON.stringify({
|
||||
errcode: 'M_UNKNOWN_TOKEN',
|
||||
error: 'Access token has expired',
|
||||
}), {
|
||||
status: 403,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})),
|
||||
});
|
||||
|
||||
await expect(client.whoami()).rejects.toBeInstanceOf(MatrixAuthError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MatrixClient 429 handling', () => {
|
||||
it('throws MatrixRateLimitError on a long retry_after rather than sleeping it out', async () => {
|
||||
const fetchImpl = (() =>
|
||||
|
||||
Reference in new issue
Block a user