saeeol 1.3.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/saeeol.cjs +3 -1
- package/bunfig.toml +7 -0
- package/package.json +1 -1
- package/src/cli/cmd/tui/preflight.ts +138 -0
- package/src/cli/cmd/tui/thread.ts +20 -0
- package/src/server/routes/instance/httpapi/groups/ltm.ts +93 -0
- package/src/server/routes/instance/httpapi/handlers/ltm.ts +118 -0
- package/src/server/routes/instance/index.ts +96 -1
- package/test/smoke/.tui-debug-output.txt +1 -0
- package/test/smoke/.tui-debug-plain.txt +1 -0
- package/test/smoke/.tui-input-report.txt +110 -0
- package/test/smoke/.tui-leader-report.txt +70 -0
- package/test/smoke/.tui-scroll-report.txt +66 -0
- package/test/smoke/.tui-slash-report.txt +146 -0
- package/test/smoke/.tui-system-report.txt +62 -0
- package/test/smoke/.tui-walkthrough-report.txt +122 -0
- package/test/smoke/smoke-tui-pty.test.ts +123 -0
- package/test/smoke/smoke-tui.mjs +83 -0
- package/test/smoke/tui-walkthrough-driver.ts +232 -0
- package/test/smoke/tui-walkthrough-input.test.ts +286 -0
- package/test/smoke/tui-walkthrough-leader.test.ts +175 -0
- package/test/smoke/tui-walkthrough-scroll.test.ts +177 -0
- package/test/smoke/tui-walkthrough-slash.test.ts +302 -0
- package/test/smoke/tui-walkthrough-system.test.ts +210 -0
- package/test/smoke/tui-walkthrough.test.ts +520 -0
- package/.turbo/turbo-typecheck.log +0 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tui-walkthrough-system.test.ts — 시스템 토글 + 부팅 + 종료 검증
|
|
3
|
+
*
|
|
4
|
+
* - TUI 부팅 (alternate screen 진입)
|
|
5
|
+
* - Home 화면 렌더링
|
|
6
|
+
* - 커맨드 팔레트에서 시스템 명령 선택
|
|
7
|
+
* - 모든 토글 명령: notifications, animations, file_context,
|
|
8
|
+
* paste_summary, diffwrap, terminal_title, session_directory_filter
|
|
9
|
+
* - debug overlay, console toggle
|
|
10
|
+
* - /restart, /exit, /quit, /q, /rs
|
|
11
|
+
* - 전체 스냅샷 에러 재검사
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, expect, test, beforeAll, afterAll } from "bun:test"
|
|
15
|
+
import { tmpdir, disposeAllInstances } from "../fixture/fixture"
|
|
16
|
+
import * as Log from "@saeeol/core/util/log"
|
|
17
|
+
import { Flag } from "@saeeol/core/flag/flag"
|
|
18
|
+
import { TuiDriver, Key, hasError } from "./tui-walkthrough-driver"
|
|
19
|
+
import path from "path"
|
|
20
|
+
|
|
21
|
+
void Log.init({ print: false })
|
|
22
|
+
|
|
23
|
+
describe("TUI walkthrough: system + boot + exit", () => {
|
|
24
|
+
let driver: TuiDriver
|
|
25
|
+
let tmp: Awaited<ReturnType<typeof tmpdir>>
|
|
26
|
+
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
tmp = await tmpdir({ git: true, config: {} })
|
|
29
|
+
Flag.SAEEOL_EXPERIMENTAL_HTTPAPI = false
|
|
30
|
+
driver = new TuiDriver(tmp.path)
|
|
31
|
+
await driver.wait(6000)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
await driver.saveReport(".tui-system-report.txt")
|
|
36
|
+
await driver.kill()
|
|
37
|
+
await disposeAllInstances()
|
|
38
|
+
Flag.SAEEOL_EXPERIMENTAL_HTTPAPI = true
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// ── 부팅 검증 ──
|
|
42
|
+
|
|
43
|
+
test("boot: TUI enters alternate screen", async () => {
|
|
44
|
+
driver.snapshot("boot")
|
|
45
|
+
expect(driver.output).toMatch(/\x1b\[\?9001h|\x1b\[\?1004h/)
|
|
46
|
+
expect(driver.errors()).toHaveLength(0)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test("home: renders content", async () => {
|
|
50
|
+
const { plain } = driver.snapshot("home")
|
|
51
|
+
expect(plain.length).toBeGreaterThan(0)
|
|
52
|
+
expect(driver.errors()).toHaveLength(0)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// ── 시스템 슬래시 명령 ──
|
|
56
|
+
|
|
57
|
+
test("/restart → restart attempt", async () => {
|
|
58
|
+
await driver.slash("restart")
|
|
59
|
+
driver.snapshot("slash-restart")
|
|
60
|
+
expect(driver.errors()).toHaveLength(0)
|
|
61
|
+
// restart 후 재부팅 대기
|
|
62
|
+
await driver.wait(6000)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test("/rs → restart alias", async () => {
|
|
66
|
+
await driver.slash("rs")
|
|
67
|
+
driver.snapshot("slash-rs")
|
|
68
|
+
expect(driver.errors()).toHaveLength(0)
|
|
69
|
+
await driver.wait(6000)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// ── 시스템 토글 (커맨드 팔레트로 진입) ──
|
|
73
|
+
// 이들은 슬래시 명령이 아니라 커맨드 팔레트(ctrl+p)에서 검색으로 선택
|
|
74
|
+
|
|
75
|
+
test("toggle: notifications via palette", async () => {
|
|
76
|
+
// 커맨드 팔레트 열고 명령 검색
|
|
77
|
+
driver.write(Key.ctrlP)
|
|
78
|
+
await driver.wait(1000)
|
|
79
|
+
driver.write("notifications")
|
|
80
|
+
await driver.wait(500)
|
|
81
|
+
driver.write(Key.enter)
|
|
82
|
+
await driver.wait(500)
|
|
83
|
+
driver.snapshot("toggle-notifications")
|
|
84
|
+
expect(driver.errors()).toHaveLength(0)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test("toggle: animations via palette", async () => {
|
|
88
|
+
driver.write(Key.ctrlP)
|
|
89
|
+
await driver.wait(1000)
|
|
90
|
+
driver.write("animations")
|
|
91
|
+
await driver.wait(500)
|
|
92
|
+
driver.write(Key.enter)
|
|
93
|
+
await driver.wait(500)
|
|
94
|
+
driver.snapshot("toggle-animations")
|
|
95
|
+
expect(driver.errors()).toHaveLength(0)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test("toggle: file context via palette", async () => {
|
|
99
|
+
driver.write(Key.ctrlP)
|
|
100
|
+
await driver.wait(1000)
|
|
101
|
+
driver.write("file context")
|
|
102
|
+
await driver.wait(500)
|
|
103
|
+
driver.write(Key.enter)
|
|
104
|
+
await driver.wait(500)
|
|
105
|
+
driver.snapshot("toggle-file-context")
|
|
106
|
+
expect(driver.errors()).toHaveLength(0)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test("toggle: paste summary via palette", async () => {
|
|
110
|
+
driver.write(Key.ctrlP)
|
|
111
|
+
await driver.wait(1000)
|
|
112
|
+
driver.write("paste summary")
|
|
113
|
+
await driver.wait(500)
|
|
114
|
+
driver.write(Key.enter)
|
|
115
|
+
await driver.wait(500)
|
|
116
|
+
driver.snapshot("toggle-paste-summary")
|
|
117
|
+
expect(driver.errors()).toHaveLength(0)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test("toggle: diffwrap via palette", async () => {
|
|
121
|
+
driver.write(Key.ctrlP)
|
|
122
|
+
await driver.wait(1000)
|
|
123
|
+
driver.write("diffwrap")
|
|
124
|
+
await driver.wait(500)
|
|
125
|
+
driver.write(Key.enter)
|
|
126
|
+
await driver.wait(500)
|
|
127
|
+
driver.snapshot("toggle-diffwrap")
|
|
128
|
+
expect(driver.errors()).toHaveLength(0)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test("toggle: session directory filter via palette", async () => {
|
|
132
|
+
driver.write(Key.ctrlP)
|
|
133
|
+
await driver.wait(1000)
|
|
134
|
+
driver.write("session directory filter")
|
|
135
|
+
await driver.wait(500)
|
|
136
|
+
driver.write(Key.enter)
|
|
137
|
+
await driver.wait(500)
|
|
138
|
+
driver.snapshot("toggle-session-dir-filter")
|
|
139
|
+
expect(driver.errors()).toHaveLength(0)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// ── 디버그/콘솔 ──
|
|
143
|
+
|
|
144
|
+
test("debug overlay via palette", async () => {
|
|
145
|
+
driver.write(Key.ctrlP)
|
|
146
|
+
await driver.wait(1000)
|
|
147
|
+
driver.write("debug")
|
|
148
|
+
await driver.wait(500)
|
|
149
|
+
driver.write(Key.enter)
|
|
150
|
+
await driver.wait(500)
|
|
151
|
+
driver.snapshot("debug-overlay")
|
|
152
|
+
expect(driver.errors()).toHaveLength(0)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
test("console toggle via palette", async () => {
|
|
156
|
+
driver.write(Key.ctrlP)
|
|
157
|
+
await driver.wait(1000)
|
|
158
|
+
driver.write("console")
|
|
159
|
+
await driver.wait(500)
|
|
160
|
+
driver.write(Key.enter)
|
|
161
|
+
await driver.wait(500)
|
|
162
|
+
driver.snapshot("console-toggle")
|
|
163
|
+
expect(driver.errors()).toHaveLength(0)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// ── org 전환 (조건부) ──
|
|
167
|
+
|
|
168
|
+
test("/org → org switch dialog", async () => {
|
|
169
|
+
await driver.slash("org")
|
|
170
|
+
driver.snapshot("slash-org")
|
|
171
|
+
expect(driver.errors()).toHaveLength(0)
|
|
172
|
+
await driver.dismiss()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test("/orgs → alias", async () => {
|
|
176
|
+
await driver.slash("orgs")
|
|
177
|
+
driver.snapshot("slash-orgs")
|
|
178
|
+
expect(driver.errors()).toHaveLength(0)
|
|
179
|
+
await driver.dismiss()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
test("/switch-org → alias", async () => {
|
|
183
|
+
await driver.slash("switch-org")
|
|
184
|
+
driver.snapshot("slash-switch-org")
|
|
185
|
+
expect(driver.errors()).toHaveLength(0)
|
|
186
|
+
await driver.dismiss()
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
// ── 종료 ──
|
|
190
|
+
|
|
191
|
+
test("/q → exit alias", async () => {
|
|
192
|
+
await driver.slash("q")
|
|
193
|
+
await driver.wait(2000)
|
|
194
|
+
driver.snapshot("slash-q-exit")
|
|
195
|
+
expect(driver.errors()).toHaveLength(0)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// ── 전체 스냅샷 에러 재검사 ──
|
|
199
|
+
|
|
200
|
+
test("all snapshots: no errors in any screen", async () => {
|
|
201
|
+
const allErrors: string[] = []
|
|
202
|
+
for (const snap of driver.snapshots) {
|
|
203
|
+
const snapErrors = hasError(snap.plain)
|
|
204
|
+
if (snapErrors.length > 0) {
|
|
205
|
+
allErrors.push(`[${snap.name}]: ${snapErrors.join("; ")}`)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
expect(allErrors).toHaveLength(0)
|
|
209
|
+
})
|
|
210
|
+
})
|