gongxiangp2/lib/__tests__/video-download-policy.test.ts

187 lines
5.7 KiB
TypeScript

import {
applyVideoPreviewPolicy,
getVideoDownloadAvailability,
getVideoDownloadUnavailableMessage,
getVideoPreviewPolicyFields,
userHasVideoEarlyAccess,
VIDEO_DOWNLOAD_WAIT_DAYS,
} from '@/lib/video-download-policy'
import { DownloadErrorCode, parseDownloadError } from '@/lib/download-errors'
describe('video download policy', () => {
const now = new Date('2026-05-25T12:00:00.000Z')
test('安装视频不受 15 天限制', () => {
const availability = getVideoDownloadAvailability(
'安装视频',
'2026-05-25T11:00:00.000Z',
now,
)
expect(availability.allowed).toBe(true)
})
test('非安装视频上传未满 15 天时禁止下载', () => {
const availability = getVideoDownloadAvailability(
'淘系-主图视频',
'2026-05-20T12:00:00.000Z',
now,
)
expect(availability).toMatchObject({
allowed: false,
reason: 'VIDEO_WAIT_PERIOD',
remainingDays: 10,
})
expect(availability.availableAt?.toISOString()).toBe('2026-06-04T12:00:00.000Z')
expect(getVideoDownloadUnavailableMessage(availability)).toContain(
`满 ${VIDEO_DOWNLOAD_WAIT_DAYS} 天才能下载`,
)
})
test('非安装视频上传满 15 天后允许下载', () => {
const availability = getVideoDownloadAvailability(
'抖音-千川素材',
'2026-05-10T12:00:00.000Z',
now,
)
expect(availability.allowed).toBe(true)
})
test('兼容旧视频类型名称', () => {
const availability = getVideoDownloadAvailability(
'主图视频',
'2026-05-24T12:00:00.000Z',
now,
)
expect(availability.allowed).toBe(false)
expect(availability.reason).toBe('VIDEO_WAIT_PERIOD')
})
test('非视频素材不受限制', () => {
const availability = getVideoDownloadAvailability(
'买家秀图片',
'2026-05-25T11:00:00.000Z',
now,
)
expect(availability.allowed).toBe(true)
})
test('下载错误解析应优先展示等待期详情', () => {
const parsed = parseDownloadError({
code: DownloadErrorCode.VIDEO_WAIT_PERIOD,
error: '视频类素材上传后满 15 天才能下载',
details: '视频类素材上传后满 15 天才能下载,当前还需约 3 天',
})
expect(parsed.message).toBe('视频类素材上传后满 15 天才能下载,当前还需约 3 天')
})
test('非安装视频上传未满 15 天时禁止进入详情预览', () => {
const policy = getVideoPreviewPolicyFields(
'淘系-主图视频',
'2026-05-20T12:00:00.000Z',
now,
)
expect(policy).toMatchObject({
videoPreviewBlocked: true,
videoPreviewUnavailableReason: 'VIDEO_WAIT_PERIOD',
videoPreviewRemainingDays: 10,
})
expect(policy.videoPreviewUnavailableMessage).toContain('才能预览和下载')
})
test('预览门禁会移除视频预览和源视频地址', () => {
const material = applyVideoPreviewPolicy(
{
materialType: '抖音-千川素材',
createdAt: '2026-05-24T12:00:00.000Z',
videoSourceUrl: 'https://example.com/source.mp4',
videoPreview540Url: 'https://example.com/preview.mp4',
videoPreviewClipUrl: 'https://example.com/clip.mp4',
videoCoverUrl: 'https://example.com/cover.jpg',
},
now,
)
expect(material.videoPreviewBlocked).toBe(true)
expect(material.videoSourceUrl).toBeNull()
expect(material.videoPreview540Url).toBeNull()
expect(material.videoPreviewClipUrl).toBeNull()
expect(material.videoCoverUrl).toBe('https://example.com/cover.jpg')
})
})
describe('video download policy — 15 天保护期豁免', () => {
const now = new Date('2026-05-25T12:00:00.000Z')
test('豁免用户不受保护期限制(直接放行)', () => {
const availability = getVideoDownloadAvailability(
'淘系-主图视频',
'2026-05-20T12:00:00.000Z',
now,
{ bypassWaitPeriod: true },
)
expect(availability).toEqual({ allowed: true })
})
test('豁免时预览字段全部放行', () => {
const fields = getVideoPreviewPolicyFields(
'逛逛视频',
'2026-05-25T00:00:00.000Z',
now,
{ bypassWaitPeriod: true },
)
expect(fields.videoPreviewBlocked).toBe(false)
expect(fields.videoPreviewUnavailableReason).toBeNull()
})
test('豁免时 URL 不被抹除', () => {
const result = applyVideoPreviewPolicy(
{
materialType: '淘系-主图视频',
createdAt: '2026-05-25T00:00:00.000Z',
videoSourceUrl: 'https://example.com/video.mp4',
videoPreview540Url: 'https://example.com/540.mp4',
},
now,
{ bypassWaitPeriod: true },
)
expect(result.videoSourceUrl).toBe('https://example.com/video.mp4')
expect(result.videoPreview540Url).toBe('https://example.com/540.mp4')
expect(result.videoPreviewBlocked).toBe(false)
})
test('未豁免时行为与旧逻辑完全一致(默认参数不变)', () => {
const withOptions = getVideoDownloadAvailability(
'淘系-主图视频',
'2026-05-20T12:00:00.000Z',
now,
{ bypassWaitPeriod: false },
)
const withoutOptions = getVideoDownloadAvailability(
'淘系-主图视频',
'2026-05-20T12:00:00.000Z',
now,
)
expect(withOptions).toEqual(withoutOptions)
expect(withOptions.allowed).toBe(false)
})
test('userHasVideoEarlyAccess 只认显式 true', () => {
expect(userHasVideoEarlyAccess({ videoEarlyAccess: true })).toBe(true)
expect(userHasVideoEarlyAccess({ videoEarlyAccess: false })).toBe(false)
expect(userHasVideoEarlyAccess({})).toBe(false)
expect(userHasVideoEarlyAccess(undefined)).toBe(false)
expect(userHasVideoEarlyAccess(null)).toBe(false)
})
})