@cueloop/client 0.1.0-alpha.11 → 0.1.0-alpha.12
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/package.json +7 -7
- package/src/App.autoclose.test.tsx +24 -35
- package/src/App.diff.test.tsx +5 -18
- package/src/App.export.test.tsx +8 -21
- package/src/App.plan-review.test.tsx +21 -52
- package/src/App.readonly.test.tsx +3 -18
- package/src/App.rendering.test.tsx +5 -13
- package/src/App.submit-confirm.test.tsx +7 -25
- package/src/App.test.tsx +13 -52
- package/src/App.tsx +197 -910
- package/src/components/AnnotationCard.stories.tsx +75 -0
- package/src/components/AnnotationCard.tsx +136 -0
- package/src/components/Breadcrumb.stories.tsx +19 -0
- package/src/components/Breadcrumb.tsx +38 -0
- package/src/components/CodeBlock.stories.tsx +25 -0
- package/src/components/CodeBlock.tsx +68 -0
- package/src/components/CompletionOverlay.stories.tsx +23 -0
- package/src/components/CompletionOverlay.tsx +50 -0
- package/src/components/ComposeBar.stories.tsx +18 -0
- package/src/components/ComposeBar.tsx +54 -0
- package/src/components/ConfirmCard.stories.tsx +22 -0
- package/src/components/ConfirmCard.tsx +130 -0
- package/src/components/DiffSheet.stories.tsx +44 -0
- package/src/components/DiffSheet.tsx +243 -0
- package/src/components/InboxList.stories.tsx +18 -0
- package/src/components/InboxList.tsx +42 -0
- package/src/components/PlanSheet.stories.tsx +81 -0
- package/src/components/PlanSheet.tsx +309 -0
- package/src/components/ReviewRail.stories.tsx +103 -0
- package/src/components/ReviewRail.tsx +158 -0
- package/src/components/SettingsDialog.stories.tsx +63 -0
- package/src/components/SettingsDialog.tsx +132 -0
- package/src/components/SettingsRows.stories.tsx +18 -0
- package/src/components/SettingsRows.tsx +92 -0
- package/src/components/__snapshots__/stories.test.tsx.snap +1189 -0
- package/src/components/format.ts +6 -0
- package/src/components/primitives/Button.stories.tsx +32 -0
- package/src/components/primitives/Button.tsx +44 -0
- package/src/components/primitives/Card.stories.tsx +25 -0
- package/src/components/primitives/Card.tsx +58 -0
- package/src/components/primitives/Dialog.stories.tsx +24 -0
- package/src/components/primitives/Dialog.tsx +52 -0
- package/src/components/primitives/StatusBar.stories.tsx +11 -0
- package/src/components/primitives/StatusBar.tsx +22 -0
- package/src/components/primitives/Tabs.stories.tsx +29 -0
- package/src/components/primitives/Tabs.tsx +97 -0
- package/src/components/primitives/Toolbar.stories.tsx +17 -0
- package/src/components/primitives/Toolbar.tsx +14 -0
- package/src/components/stories-app.tsx +94 -0
- package/src/components/stories.test.tsx +51 -0
- package/src/components/story-fixtures.ts +90 -0
- package/src/components/story.ts +66 -0
- package/src/components/syntax-highlight.ts +57 -0
- package/src/components/theme-context.stories.tsx +41 -0
- package/src/components/theme-context.tsx +30 -0
- package/src/key-bindings.test.ts +103 -0
- package/src/key-bindings.ts +332 -0
- package/src/keymap.ts +8 -2
- package/src/run.ts +3 -1
- package/src/session-controller.ts +28 -7
- package/src/test-support.ts +87 -0
- package/src/theme.ts +3 -0
- package/src/view.test.ts +35 -13
- package/src/view.ts +41 -64
- package/src/syntax.test.ts +0 -41
- package/src/syntax.ts +0 -88
package/src/App.test.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import { testRender } from "@opentui/react/test-utils";
|
|
|
13
13
|
import { DaemonServer } from "@cueloop/daemon";
|
|
14
14
|
import type { ReviewSession } from "@cueloop/schema";
|
|
15
15
|
import { App } from "./App";
|
|
16
|
+
import { press, typeText as type, waitForState, waitForText } from "./test-support";
|
|
16
17
|
|
|
17
18
|
const PLAN = `# Migration Plan
|
|
18
19
|
|
|
@@ -49,35 +50,11 @@ async function renderApp(sessionId?: string) {
|
|
|
49
50
|
width: 120,
|
|
50
51
|
height: 32,
|
|
51
52
|
});
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
await Bun.sleep(25);
|
|
55
|
-
await setup.renderOnce();
|
|
56
|
-
}
|
|
57
|
-
await setup.renderOnce();
|
|
53
|
+
// the async daemon connect + first fetch land within the frame wait
|
|
54
|
+
await waitForText(setup, "cueloop");
|
|
58
55
|
return setup;
|
|
59
56
|
}
|
|
60
57
|
|
|
61
|
-
type Setup = Awaited<ReturnType<typeof renderApp>>;
|
|
62
|
-
|
|
63
|
-
/** Drive one key press: letters type as text; named keys use KeyCodes ids. */
|
|
64
|
-
async function press(setup: Setup, k: string): Promise<void> {
|
|
65
|
-
if (k === "enter") setup.mockInput.pressKey("RETURN");
|
|
66
|
-
else if (k === "escape") setup.mockInput.pressKey("ESCAPE");
|
|
67
|
-
else if (k === "backspace") setup.mockInput.pressKey("BACKSPACE");
|
|
68
|
-
else if (k === "left") setup.mockInput.pressKey("ARROW_LEFT");
|
|
69
|
-
else if (k === "right") setup.mockInput.pressKey("ARROW_RIGHT");
|
|
70
|
-
else await type(setup, k);
|
|
71
|
-
await Bun.sleep(15);
|
|
72
|
-
await setup.renderOnce();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function type(setup: Setup, text: string): Promise<void> {
|
|
76
|
-
await setup.mockInput.typeText(text);
|
|
77
|
-
await Bun.sleep(15);
|
|
78
|
-
await setup.renderOnce();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
58
|
describe("plan rendering", () => {
|
|
82
59
|
test("renders the plan with headings, list markers, and the rail", async () => {
|
|
83
60
|
const setup = await renderApp();
|
|
@@ -111,12 +88,10 @@ describe("keyboard grammar", () => {
|
|
|
111
88
|
expect(setup.captureCharFrame()).toContain('comment on "The daemon');
|
|
112
89
|
await type(setup, "Define atomically.");
|
|
113
90
|
await press(setup, "enter");
|
|
114
|
-
await
|
|
115
|
-
await setup.renderOnce();
|
|
91
|
+
await waitForText(setup, "COMMENT");
|
|
116
92
|
const stored = server.core.sessionGet(session.id);
|
|
117
93
|
expect(stored.annotations.length).toBe(1);
|
|
118
94
|
expect(stored.annotations[0]!.body).toBe("Define atomically.");
|
|
119
|
-
expect(setup.captureCharFrame()).toContain("COMMENT");
|
|
120
95
|
});
|
|
121
96
|
|
|
122
97
|
test("span mode: v + l selects words, c anchors the exact span", async () => {
|
|
@@ -128,7 +103,7 @@ describe("keyboard grammar", () => {
|
|
|
128
103
|
await press(setup, "c");
|
|
129
104
|
await type(setup, "Which daemon?");
|
|
130
105
|
await press(setup, "enter");
|
|
131
|
-
await
|
|
106
|
+
await waitForState(setup, () => server.core.sessionGet(session.id).annotations.length === 1);
|
|
132
107
|
const stored = server.core.sessionGet(session.id);
|
|
133
108
|
expect(stored.annotations[0]!.anchor.quote).toBe("The daemon");
|
|
134
109
|
});
|
|
@@ -138,14 +113,10 @@ describe("keyboard grammar", () => {
|
|
|
138
113
|
// move to "- move the store" (h1, h2, p, h2 = 4 steps in)
|
|
139
114
|
for (let i = 0; i < 4; i++) await press(setup, "j");
|
|
140
115
|
await press(setup, "x");
|
|
141
|
-
await
|
|
142
|
-
await setup.renderOnce();
|
|
116
|
+
await waitForText(setup, "[cut]");
|
|
143
117
|
expect(server.core.sessionGet(session.id).workingCopy).not.toContain("move the store");
|
|
144
|
-
expect(setup.captureCharFrame()).toContain("[cut]");
|
|
145
118
|
await press(setup, "x");
|
|
146
|
-
await
|
|
147
|
-
await setup.renderOnce();
|
|
148
|
-
expect(server.core.sessionGet(session.id).workingCopy).toBeUndefined();
|
|
119
|
+
await waitForState(setup, () => server.core.sessionGet(session.id).workingCopy === undefined);
|
|
149
120
|
});
|
|
150
121
|
|
|
151
122
|
test("e runs $EDITOR on the working copy and tracks the diff", async () => {
|
|
@@ -156,10 +127,8 @@ describe("keyboard grammar", () => {
|
|
|
156
127
|
try {
|
|
157
128
|
const setup = await renderApp();
|
|
158
129
|
await press(setup, "e");
|
|
159
|
-
await
|
|
160
|
-
await setup.renderOnce();
|
|
130
|
+
await waitForText(setup, "[edited]");
|
|
161
131
|
expect(server.core.sessionGet(session.id).workingCopy).toContain("very atomically");
|
|
162
|
-
expect(setup.captureCharFrame()).toContain("[edited]");
|
|
163
132
|
} finally {
|
|
164
133
|
delete process.env.CUELOOP_EDITOR;
|
|
165
134
|
}
|
|
@@ -174,14 +143,12 @@ describe("submit", () => {
|
|
|
174
143
|
await press(setup, "c");
|
|
175
144
|
await type(setup, "Needs a phase list.");
|
|
176
145
|
await press(setup, "enter");
|
|
177
|
-
await
|
|
146
|
+
await waitForText(setup, "Review (1)");
|
|
178
147
|
await press(setup, "enter"); // open submit
|
|
179
|
-
await setup.renderOnce();
|
|
180
148
|
expect(setup.captureCharFrame()).toContain("[Changes]");
|
|
181
149
|
await type(setup, "Expand the steps.");
|
|
182
150
|
await press(setup, "enter");
|
|
183
|
-
await
|
|
184
|
-
await setup.renderOnce();
|
|
151
|
+
await waitForText(setup, "✎ feedback sent");
|
|
185
152
|
const stored = server.core.sessionGet(session.id);
|
|
186
153
|
expect(stored.status).toBe("resolved");
|
|
187
154
|
expect(stored.verdict!.kind).toBe("request_changes");
|
|
@@ -193,10 +160,9 @@ describe("submit", () => {
|
|
|
193
160
|
test("approve via ←/→ verdict cycling", async () => {
|
|
194
161
|
const setup = await renderApp();
|
|
195
162
|
await press(setup, "enter");
|
|
196
|
-
await setup.renderOnce();
|
|
197
163
|
expect(setup.captureCharFrame()).toContain("[Approve]"); // no pending items → approve default
|
|
198
164
|
await press(setup, "enter");
|
|
199
|
-
await
|
|
165
|
+
await waitForState(setup, () => server.core.sessionGet(session.id).verdict !== undefined);
|
|
200
166
|
expect(server.core.sessionGet(session.id).verdict!.kind).toBe("approve");
|
|
201
167
|
});
|
|
202
168
|
});
|
|
@@ -204,15 +170,10 @@ describe("submit", () => {
|
|
|
204
170
|
describe("inbox", () => {
|
|
205
171
|
test("inbox mode renders and opens a session", async () => {
|
|
206
172
|
const setup = await testRender(<App home={home} />, { width: 120, height: 32 });
|
|
207
|
-
|
|
208
|
-
await Bun.sleep(25);
|
|
209
|
-
await setup.renderOnce();
|
|
210
|
-
}
|
|
173
|
+
await waitForText(setup, "inbox");
|
|
211
174
|
expect(setup.captureCharFrame()).toContain("inbox (1 pending)");
|
|
212
175
|
expect(setup.captureCharFrame()).toContain("Migration Plan");
|
|
213
176
|
await press(setup, "enter");
|
|
214
|
-
await
|
|
215
|
-
await setup.renderOnce();
|
|
216
|
-
expect(setup.captureCharFrame()).toContain("Submit review (0)");
|
|
177
|
+
await waitForText(setup, "Submit review (0)");
|
|
217
178
|
});
|
|
218
179
|
});
|