Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import type { MessageElement } from '@snowluma/protocol/events';
|
|
import { getImageInfo } from '../src/modules/media-actions';
|
|
import type { CachedImage, MediaStore } from '../src/media-store';
|
|
|
|
const RAW = 'https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=ABC';
|
|
|
|
function fakeStore(image: CachedImage | null): MediaStore {
|
|
return { findImage: () => image } as unknown as MediaStore;
|
|
}
|
|
|
|
function cachedImage(overrides: Partial<CachedImage> = {}): CachedImage {
|
|
return {
|
|
file: 'ABC.jpg',
|
|
url: `${RAW}&rkey=STALE`, // signed when the message arrived; now expired
|
|
fileSize: 100,
|
|
fileName: 'ABC.jpg',
|
|
subType: 0,
|
|
summary: '',
|
|
isGroup: true,
|
|
sessionId: 123,
|
|
imageUrl: RAW, // raw, unsigned — the basis for re-signing
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe('getImageInfo — rkey re-signing at lookup time', () => {
|
|
it('re-signs from the raw imageUrl via the resolver', async () => {
|
|
const resolver = vi.fn(async (el: MessageElement) => `${el.imageUrl}&rkey=FRESH`);
|
|
|
|
const info = await getImageInfo(fakeStore(cachedImage()), 'ABC.jpg', resolver);
|
|
|
|
expect(info?.url).toBe(`${RAW}&rkey=FRESH`);
|
|
expect(info?.file).toBe(`${RAW}&rkey=FRESH`);
|
|
expect(resolver).toHaveBeenCalledWith(
|
|
expect.objectContaining({ type: 'image', imageUrl: RAW }),
|
|
true, // isGroup carried through
|
|
);
|
|
});
|
|
|
|
it('returns the stored URL when no resolver is wired', async () => {
|
|
const info = await getImageInfo(fakeStore(cachedImage()), 'ABC.jpg');
|
|
expect(info?.url).toBe(`${RAW}&rkey=STALE`);
|
|
});
|
|
|
|
it('falls back to the stored URL when the resolver throws', async () => {
|
|
const resolver = vi.fn(async () => {
|
|
throw new Error('rkey fetch failed');
|
|
});
|
|
const info = await getImageInfo(fakeStore(cachedImage()), 'ABC.jpg', resolver);
|
|
expect(info?.url).toBe(`${RAW}&rkey=STALE`);
|
|
});
|
|
|
|
it('skips re-signing when no raw imageUrl is stored', async () => {
|
|
const resolver = vi.fn(async () => 'should-not-be-used');
|
|
const info = await getImageInfo(
|
|
fakeStore(cachedImage({ imageUrl: '' })),
|
|
'ABC.jpg',
|
|
resolver,
|
|
);
|
|
expect(resolver).not.toHaveBeenCalled();
|
|
expect(info?.url).toBe(`${RAW}&rkey=STALE`);
|
|
});
|
|
|
|
it('returns null when the image is not cached', async () => {
|
|
const info = await getImageInfo(fakeStore(null), 'missing.jpg');
|
|
expect(info).toBeNull();
|
|
});
|
|
});
|