Skip to content

Commit bc06d99

Browse files
authored
fix(xiaohongshu): detect current draft save success (#1060)
1 parent 3738cd2 commit bc06d99

2 files changed

Lines changed: 106 additions & 6 deletions

File tree

clis/xiaohongshu/publish.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -621,17 +621,17 @@ cli({
621621
// ── Step 8: Verify success ─────────────────────────────────────────────────
622622
await page.wait({ time: 4 });
623623
const finalUrl = await page.evaluate('() => location.href');
624+
const successMarkers = isDraft
625+
? ['草稿已保存', '暂存成功', '保存成功', '上传成功']
626+
: ['发布成功', '上传成功'];
624627
const successMsg = await page.evaluate(`
625-
() => {
628+
(markers => {
626629
for (const el of document.querySelectorAll('*')) {
627630
const text = (el.innerText || '').trim();
628-
if (
629-
el.children.length === 0 &&
630-
(text.includes('发布成功') || text.includes('草稿已保存') || text.includes('暂存成功') || text.includes('上传成功'))
631-
) return text;
631+
if (el.children.length === 0 && markers.some(marker => text.includes(marker))) return text;
632632
}
633633
return '';
634-
}
634+
})(${JSON.stringify(successMarkers)})
635635
`);
636636
const navigatedAway = !finalUrl.includes('/publish/publish');
637637
const isSuccess = successMsg.length > 0 || navigatedAway;

clis/xiaohongshu/publish.test.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,4 +405,104 @@ describe('xiaohongshu publish', () => {
405405
},
406406
]);
407407
});
408+
it('treats 保存成功 on the draft list as a successful draft save', async () => {
409+
const cmd = getRegistry().get('xiaohongshu/publish');
410+
expect(cmd?.func).toBeTypeOf('function');
411+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-xhs-publish-'));
412+
const imagePath = path.join(tempDir, 'demo.jpg');
413+
fs.writeFileSync(imagePath, Buffer.from([0xff, 0xd8, 0xff, 0xd9]));
414+
const page = createConditionalPageMock((code) => {
415+
if (code.includes('location.href'))
416+
return 'https://creator.xiaohongshu.com/publish/publish?from=menu_left&target=image';
417+
if (code.includes("const targets = ['上传图文', '图文', '图片']"))
418+
return { ok: true, target: '上传图文', text: '上传图文' };
419+
if (code.includes('hasTitleInput') && code.includes('hasVideoSurface'))
420+
return { state: 'editor_ready', hasTitleInput: true, hasImageInput: true, hasVideoSurface: false };
421+
if (code.includes('const images =') && code.includes('dt.items.add(new File'))
422+
return { ok: true, count: 1 };
423+
if (code.includes('[class*="upload"][class*="progress"]'))
424+
return false;
425+
if (code.includes('const sels =') && code.includes('for (const sel of sels)'))
426+
return true;
427+
if (code.includes('__opencli_xhs_fill_phase') && code.includes('"locate"')) {
428+
return code.includes('[contenteditable="true"][class*="content"]')
429+
? { ok: true, sel: '[contenteditable="true"][class*="content"]', kind: 'contenteditable' }
430+
: { ok: true, sel: 'input[placeholder*="标题"]', kind: 'input' };
431+
}
432+
if (code.includes('__opencli_xhs_fill_phase') && code.includes('"apply"')) {
433+
return code.includes('[contenteditable="true"][class*="content"]')
434+
? { ok: true, actual: '停留在发布页也算成功' }
435+
: { ok: true, actual: '草稿成功提示' };
436+
}
437+
if (code.includes('labels.some'))
438+
return true;
439+
if (code.includes('for (const el of document.querySelectorAll')) {
440+
return code.includes('保存成功') ? '保存成功' : '';
441+
}
442+
throw new Error(`Unhandled evaluate call: ${code.slice(0, 120)}`);
443+
});
444+
const result = await cmd.func(page, {
445+
title: '草稿成功提示',
446+
content: '停留在发布页也算成功',
447+
images: imagePath,
448+
topics: '',
449+
draft: true,
450+
});
451+
expect(result).toEqual([
452+
{
453+
status: '✅ 暂存成功',
454+
detail: '"草稿成功提示" · 1张图片 · 保存成功',
455+
},
456+
]);
457+
});
458+
it('does not treat 保存成功 alone as a publish success signal', async () => {
459+
const cmd = getRegistry().get('xiaohongshu/publish');
460+
expect(cmd?.func).toBeTypeOf('function');
461+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-xhs-publish-'));
462+
const imagePath = path.join(tempDir, 'demo.jpg');
463+
fs.writeFileSync(imagePath, Buffer.from([0xff, 0xd8, 0xff, 0xd9]));
464+
const page = createConditionalPageMock((code) => {
465+
if (code.includes('location.href'))
466+
return 'https://creator.xiaohongshu.com/publish/publish?from=menu_left&target=image';
467+
if (code.includes("const targets = ['上传图文', '图文', '图片']"))
468+
return { ok: true, target: '上传图文', text: '上传图文' };
469+
if (code.includes('hasTitleInput') && code.includes('hasVideoSurface'))
470+
return { state: 'editor_ready', hasTitleInput: true, hasImageInput: true, hasVideoSurface: false };
471+
if (code.includes('const images =') && code.includes('dt.items.add(new File'))
472+
return { ok: true, count: 1 };
473+
if (code.includes('[class*="upload"][class*="progress"]'))
474+
return false;
475+
if (code.includes('const sels =') && code.includes('for (const sel of sels)'))
476+
return true;
477+
if (code.includes('__opencli_xhs_fill_phase') && code.includes('"locate"')) {
478+
return code.includes('[contenteditable="true"][class*="content"]')
479+
? { ok: true, sel: '[contenteditable="true"][class*="content"]', kind: 'contenteditable' }
480+
: { ok: true, sel: 'input[placeholder*="标题"]', kind: 'input' };
481+
}
482+
if (code.includes('__opencli_xhs_fill_phase') && code.includes('"apply"')) {
483+
return code.includes('[contenteditable="true"][class*="content"]')
484+
? { ok: true, actual: '发布提示不该复用草稿成功' }
485+
: { ok: true, actual: '发布成功提示' };
486+
}
487+
if (code.includes('labels.some'))
488+
return true;
489+
if (code.includes('for (const el of document.querySelectorAll')) {
490+
return code.includes('保存成功') ? '保存成功' : '';
491+
}
492+
throw new Error(`Unhandled evaluate call: ${code.slice(0, 120)}`);
493+
});
494+
const result = await cmd.func(page, {
495+
title: '发布成功提示',
496+
content: '发布提示不该复用草稿成功',
497+
images: imagePath,
498+
topics: '',
499+
draft: false,
500+
});
501+
expect(result).toEqual([
502+
{
503+
status: '⚠️ 操作完成,请在浏览器中确认',
504+
detail: '"发布成功提示" · 1张图片 · https://creator.xiaohongshu.com/publish/publish?from=menu_left&target=image',
505+
},
506+
]);
507+
});
408508
});

0 commit comments

Comments
 (0)