task-215: 下载 URL 格式契约(前端 node --test:绝对直链保留/origin 补齐/schema 完整/&拼接 user_id/仅带 user_id 无签名)+ 9 条测试
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
import { test } from 'node:test'
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { getJavaDownloadUrl } from '../src/shared/api/download-url.ts'
|
||||||
|
|
||||||
|
/** task-215:下载 URL 格式契约(公开直链、绝对 schema、origin 补齐、user_id 附加、query 拼接)。 */
|
||||||
|
|
||||||
|
function setup(uid = '42', origin = 'http://localhost:5173') {
|
||||||
|
;(globalThis as Record<string, unknown>).window = {
|
||||||
|
localStorage: { getItem: (k: string) => (k === 'uid' ? uid : null) },
|
||||||
|
location: { origin },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('绝对 https 直链被保留并追加 user_id', () => {
|
||||||
|
setup()
|
||||||
|
const url = getJavaDownloadUrl('https://api.example.com/result/a.xlsx')
|
||||||
|
assert.ok(url.startsWith('https://api.example.com/result/a.xlsx'), url)
|
||||||
|
assert.ok(url.includes('?user_id=42'), url)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('相对路径在 window 环境补齐 origin(schema 完整)', () => {
|
||||||
|
setup()
|
||||||
|
const url = getJavaDownloadUrl('/newApi/download/x')
|
||||||
|
assert.ok(url.startsWith('http://localhost:5173'), url)
|
||||||
|
assert.ok(url.includes('user_id=42'), url)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('绝对 http 直链不被 origin 包裹', () => {
|
||||||
|
setup()
|
||||||
|
const url = getJavaDownloadUrl('http://cdn.example.com/result/b.xlsx')
|
||||||
|
assert.ok(url.startsWith('http://cdn.example.com/result/b.xlsx'), url)
|
||||||
|
assert.ok(!url.startsWith('http://localhost:5173'), url)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('已带 query 的 URL 用 & 拼接 user_id', () => {
|
||||||
|
setup()
|
||||||
|
const url = getJavaDownloadUrl('https://api.example.com/result/c.xlsx?k=1')
|
||||||
|
assert.ok(url.includes('k=1&user_id=42'), url)
|
||||||
|
assert.ok(!/\?user_id=42/.test(url), '不应出现第二个 ?')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('user_id 为当前 uid 且 URL 编码可解析', () => {
|
||||||
|
setup('42')
|
||||||
|
const url = getJavaDownloadUrl('https://api.example.com/result/d.xlsx')
|
||||||
|
const params = new URL(url).searchParams
|
||||||
|
assert.equal(params.get('user_id'), '42')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('相对产物 query 仅含 user_id(无签名/多余参数)', () => {
|
||||||
|
setup('42')
|
||||||
|
const url = getJavaDownloadUrl('/api/result/e.xlsx')
|
||||||
|
const params = new URL(url).searchParams
|
||||||
|
const keys = [...params.keys()]
|
||||||
|
assert.deepEqual(keys, ['user_id'], url)
|
||||||
|
assert.ok(!url.includes('X-Amz-Signature'), '不应出现签名参数')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('不含重复问号', () => {
|
||||||
|
setup()
|
||||||
|
const url = getJavaDownloadUrl('https://api.example.com/result/e.xlsx')
|
||||||
|
const questionMarks = (url.match(/\?/g) ?? []).length
|
||||||
|
assert.equal(questionMarks, 1, url)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('返回 URL 始终带 schema(save_file 兼容)', () => {
|
||||||
|
setup()
|
||||||
|
for (const p of ['/a', 'relative', '/newApi/result/f.xlsx']) {
|
||||||
|
const url = getJavaDownloadUrl(p)
|
||||||
|
assert.ok(url.startsWith('http://') || url.startsWith('https://'), `${p} -> ${url}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('结果稳定可复现', () => {
|
||||||
|
setup()
|
||||||
|
const a = getJavaDownloadUrl('https://api.example.com/result/g.xlsx')
|
||||||
|
const b = getJavaDownloadUrl('https://api.example.com/result/g.xlsx')
|
||||||
|
assert.equal(a, b)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user