Files
capcut-mate/desktop-client/nodeapi/draftPaths.test.js

150 lines
5.8 KiB
JavaScript

const { test } = require('node:test');
const assert = require('node:assert/strict');
const path = require('path');
const draftPaths = require('./draftPaths');
const DRAFT_DIR = path.join('C:', 'Users', 'me', 'drafts', '20260927202001abcd');
const PREFIX = draftPaths.placeholderPrefix();
test('placeholder prefix matches the jianying native form', () => {
assert.equal(
PREFIX,
'##_draftpath_placeholder_0E685133-18CE-45ED-8CB8-2904A212EC80_##'
);
});
test('absolute path inside the draft dir becomes placeholder-relative', () => {
const inside = path.join(DRAFT_DIR, 'assets', 'videos', 'a.mp4');
assert.equal(
draftPaths.toDraftRelative(inside, DRAFT_DIR),
`${PREFIX}/assets/videos/a.mp4`
);
});
test('posix-separated absolute path inside the draft dir is handled too', () => {
const inside = 'C:/Users/me/drafts/20260927202001abcd/assets/videos/a.mp4';
assert.equal(
draftPaths.toDraftRelative(inside, 'C:/Users/me/drafts/20260927202001abcd'),
`${PREFIX}/assets/videos/a.mp4`
);
});
test('http urls, existing placeholders and relative paths are left alone', () => {
const url = 'https://cdn.example.com/a.mp4';
assert.equal(draftPaths.toDraftRelative(url, DRAFT_DIR), url);
const already = `${PREFIX}/assets/videos/a.mp4`;
assert.equal(draftPaths.toDraftRelative(already, DRAFT_DIR), already);
assert.equal(draftPaths.toDraftRelative('assets/videos/a.mp4', DRAFT_DIR), 'assets/videos/a.mp4');
});
test('absolute paths outside the draft dir are left alone', () => {
const outside = path.join('C:', 'other', 'a.mp4');
assert.equal(draftPaths.toDraftRelative(outside, DRAFT_DIR), outside);
});
test('font sentinels are not mistaken for absolute paths', () => {
assert.equal(draftPaths.isAbsLike('D:'), false);
assert.equal(draftPaths.isAbsLike('C:'), false);
assert.equal(draftPaths.toDraftRelative('D:', DRAFT_DIR), 'D:');
assert.equal(draftPaths.toDraftFilePath('D:'), 'D:');
});
test('toDraftFilePath prefixes ./ and strips any placeholder', () => {
assert.equal(
draftPaths.toDraftFilePath(`${PREFIX}/assets/videos/a.mp4`),
'./assets/videos/a.mp4'
);
assert.equal(draftPaths.toDraftFilePath('assets/videos/a.mp4'), './assets/videos/a.mp4');
});
test('rewrite is idempotent and skips non-path keys', () => {
const materials = {
videos: [{ path: path.join(DRAFT_DIR, 'assets', 'videos', 'a.mp4'), type: 'video' }],
audios: [],
texts: [{ font_path: 'D:', styles: [{ font: { path: 'D:' } }] }],
};
assert.equal(draftPaths.normalizeMaterialPaths(materials, DRAFT_DIR), true);
assert.equal(materials.videos[0].path, `${PREFIX}/assets/videos/a.mp4`);
assert.equal(materials.texts[0].font_path, 'D:');
assert.equal(materials.texts[0].styles[0].font.path, 'D:');
assert.equal(draftPaths.normalizeMaterialPaths(materials, DRAFT_DIR), false);
});
test('material_save_mode follows the actual paths', () => {
const local = { videos: [{ path: `${PREFIX}/assets/videos/a.mp4` }], audios: [] };
assert.equal(draftPaths.computeMaterialSaveMode(local, DRAFT_DIR), 1);
const remote = { videos: [{ path: 'https://cdn/a.mp4' }], audios: [] };
assert.equal(draftPaths.computeMaterialSaveMode(remote, DRAFT_DIR), 0);
const external = { videos: [{ path: path.join('E:', 'external', 'a.mp4') }], audios: [] };
assert.equal(draftPaths.computeMaterialSaveMode(external, DRAFT_DIR), 0);
});
test('normalizeDraftContent localizes then recomputes the mode', () => {
const jsonData = {
config: { material_save_mode: 0 },
materials: {
videos: [{ path: path.join(DRAFT_DIR, 'assets', 'videos', 'a.mp4') }],
audios: [],
},
};
assert.equal(draftPaths.normalizeDraftContent(jsonData, DRAFT_DIR), 1);
assert.equal(jsonData.materials.videos[0].path, `${PREFIX}/assets/videos/a.mp4`);
assert.equal(jsonData.config.material_save_mode, 1);
});
test('url mode keeps mode 0 so jianying knows the media is not in the draft', () => {
const jsonData = {
config: {},
materials: { videos: [{ path: 'https://cdn.example.com/a.mp4' }], audios: [] },
};
assert.equal(draftPaths.normalizeDraftContent(jsonData, DRAFT_DIR), 0);
assert.equal(jsonData.config.material_save_mode, 0);
});
test('localizeDraftMeta rewrites server paths to the local draft dir', () => {
const meta = {
draft_name: 'server-side-name',
draft_fold_path: 'C:/server/drafts/20260927202001abcd',
draft_root_path: 'C:/server/drafts',
draft_materials: [
{ type: 0, value: [{ file_Path: `${PREFIX}/assets/videos/a.mp4` }] },
{ type: 1, value: [] },
],
};
draftPaths.localizeDraftMeta(meta, DRAFT_DIR, '20260927202001abcd');
assert.equal(meta.draft_name, '20260927202001abcd');
assert.equal(meta.draft_fold_path, DRAFT_DIR.replace(/\\/g, '/'));
assert.equal(meta.draft_root_path, path.dirname(DRAFT_DIR).replace(/\\/g, '/'));
assert.equal(meta.draft_materials[0].value[0].file_Path, './assets/videos/a.mp4');
// 未被识别的分组保持原样
assert.deepEqual(meta.draft_materials[1], { type: 1, value: [] });
// 服务端路径不应残留
assert.equal(JSON.stringify(meta).includes('C:/server'), false);
});
test('materialLocalDir routes through the shared media-root constant', () => {
assert.equal(
draftPaths.materialLocalDir(DRAFT_DIR, 'videos'),
path.join(DRAFT_DIR, draftPaths.DRAFT_MEDIA_ROOT, 'videos')
);
// 与 Python 侧 draft_paths.DRAFT_MEDIA_ROOT 必须一致
assert.equal(draftPaths.DRAFT_MEDIA_ROOT, 'assets');
});
test('env var can override the placeholder id', () => {
const original = process.env.DRAFT_PATH_PLACEHOLDER_ID;
process.env.DRAFT_PATH_PLACEHOLDER_ID = 'TEST-UUID';
try {
assert.equal(
draftPaths.placeholderPrefix(),
'##_draftpath_placeholder_TEST-UUID_##'
);
} finally {
if (original === undefined) delete process.env.DRAFT_PATH_PLACEHOLDER_ID;
else process.env.DRAFT_PATH_PLACEHOLDER_ID = original;
}
});