import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import test from 'node:test'; import ts from 'typescript'; import * as vue from 'vue'; import { compileScript, parse } from 'vue/compiler-sfc'; function loadTS(source, imports = {}, globals = {}) { const js = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 } }).outputText; const exports = {}; new Function('exports', 'require', ...Object.keys(globals), js)(exports, name => { assert.ok(imports[name], `unexpected module ${name}`); return imports[name]; }, ...Object.values(globals)); return exports; } const helper = loadTS(readFileSync(new URL('../src/utils/avatar-image.ts', import.meta.url), 'utf8')); test('versioned uploads use thumbnails, while external, local and signed URLs remain intact', () => { for (const prefix of ['https://cdn.example.com/media/2026/08/', '/uploads/']) { const src = `${prefix}42-1788189400000-av1.jpg`; assert.equal(helper.avatarImageSource(src), `${prefix}42-1788189400000-av1-thumb.jpg`); assert.equal(helper.avatarImageSource(src, 'display'), src); } for (const src of ['', undefined, 'https://cdn.example.com/42-1.png', 'https://oauth.example.com/photo.jpg', 'https://cdn.example.com/42-1-av1.jpg?signature=secret', 'https://cdn.example.com/42-1-av1.jpg#hash', 'https://cdn.example.com/42-1-av1-thumb.jpg', 'https://cdn.example.com/42-1-av1-original.png', '/tmp/42-1-av1.jpg', 'file:///tmp/42-1-av1.jpg', 'blob:https://app.example.com/42-1-av1.jpg']) { assert.equal(helper.avatarImageSource(src), src || ''); } }); test('avatar component falls back once, then resets when reused for another user', async () => { const source = readFileSync(new URL('../src/components/AvatarImage.vue', import.meta.url), 'utf8'); const { descriptor } = parse(source); const script = compileScript(descriptor, { id: 'avatar-regression' }); const component = loadTS(script.content, { vue, '../utils/avatar-image': helper }).default; const props = vue.reactive({ src: 'https://cdn.example.com/42-1-av1.jpg', variant: 'thumbnail', lazy: true }); const scope = vue.effectScope(); const state = scope.run(() => component.setup(props, { expose() {} })); try { assert.match(state.imageSource.value, /-thumb\.jpg$/); state.onError(); assert.equal(state.imageSource.value, props.src); state.onError(); assert.equal(state.imageSource.value, props.src); props.src = 'https://cdn.example.com/43-2-av1.jpg'; await vue.nextTick(); assert.equal(state.imageSource.value, 'https://cdn.example.com/43-2-av1-thumb.jpg'); props.variant = 'display'; await vue.nextTick(); assert.equal(state.imageSource.value, props.src); } finally { scope.stop(); } }); function uploadClient(retry = false) { const uploads = []; const storage = { accessToken: 'old-token', refreshToken: 'refresh-token' }; const uni = { getStorageSync: key => storage[key], setStorageSync: (key, value) => { storage[key] = value; }, uploadFile(options) { uploads.push(options); queueMicrotask(() => options.success(retry && uploads.length === 1 ? { statusCode: 401, data: JSON.stringify({ code: 401, message: 'expired' }) } : { statusCode: 200, data: JSON.stringify({ code: 0, data: { url: 'https://cdn.example.com/42-1-av1.jpg' } }) })); }, request(options) { assert.match(options.url, /\/auth\/token\/refresh$/); queueMicrotask(() => options.success({ statusCode: 200, data: { code: 0, data: { accessToken: 'new-token' } } })); }, }; const source = readFileSync(new URL('../src/utils/request.ts', import.meta.url), 'utf8') .replaceAll('import.meta.env.VITE_API_ORIGIN', '"https://api.example.com"'); const client = loadTS(source, { './device': { getDeviceHeaders: () => ({ 'X-Device-Id': 'test-device' }) }, './network-errors': { isLoopbackServer: () => false } }, { uni }); return { client, uploads }; } test('avatar upload purpose and refreshed authorization survive a token retry', async () => { const { client, uploads } = uploadClient(true); assert.equal(await client.api.uploadAvatar('/tmp/camera.jpg'), 'https://cdn.example.com/42-1-av1.jpg'); assert.equal(uploads.length, 2); for (const upload of uploads) { assert.deepEqual(upload.formData, { purpose: 'avatar' }); assert.equal(upload.filePath, '/tmp/camera.jpg'); assert.equal(upload.header['X-Device-Id'], 'test-device'); } assert.equal(uploads[1].header.Authorization, 'Bearer new-token'); }); test('ordinary media uploads do not request avatar processing', async () => { const { client, uploads } = uploadClient(); await client.api.uploadMedia('/tmp/evidence.png'); assert.equal(uploads.length, 1); assert.equal(uploads[0].formData, undefined); });