From 261eb6b7ae8d53af3cb9d1a792f314b40be65f8e Mon Sep 17 00:00:00 2001 From: NI0317 Date: Fri, 31 Jul 2026 00:28:38 +0800 Subject: [PATCH] test(tui): stabilize first-run PTY snapshots --- apps/cli/tests/pty-harness.ts | 22 ++++- .../60-columns-low-height.expected.txt | 39 --------- .../120-columns.expected.txt | 60 +++++--------- .../160-columns.expected.txt | 60 +++++--------- .../60-columns-low-height.expected.txt | 31 +++++++ .../60-columns.expected.txt | 82 +++++++++---------- .../80-columns.expected.txt | 78 ++++++++---------- apps/cli/tests/tui-keyless-smoke.e2e.ts | 47 +++++++---- 8 files changed, 194 insertions(+), 225 deletions(-) delete mode 100644 apps/cli/tests/snapshots/tui-first-run-welcome/60-columns-low-height.expected.txt rename apps/cli/tests/{snapshots/tui-first-run-welcome => tui-first-run-snapshots}/120-columns.expected.txt (53%) rename apps/cli/tests/{snapshots/tui-first-run-welcome => tui-first-run-snapshots}/160-columns.expected.txt (57%) create mode 100644 apps/cli/tests/tui-first-run-snapshots/60-columns-low-height.expected.txt rename apps/cli/tests/{snapshots/tui-first-run-welcome => tui-first-run-snapshots}/60-columns.expected.txt (50%) rename apps/cli/tests/{snapshots/tui-first-run-welcome => tui-first-run-snapshots}/80-columns.expected.txt (58%) diff --git a/apps/cli/tests/pty-harness.ts b/apps/cli/tests/pty-harness.ts index fb926bd7c1..b8225a8f50 100644 --- a/apps/cli/tests/pty-harness.ts +++ b/apps/cli/tests/pty-harness.ts @@ -55,6 +55,9 @@ while time.monotonic() < deadline: os.write(fd, action["send"].encode()) else: os.write(fd, action["send"].encode()) + if "signalAfterMs" in action: + time.sleep(action["signalAfterMs"] / 1000) + os.kill(pid, signal.SIGTERM) action_index += 1 waited, candidate = os.waitpid(pid, os.WNOHANG) if waited == pid: @@ -76,7 +79,14 @@ if actual_exit != int(expected_exit): /** One terminal input or workspace mutation performed after its marker renders. */ type TuiPtyAction = - | { readonly waitFor: string; readonly occurrence?: number; readonly send: string; readonly delayMs?: number } + | { + readonly waitFor: string + readonly occurrence?: number + readonly send: string + readonly delayMs?: number + /** Terminate the process this many milliseconds after sending input. */ + readonly signalAfterMs?: number + } | { readonly waitFor: string; readonly occurrence?: number; readonly signal: 'SIGTERM'; readonly delayMs?: number } | { readonly waitFor: string @@ -205,8 +215,14 @@ async function runWindowsPtySmoke( else setTimeout(() => { terminal.write(input) }, action.delayMs) } } else { - if (action.delayMs === undefined) terminal.write(action.send) - else setTimeout(() => { terminal.write(action.send) }, action.delayMs) + const send = (): void => { + terminal.write(action.send) + if (action.signalAfterMs !== undefined) { + setTimeout(() => { terminal.kill('SIGTERM') }, action.signalAfterMs) + } + } + if (action.delayMs === undefined) send() + else setTimeout(send, action.delayMs) } actionIndex += 1 } diff --git a/apps/cli/tests/snapshots/tui-first-run-welcome/60-columns-low-height.expected.txt b/apps/cli/tests/snapshots/tui-first-run-welcome/60-columns-low-height.expected.txt deleted file mode 100644 index dc0459ab43..0000000000 --- a/apps/cli/tests/snapshots/tui-first-run-welcome/60-columns-low-height.expected.txt +++ /dev/null @@ -1,39 +0,0 @@ -terminal 60x12 buffer=normal length=16 base=4 viewport=4 -lifecycle started=0 stopped=0 progress=inactive -title "" -cursor visible column=0 viewportRow=11 bufferRow=15 -viewport -4| " DEEPSEEK HARNESS" - style 1-8 fg=bright-magenta bold - style 10-16 bold -5| "╭──────────────────────────────────────────────────────────╮" - style 0-59 dim -6| "│ DeepSeek Harness │" - style 0-0 dim - style 22-37 fg=blue bold - style 59-59 dim -7| "│ │" - style 0-0 dim - style 59-59 dim -8| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" - style 0-0 dim - style 59-59 dim -9| "│ │" - style 0-0 dim - style 59-59 dim -10| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验 │" - style 0-0 dim - style 59-59 dim -11| "├──────────────────────────────────────────────────────────┤" - style 0-59 dim -12| "│ Enter 继续 │" - style 0-0 dim - style 24-34 fg=bright-magenta bold - style 59-59 dim -13| "│ ↑/↓ 滚动 ↓ │" - style 0-0 dim - style 24-35 dim - style 59-59 dim -14| "╰──────────────────────────────────────────────────────────╯" - style 0-59 dim -15| diff --git a/apps/cli/tests/snapshots/tui-first-run-welcome/120-columns.expected.txt b/apps/cli/tests/tui-first-run-snapshots/120-columns.expected.txt similarity index 53% rename from apps/cli/tests/snapshots/tui-first-run-welcome/120-columns.expected.txt rename to apps/cli/tests/tui-first-run-snapshots/120-columns.expected.txt index a22b548e5a..c279f39afd 100644 --- a/apps/cli/tests/snapshots/tui-first-run-welcome/120-columns.expected.txt +++ b/apps/cli/tests/tui-first-run-snapshots/120-columns.expected.txt @@ -1,94 +1,76 @@ -terminal 120x30 buffer=normal length=32 base=2 viewport=2 -lifecycle started=0 stopped=0 progress=inactive -title "" -cursor visible column=0 viewportRow=29 bufferRow=31 -viewport -2| " DEEPSEEK HARNESS" - style 1-8 fg=bright-magenta bold - style 10-16 bold -3| " scripted TUI ready." - style 1-19 dim -4| " main-session-{{uuid}}" - style 1-49 dim -5| -6| "/tmp/dsh-tui-welcome tui-scripted-model ↑0 ↓0 0% conte" - style 0-82 fg=bright-magenta bold - style 85-102 dim - style 105-109 dim - style 112-119 dim -7| "╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮" +overlay 120x30 rows=20 +0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮" style 0-119 dim -8| "│ ▄ DeepSeek Harness │" +1| "│ ▄ DeepSeek Harness │" style 0-0 dim style 10-37 fg=blue style 75-90 fg=blue bold style 119-119 dim -9| "│ ▄▄▄▄▄▄▄▄▄▄███▀ ██▄ │" +2| "│ ▄▄▄▄▄▄▄▄▄▄███▀ ██▄ │" style 0-0 dim style 9-38 fg=blue style 119-119 dim -10| "│ ▄███████████████▄ ████▄ ▄▄▄▄██ 感谢您愿意拨冗试用 DeepSeek Harness。 │" +3| "│ ▄███████████████▄ ████▄ ▄▄▄▄██ 感谢您愿意拨冗试用 DeepSeek Harness。 │" style 0-0 dim style 4-43 fg=blue style 119-119 dim -11| "│ ▄███████████████████▄ ████████████▀ │" +4| "│ ▄███████████████████▄ ████████████▀ │" style 0-0 dim style 4-43 fg=blue style 119-119 dim -12| "│ ▄██████████████████████▄ ▀█████████▀ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" +5| "│ ▄██████████████████████▄ ▀█████████▀ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" style 0-0 dim style 4-42 fg=blue style 119-119 dim -13| "│ ▄███▀█████████████████████▄ ████▀▀ │" +6| "│ ▄███▀█████████████████████▄ ████▀▀ │" style 0-0 dim style 6-41 fg=blue style 119-119 dim -14| "│ ███ ▀▀█████████▀▀▀█████████▀ “如切如磋,如琢如磨。” │" +7| "│ ███ ▀▀█████████▀▀▀█████████▀ “如切如磋,如琢如磨。” │" style 0-0 dim style 7-40 fg=blue style 49-70 bold style 119-119 dim -15| "│ ███ ▀███████▀█ ▀███████ │" +8| "│ ███ ▀███████▀█ ▀███████ │" style 0-0 dim style 7-39 fg=blue style 119-119 dim -16| "│ ███▄ ▀███████▄ ▀█████▀ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的 │" +9| "│ ███▄ ▀███████▄ ▀█████▀ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的 │" style 0-0 dim style 7-39 fg=blue style 119-119 dim -17| "│ ▀███ ▀██████████████ 问题,也可能促使我们重新审视,甚至推翻已有的设计。 │" +10| "│ ▀███ ▀██████████████ 问题,也可能促使我们重新审视,甚至推翻已有的设计。 │" style 0-0 dim style 8-39 fg=blue style 119-119 dim -18| "│ ▀███▄ ▀███████████▀ │" +11| "│ ▀███▄ ▀███████████▀ │" style 0-0 dim style 8-38 fg=blue style 119-119 dim -19| "│ ▀███▄ ▄▄▄ ▀████████▀ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能帮到您,甚至 │" +12| "│ ▀███▄ ▄▄▄ ▀████████▀ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能帮到您,甚至 │" style 0-0 dim style 9-38 fg=blue style 119-119 dim -20| "│ █████▄ ███▄▄ ▀█████▄▄ 反而为工作平添了麻烦,请在企业微信群中留言,将使用感受告诉我们。每一 │" +13| "│ █████▄ ███▄▄ ▀█████▄▄ 反而为工作平添了麻烦,请在企业微信群中留言,将使用感受告诉我们。每一 │" style 0-0 dim style 9-38 fg=blue style 119-119 dim -21| "│ ▀█████████████▄▄▄▄█▀█████▀ 条反馈,都会帮助我们把它打磨得更好。 │" +14| "│ ▀█████████████▄▄▄▄█▀█████▀ 条反馈,都会帮助我们把它打磨得更好。 │" style 0-0 dim style 8-39 fg=blue style 119-119 dim -22| "│ ▀▀███████████▀▀ │" +15| "│ ▀▀███████████▀▀ │" style 0-0 dim style 12-34 fg=blue style 119-119 dim -23| "├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤" +16| "├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤" style 0-119 dim -24| "│ Enter 继续 │" +17| "│ Enter 继续 │" style 0-0 dim style 54-64 fg=bright-magenta bold style 119-119 dim -25| "│ │" +18| "│ │" style 0-0 dim style 119-119 dim -26| "╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯" +19| "╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯" style 0-119 dim -27-31| diff --git a/apps/cli/tests/snapshots/tui-first-run-welcome/160-columns.expected.txt b/apps/cli/tests/tui-first-run-snapshots/160-columns.expected.txt similarity index 57% rename from apps/cli/tests/snapshots/tui-first-run-welcome/160-columns.expected.txt rename to apps/cli/tests/tui-first-run-snapshots/160-columns.expected.txt index 4c22bfd6cb..5b6b903502 100644 --- a/apps/cli/tests/snapshots/tui-first-run-welcome/160-columns.expected.txt +++ b/apps/cli/tests/tui-first-run-snapshots/160-columns.expected.txt @@ -1,94 +1,76 @@ -terminal 160x30 buffer=normal length=32 base=2 viewport=2 -lifecycle started=0 stopped=0 progress=inactive -title "" -cursor visible column=0 viewportRow=29 bufferRow=31 -viewport -2| " DEEPSEEK HARNESS" - style 1-8 fg=bright-magenta bold - style 10-16 bold -3| " scripted TUI ready." - style 1-19 dim -4| " main-session-{{uuid}}" - style 1-49 dim -5| -6| "/tmp/dsh-tui-welcome tui-scripted-model ↑0 ↓0 0% context" - style 0-82 fg=bright-magenta bold - style 85-102 dim - style 105-109 dim - style 112-121 dim -7| "╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮" +overlay 160x30 rows=20 +0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮" style 0-159 dim -8| "│ ▄ DeepSeek Harness │" +1| "│ ▄ DeepSeek Harness │" style 0-0 dim style 10-37 fg=blue style 95-110 fg=blue bold style 159-159 dim -9| "│ ▄▄▄▄▄▄▄▄▄▄███▀ ██▄ │" +2| "│ ▄▄▄▄▄▄▄▄▄▄███▀ ██▄ │" style 0-0 dim style 9-38 fg=blue style 159-159 dim -10| "│ ▄███████████████▄ ████▄ ▄▄▄▄██ 感谢您愿意拨冗试用 DeepSeek Harness。 │" +3| "│ ▄███████████████▄ ████▄ ▄▄▄▄██ 感谢您愿意拨冗试用 DeepSeek Harness。 │" style 0-0 dim style 4-43 fg=blue style 159-159 dim -11| "│ ▄███████████████████▄ ████████████▀ │" +4| "│ ▄███████████████████▄ ████████████▀ │" style 0-0 dim style 4-43 fg=blue style 159-159 dim -12| "│ ▄██████████████████████▄ ▀█████████▀ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" +5| "│ ▄██████████████████████▄ ▀█████████▀ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" style 0-0 dim style 4-42 fg=blue style 159-159 dim -13| "│ ▄███▀█████████████████████▄ ████▀▀ │" +6| "│ ▄███▀█████████████████████▄ ████▀▀ │" style 0-0 dim style 6-41 fg=blue style 159-159 dim -14| "│ ███ ▀▀█████████▀▀▀█████████▀ “如切如磋,如琢如磨。” │" +7| "│ ███ ▀▀█████████▀▀▀█████████▀ “如切如磋,如琢如磨。” │" style 0-0 dim style 7-40 fg=blue style 49-70 bold style 159-159 dim -15| "│ ███ ▀███████▀█ ▀███████ │" +8| "│ ███ ▀███████▀█ ▀███████ │" style 0-0 dim style 7-39 fg=blue style 159-159 dim -16| "│ ███▄ ▀███████▄ ▀█████▀ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的问题,也可能促使我们重新审视,甚至推翻已 │" +9| "│ ███▄ ▀███████▄ ▀█████▀ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的问题,也可能促使我们重新审视,甚至推翻已 │" style 0-0 dim style 7-39 fg=blue style 159-159 dim -17| "│ ▀███ ▀██████████████ 有的设计。 │" +10| "│ ▀███ ▀██████████████ 有的设计。 │" style 0-0 dim style 8-39 fg=blue style 159-159 dim -18| "│ ▀███▄ ▀███████████▀ │" +11| "│ ▀███▄ ▀███████████▀ │" style 0-0 dim style 8-38 fg=blue style 159-159 dim -19| "│ ▀███▄ ▄▄▄ ▀████████▀ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能帮到您,甚至反而为工作平添了麻烦,请在企业微信群中留 │" +12| "│ ▀███▄ ▄▄▄ ▀████████▀ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能帮到您,甚至反而为工作平添了麻烦,请在企业微信群中留 │" style 0-0 dim style 9-38 fg=blue style 159-159 dim -20| "│ █████▄ ███▄▄ ▀█████▄▄ 言,将使用感受告诉我们。每一条反馈,都会帮助我们把它打磨得更好。 │" +13| "│ █████▄ ███▄▄ ▀█████▄▄ 言,将使用感受告诉我们。每一条反馈,都会帮助我们把它打磨得更好。 │" style 0-0 dim style 9-38 fg=blue style 159-159 dim -21| "│ ▀█████████████▄▄▄▄█▀█████▀ │" +14| "│ ▀█████████████▄▄▄▄█▀█████▀ │" style 0-0 dim style 8-39 fg=blue style 159-159 dim -22| "│ ▀▀███████████▀▀ │" +15| "│ ▀▀███████████▀▀ │" style 0-0 dim style 12-34 fg=blue style 159-159 dim -23| "├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤" +16| "├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤" style 0-159 dim -24| "│ Enter 继续 │" +17| "│ Enter 继续 │" style 0-0 dim style 74-84 fg=bright-magenta bold style 159-159 dim -25| "│ │" +18| "│ │" style 0-0 dim style 159-159 dim -26| "╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯" +19| "╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯" style 0-159 dim -27-31| diff --git a/apps/cli/tests/tui-first-run-snapshots/60-columns-low-height.expected.txt b/apps/cli/tests/tui-first-run-snapshots/60-columns-low-height.expected.txt new file mode 100644 index 0000000000..d47dfcac84 --- /dev/null +++ b/apps/cli/tests/tui-first-run-snapshots/60-columns-low-height.expected.txt @@ -0,0 +1,31 @@ +overlay 60x12 rows=10 +0| "╭──────────────────────────────────────────────────────────╮" + style 0-59 dim +1| "│ DeepSeek Harness │" + style 0-0 dim + style 22-37 fg=blue bold + style 59-59 dim +2| "│ │" + style 0-0 dim + style 59-59 dim +3| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" + style 0-0 dim + style 59-59 dim +4| "│ │" + style 0-0 dim + style 59-59 dim +5| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验 │" + style 0-0 dim + style 59-59 dim +6| "├──────────────────────────────────────────────────────────┤" + style 0-59 dim +7| "│ Enter 继续 │" + style 0-0 dim + style 24-34 fg=bright-magenta bold + style 59-59 dim +8| "│ ↑/↓ 滚动 ↓ │" + style 0-0 dim + style 24-35 dim + style 59-59 dim +9| "╰──────────────────────────────────────────────────────────╯" + style 0-59 dim diff --git a/apps/cli/tests/snapshots/tui-first-run-welcome/60-columns.expected.txt b/apps/cli/tests/tui-first-run-snapshots/60-columns.expected.txt similarity index 50% rename from apps/cli/tests/snapshots/tui-first-run-welcome/60-columns.expected.txt rename to apps/cli/tests/tui-first-run-snapshots/60-columns.expected.txt index 8cbafd5d27..f3d6bd6390 100644 --- a/apps/cli/tests/snapshots/tui-first-run-welcome/60-columns.expected.txt +++ b/apps/cli/tests/tui-first-run-snapshots/60-columns.expected.txt @@ -1,98 +1,90 @@ -terminal 60x30 buffer=normal length=34 base=4 viewport=4 -lifecycle started=0 stopped=0 progress=inactive -title "" -cursor visible column=0 viewportRow=29 bufferRow=33 -viewport -4| " DEEPSEEK HARNESS" - style 1-8 fg=bright-magenta bold - style 10-16 bold -5| "╭──────────────────────────────────────────────────────────╮" +overlay 60x30 rows=27 +0| "╭──────────────────────────────────────────────────────────╮" style 0-59 dim -6| "│ ▄▄▄▄▄▄ ▄▄ │" +1| "│ ▄▄▄▄▄▄ ▄▄ │" style 0-0 dim style 23-36 fg=blue style 59-59 dim -7| "│ ▄████████▄ ▀████▀ │" +2| "│ ▄████████▄ ▀████▀ │" style 0-0 dim style 21-38 fg=blue style 59-59 dim -8| "│ █▀▀▀▀███████▄██▀ │" +3| "│ █▀▀▀▀███████▄██▀ │" style 0-0 dim style 22-37 fg=blue style 59-59 dim -9| "│ █▄ ▀███ ▀███ │" +4| "│ █▄ ▀███ ▀███ │" style 0-0 dim style 22-36 fg=blue style 59-59 dim -10| "│ ▀█▄ ▀█████ │" +5| "│ ▀█▄ ▀█████ │" style 0-0 dim style 23-36 fg=blue style 59-59 dim -11| "│ ▀█▄▄ █▄▄▀███▄ │" +6| "│ ▀█▄▄ █▄▄▀███▄ │" style 0-0 dim style 23-36 fg=blue style 59-59 dim -12| "│ ▀▀▀▀▀▀ │" +7| "│ ▀▀▀▀▀▀ │" style 0-0 dim style 25-34 fg=blue style 59-59 dim -13| "│ │" +8| "│ │" style 0-0 dim style 59-59 dim -14| "│ DeepSeek Harness │" +9| "│ DeepSeek Harness │" style 0-0 dim style 22-37 fg=blue bold style 59-59 dim +10| "│ │" + style 0-0 dim + style 59-59 dim +11| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" + style 0-0 dim + style 59-59 dim +12| "│ │" + style 0-0 dim + style 59-59 dim +13| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验 │" + style 0-0 dim + style 59-59 dim +14| "│ 难免粗粝。 │" + style 0-0 dim + style 59-59 dim 15| "│ │" style 0-0 dim style 59-59 dim -16| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" +16| "│ “如切如磋,如琢如磨。” │" style 0-0 dim + style 2-23 bold style 59-59 dim 17| "│ │" style 0-0 dim style 59-59 dim -18| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验 │" +18| "│ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实 │" style 0-0 dim style 59-59 dim -19| "│ 难免粗粝。 │" +19| "│ 使用中暴露的问题,也可能促使我们重新审视,甚至推翻已有的 │" style 0-0 dim style 59-59 dim -20| "│ │" +20| "│ 设计。 │" style 0-0 dim style 59-59 dim -21| "│ “如切如磋,如琢如磨。” │" - style 0-0 dim - style 2-23 bold - style 59-59 dim -22| "│ │" +21| "│ │" style 0-0 dim style 59-59 dim -23| "│ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实 │" +22| "│ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能 │" style 0-0 dim style 59-59 dim -24| "│ 使用中暴露的问题,也可能促使我们重新审视,甚至推翻已有的 │" - style 0-0 dim - style 59-59 dim -25| "│ 设计。 │" - style 0-0 dim - style 59-59 dim -26| "│ │" - style 0-0 dim - style 59-59 dim -27| "│ 我们尤其希望听见那些失败、困惑与不顺手的时刻——如果它未能 │" - style 0-0 dim - style 59-59 dim -28| "├──────────────────────────────────────────────────────────┤" +23| "├──────────────────────────────────────────────────────────┤" style 0-59 dim -29| "│ Enter 继续 │" +24| "│ Enter 继续 │" style 0-0 dim style 24-34 fg=bright-magenta bold style 59-59 dim -30| "│ ↑/↓ 滚动 ↓ │" +25| "│ ↑/↓ 滚动 ↓ │" style 0-0 dim style 24-35 dim style 59-59 dim -31| "╰──────────────────────────────────────────────────────────╯" +26| "╰──────────────────────────────────────────────────────────╯" style 0-59 dim -32-33| diff --git a/apps/cli/tests/snapshots/tui-first-run-welcome/80-columns.expected.txt b/apps/cli/tests/tui-first-run-snapshots/80-columns.expected.txt similarity index 58% rename from apps/cli/tests/snapshots/tui-first-run-welcome/80-columns.expected.txt rename to apps/cli/tests/tui-first-run-snapshots/80-columns.expected.txt index 9c3287e290..500c00efbc 100644 --- a/apps/cli/tests/snapshots/tui-first-run-welcome/80-columns.expected.txt +++ b/apps/cli/tests/tui-first-run-snapshots/80-columns.expected.txt @@ -1,101 +1,93 @@ -terminal 80x30 buffer=normal length=33 base=3 viewport=3 -lifecycle started=0 stopped=0 progress=inactive -title "" -cursor visible column=0 viewportRow=29 bufferRow=32 -viewport -3| " DEEPSEEK HARNESS" - style 1-8 fg=bright-magenta bold - style 10-16 bold -4| "╭──────────────────────────────────────────────────────────────────────────────╮" +overlay 80x30 rows=27 +0| "╭──────────────────────────────────────────────────────────────────────────────╮" style 0-79 dim -5| "│ ▄▄▄▄▄▄▄██▀ █▄ ▄ │" +1| "│ ▄▄▄▄▄▄▄██▀ █▄ ▄ │" style 0-0 dim style 26-53 fg=blue style 79-79 dim -6| "│ ▄███████████▄▄ ███▄▄████ │" +2| "│ ▄███████████▄▄ ███▄▄████ │" style 0-0 dim style 26-53 fg=blue style 79-79 dim -7| "│ ████████████████▄ ▀██████▀ │" +3| "│ ████████████████▄ ▀██████▀ │" style 0-0 dim style 26-52 fg=blue style 79-79 dim -8| "│ ██▀▀▀▀▀████████████▄▄██▀ │" +4| "│ ██▀▀▀▀▀████████████▄▄██▀ │" style 0-0 dim style 28-51 fg=blue style 79-79 dim -9| "│ ██ ▀█████▄ ▀█████ │" +5| "│ ██ ▀█████▄ ▀█████ │" style 0-0 dim style 28-50 fg=blue style 79-79 dim -10| "│ ██▄ ▀████▄ ▄████ │" +6| "│ ██▄ ▀████▄ ▄████ │" style 0-0 dim style 28-50 fg=blue style 79-79 dim -11| "│ ██▄ ████████▀ │" +7| "│ ██▄ ████████▀ │" style 0-0 dim style 29-50 fg=blue style 79-79 dim -12| "│ ██▄ ▄▄ ▀█████▀ │" +8| "│ ██▄ ▄▄ ▀█████▀ │" style 0-0 dim style 29-49 fg=blue style 79-79 dim -13| "│ ▀███▄▄▄███▄ ████▄▄ │" +9| "│ ▀███▄▄▄███▄ ████▄▄ │" style 0-0 dim style 29-50 fg=blue style 79-79 dim -14| "│ ▀▀▀███████▀▀ │" +10| "│ ▀▀▀███████▀▀ │" style 0-0 dim style 31-47 fg=blue style 79-79 dim +11| "│ │" + style 0-0 dim + style 79-79 dim +12| "│ DeepSeek Harness │" + style 0-0 dim + style 32-47 fg=blue bold + style 79-79 dim +13| "│ │" + style 0-0 dim + style 79-79 dim +14| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" + style 0-0 dim + style 79-79 dim 15| "│ │" style 0-0 dim style 79-79 dim -16| "│ DeepSeek Harness │" +16| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" style 0-0 dim - style 32-47 fg=blue bold style 79-79 dim 17| "│ │" style 0-0 dim style 79-79 dim -18| "│ 感谢您愿意拨冗试用 DeepSeek Harness。 │" +18| "│ “如切如磋,如琢如磨。” │" style 0-0 dim + style 2-23 bold style 79-79 dim 19| "│ │" style 0-0 dim style 79-79 dim -20| "│ 目前的版本仍处于内部测试阶段,有些功能仍待完善,有些体验难免粗粝。 │" +20| "│ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的问题,也 │" style 0-0 dim style 79-79 dim -21| "│ │" +21| "│ 可能促使我们重新审视,甚至推翻已有的设计。 │" style 0-0 dim style 79-79 dim -22| "│ “如切如磋,如琢如磨。” │" - style 0-0 dim - style 2-23 bold - style 79-79 dim -23| "│ │" +22| "│ │" style 0-0 dim style 79-79 dim -24| "│ 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中暴露的问题,也 │" - style 0-0 dim - style 79-79 dim -25| "│ 可能促使我们重新审视,甚至推翻已有的设计。 │" - style 0-0 dim - style 79-79 dim -26| "│ │" - style 0-0 dim - style 79-79 dim -27| "├──────────────────────────────────────────────────────────────────────────────┤" +23| "├──────────────────────────────────────────────────────────────────────────────┤" style 0-79 dim -28| "│ Enter 继续 │" +24| "│ Enter 继续 │" style 0-0 dim style 34-44 fg=bright-magenta bold style 79-79 dim -29| "│ ↑/↓ 滚动 ↓ │" +25| "│ ↑/↓ 滚动 ↓ │" style 0-0 dim style 34-45 dim style 79-79 dim -30| "╰──────────────────────────────────────────────────────────────────────────────╯" +26| "╰──────────────────────────────────────────────────────────────────────────────╯" style 0-79 dim -31-32| diff --git a/apps/cli/tests/tui-keyless-smoke.e2e.ts b/apps/cli/tests/tui-keyless-smoke.e2e.ts index 10e2c88e95..12c018f255 100644 --- a/apps/cli/tests/tui-keyless-smoke.e2e.ts +++ b/apps/cli/tests/tui-keyless-smoke.e2e.ts @@ -25,7 +25,7 @@ const dshBinScript = fileURLToPath(new URL('../src/bin.ts', import.meta.url)) // needs no config argument at all; these are the overlays under test. const scriptedConfigPath = fileURLToPath(new URL('./fixtures/tui-scripted.cordis.yml', import.meta.url)) const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url)) -const firstRunSnapshots = fileURLToPath(new URL('./snapshots/tui-first-run-welcome/', import.meta.url)) +const firstRunSnapshots = fileURLToPath(new URL('./tui-first-run-snapshots/', import.meta.url)) const synchronizedFrameEnd = '\x1b[?2026l' /** @@ -166,7 +166,24 @@ function smoke(overrides: Partial & { const firstRunCopy = TUI_FIRST_RUN_WELCOME_NOTICE_COPY[TUI_FIRST_RUN_WELCOME_NOTICE_LOCALE] -/** Project the first synchronized PTY frame containing `marker` into the stable terminal snapshot format. */ +/** Keep only the overlay rows, excluding platform-specific scrollback and the underlying TUI. */ +function overlaySnapshot(snapshot: string, columns: number, rows: number): string { + const blocks: string[][] = [] + for (const line of snapshot.split('\n')) { + if (/^\d+(?:-\d+)?~?\| /u.test(line)) blocks.push([line]) + else if (line.startsWith(' style ') && blocks.length > 0) blocks.at(-1)?.push(line) + } + const first = blocks.findIndex(block => block[0]?.includes('╭') === true) + const last = blocks.findIndex((block, index) => index >= first && block[0]?.includes('╰') === true) + if (first < 0 || last < first) throw new Error('first-run PTY snapshot has no complete overlay frame') + const overlay = blocks.slice(first, last + 1).flatMap((block, index) => [ + block[0]!.replace(/^\d+(?:-\d+)?(~)?\|/u, `${String(index)}$1|`), + ...block.slice(1), + ]) + return [`overlay ${String(columns)}x${String(rows)} rows=${String(last - first + 1)}`, ...overlay, ''].join('\n') +} + +/** Project the first synchronized PTY frame containing `marker` into an overlay-only snapshot. */ async function firstRunFrameSnapshot( output: string, marker: string, @@ -180,9 +197,7 @@ async function firstRunFrameSnapshot( const terminal = new HeadlessTerminal(columns, rows) try { terminal.write(output.slice(0, frameEnd + synchronizedFrameEnd.length)) - return (await terminal.snapshot()) - .replace(/main-session-[0-9a-f-]{36}/gu, 'main-session-{{uuid}}') - .replace(/\/[^"\s]*dsh-tui-welcome-\d+-[A-Za-z0-9]+/gu, '/tmp/dsh-tui-welcome') + return overlaySnapshot(await terminal.snapshot(), columns, rows) } finally { await terminal.dispose() } @@ -212,10 +227,7 @@ describe('dsh TUI keyless smoke (real Loader tree in a PTY)', () => { columns, rows: 30, actions: [ - { waitFor: firstRunCopy.paragraphs[0]!, send: '\r' }, - columns >= 120 - ? { waitFor: firstRunCopy.saving, signal: 'SIGTERM', delayMs: 500 } - : { waitFor: 'main-session-', occurrence: 2, signal: 'SIGTERM' }, + { waitFor: `Enter ${firstRunCopy.continueLabel}`, send: '\r', signalAfterMs: 2_000 }, ], inspect: async (cwd) => { expect(await hasTuiFirstRunWelcomeAcknowledgement(join(cwd, '.dsh'))).toBe(true) @@ -244,8 +256,12 @@ describe('dsh TUI keyless smoke (real Loader tree in a PTY)', () => { rows: 12, actions: [ { waitFor: firstRunCopy.paragraphs[0]!, send: '\x1b[F' }, - { waitFor: '企业微信群', send: '\r' }, - { waitFor: 'main-session-', occurrence: 2, signal: 'SIGTERM' }, + { + waitFor: `Enter ${firstRunCopy.continueLabel}`, + occurrence: 2, + send: '\r', + signalAfterMs: 2_000, + }, ], }) await expect(await firstRunFrameSnapshot(output, firstRunCopy.paragraphs[0]!, 60, 12)) @@ -268,8 +284,7 @@ describe('dsh TUI keyless smoke (real Loader tree in a PTY)', () => { showFirstRunWelcome: true, expectedExitCode: process.platform === 'win32' ? 0 : -15, actions: [ - { waitFor: firstRunCopy.paragraphs[0]!, send: '\r' }, - { waitFor: firstRunCopy.saving, signal: 'SIGTERM', delayMs: 500 }, + { waitFor: `Enter ${firstRunCopy.continueLabel}`, send: '\r', signalAfterMs: 2_000 }, ], }) expect(first).toContain(firstRunCopy.title) @@ -314,8 +329,7 @@ describe('dsh TUI keyless smoke (real Loader tree in a PTY)', () => { showFirstRunWelcome: true, expectedExitCode: -15, actions: [ - { waitFor: firstRunCopy.paragraphs[0]!, send: '\r' }, - { waitFor: firstRunCopy.saving, signal: 'SIGTERM', delayMs: 500 }, + { waitFor: `Enter ${firstRunCopy.continueLabel}`, send: '\r', signalAfterMs: 2_000 }, ], }) expect(next).toContain(firstRunCopy.paragraphs[0]) @@ -515,8 +529,7 @@ describe('dsh CLI keyless smoke (apps/cli through the same PTY)', () => { originalLineCount = before.split('\n').filter(Boolean).length }, actions: [ - { waitFor: firstRunCopy.paragraphs[0]!, send: '\r' }, - { waitFor: firstRunCopy.saving, signal: 'SIGTERM', delayMs: 500 }, + { waitFor: `Enter ${firstRunCopy.continueLabel}`, send: '\r', signalAfterMs: 2_000 }, ], inspect: async (cwd) => { const after = await readFile(logPath(