gogcli-mcp-docs 1.0.9 → 2.0.2
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/README.md +5 -2
- package/SKILL.md +4 -4
- package/dist/index.js +10 -550
- package/manifest.json +4 -168
- package/package.json +13 -2
- package/src/index.ts +4 -2
- package/tests/tools/docs-extra.test.ts +128 -246
|
@@ -1,35 +1,22 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { registerExtraDocsTools } from '../../src/tools/docs-extra.js';
|
|
4
|
+
import * as lib from '../../../gogcli-mcp/src/lib.js';
|
|
3
5
|
|
|
4
|
-
vi.mock('../../../gogcli-mcp/src/lib.js', async () => {
|
|
5
|
-
const
|
|
6
|
-
const mockRun = vi.fn<(args: string[], options?: { account?: string }) => Promise<string>>();
|
|
7
|
-
const accountParam = z.string().optional().describe('Google account email');
|
|
8
|
-
const toText = (output: string) => ({ content: [{ type: 'text' as const, text: output }] });
|
|
9
|
-
const toError = (err: unknown) =>
|
|
10
|
-
toText(err instanceof Error ? `Error: ${err.message}` : String(err));
|
|
11
|
-
|
|
6
|
+
vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
|
|
7
|
+
const actual = await importOriginal<typeof lib>();
|
|
12
8
|
return {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
accountParam,
|
|
16
|
-
toText,
|
|
17
|
-
toError,
|
|
18
|
-
runOrDiagnose: async (args: string[], options: { account?: string }) => {
|
|
19
|
-
try {
|
|
20
|
-
return toText(await mockRun(args, options));
|
|
21
|
-
} catch (err) {
|
|
22
|
-
return toError(err);
|
|
23
|
-
}
|
|
24
|
-
},
|
|
9
|
+
...actual,
|
|
10
|
+
runOrDiagnose: vi.fn(),
|
|
25
11
|
};
|
|
26
12
|
});
|
|
27
13
|
|
|
28
|
-
import { run } from '../../../gogcli-mcp/src/lib.js';
|
|
29
|
-
import { registerExtraDocsTools } from '../../src/tools/docs-extra.js';
|
|
30
|
-
|
|
31
14
|
type ToolHandler = (args: Record<string, unknown>) => Promise<{ content: Array<{ type: string; text: string }> }>;
|
|
32
15
|
|
|
16
|
+
function toText(text: string) {
|
|
17
|
+
return { content: [{ type: 'text', text }] };
|
|
18
|
+
}
|
|
19
|
+
|
|
33
20
|
function setupHandlers(): Map<string, ToolHandler> {
|
|
34
21
|
const server = new McpServer({ name: 'test', version: '0.0.0' });
|
|
35
22
|
const handlers = new Map<string, ToolHandler>();
|
|
@@ -46,608 +33,503 @@ beforeEach(() => vi.clearAllMocks());
|
|
|
46
33
|
// --- gog_docs_copy ---
|
|
47
34
|
|
|
48
35
|
describe('gog_docs_copy', () => {
|
|
49
|
-
it('calls
|
|
50
|
-
vi.mocked(
|
|
36
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
37
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
51
38
|
const handlers = setupHandlers();
|
|
52
|
-
|
|
53
|
-
expect(
|
|
54
|
-
expect(result.content[0].text).toContain('newid');
|
|
39
|
+
await handlers.get('gog_docs_copy')!({ docId: 'abc', title: 'My Copy' });
|
|
40
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'copy', 'abc', 'My Copy'], { account: undefined });
|
|
55
41
|
});
|
|
56
42
|
|
|
57
43
|
it('includes --parent when provided', async () => {
|
|
58
|
-
vi.mocked(
|
|
44
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
59
45
|
const handlers = setupHandlers();
|
|
60
46
|
await handlers.get('gog_docs_copy')!({ docId: 'abc', title: 'Copy', parent: 'folder123' });
|
|
61
|
-
expect(
|
|
47
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
62
48
|
['docs', 'copy', 'abc', 'Copy', '--parent=folder123'],
|
|
63
49
|
{ account: undefined },
|
|
64
50
|
);
|
|
65
51
|
});
|
|
66
52
|
|
|
67
53
|
it('omits --parent when not provided', async () => {
|
|
68
|
-
vi.mocked(
|
|
54
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
69
55
|
const handlers = setupHandlers();
|
|
70
56
|
await handlers.get('gog_docs_copy')!({ docId: 'abc', title: 'Copy' });
|
|
71
|
-
expect(
|
|
57
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'copy', 'abc', 'Copy'], { account: undefined });
|
|
72
58
|
});
|
|
73
59
|
|
|
74
60
|
it('forwards account override', async () => {
|
|
75
|
-
vi.mocked(
|
|
61
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
76
62
|
const handlers = setupHandlers();
|
|
77
63
|
await handlers.get('gog_docs_copy')!({ docId: 'abc', title: 'Copy', account: 'other@gmail.com' });
|
|
78
|
-
expect(
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('returns error text on failure', async () => {
|
|
82
|
-
vi.mocked(run).mockRejectedValue(new Error('Copy failed'));
|
|
83
|
-
const handlers = setupHandlers();
|
|
84
|
-
const result = await handlers.get('gog_docs_copy')!({ docId: 'bad', title: 'x' });
|
|
85
|
-
expect(result.content[0].text).toBe('Error: Copy failed');
|
|
64
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'copy', 'abc', 'Copy'], { account: 'other@gmail.com' });
|
|
86
65
|
});
|
|
87
66
|
});
|
|
88
67
|
|
|
89
68
|
// --- gog_docs_delete ---
|
|
90
69
|
|
|
91
70
|
describe('gog_docs_delete', () => {
|
|
92
|
-
it('calls
|
|
93
|
-
vi.mocked(
|
|
71
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
72
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
94
73
|
const handlers = setupHandlers();
|
|
95
74
|
await handlers.get('gog_docs_delete')!({ docId: 'abc', start: 5, end: 10 });
|
|
96
|
-
expect(
|
|
75
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
97
76
|
['docs', 'delete', '--start=5', '--end=10', 'abc'],
|
|
98
77
|
{ account: undefined },
|
|
99
78
|
);
|
|
100
79
|
});
|
|
101
80
|
|
|
102
81
|
it('includes --tab-id when provided', async () => {
|
|
103
|
-
vi.mocked(
|
|
82
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
104
83
|
const handlers = setupHandlers();
|
|
105
84
|
await handlers.get('gog_docs_delete')!({ docId: 'abc', start: 1, end: 5, tabId: 'tab1' });
|
|
106
|
-
expect(
|
|
85
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
107
86
|
['docs', 'delete', '--start=1', '--end=5', 'abc', '--tab-id=tab1'],
|
|
108
87
|
{ account: undefined },
|
|
109
88
|
);
|
|
110
89
|
});
|
|
111
90
|
|
|
112
91
|
it('omits --tab-id when not provided', async () => {
|
|
113
|
-
vi.mocked(
|
|
92
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
114
93
|
const handlers = setupHandlers();
|
|
115
94
|
await handlers.get('gog_docs_delete')!({ docId: 'abc', start: 1, end: 5 });
|
|
116
|
-
expect(
|
|
95
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
117
96
|
['docs', 'delete', '--start=1', '--end=5', 'abc'],
|
|
118
97
|
{ account: undefined },
|
|
119
98
|
);
|
|
120
99
|
});
|
|
121
|
-
|
|
122
|
-
it('returns error text on failure', async () => {
|
|
123
|
-
vi.mocked(run).mockRejectedValue(new Error('Delete failed'));
|
|
124
|
-
const handlers = setupHandlers();
|
|
125
|
-
const result = await handlers.get('gog_docs_delete')!({ docId: 'bad', start: 1, end: 5 });
|
|
126
|
-
expect(result.content[0].text).toBe('Error: Delete failed');
|
|
127
|
-
});
|
|
128
100
|
});
|
|
129
101
|
|
|
130
102
|
// --- gog_docs_edit ---
|
|
131
103
|
|
|
132
104
|
describe('gog_docs_edit', () => {
|
|
133
|
-
it('calls
|
|
134
|
-
vi.mocked(
|
|
105
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
106
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
135
107
|
const handlers = setupHandlers();
|
|
136
108
|
await handlers.get('gog_docs_edit')!({ docId: 'abc', find: 'old', replace: 'new' });
|
|
137
|
-
expect(
|
|
109
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
138
110
|
['docs', 'edit', 'abc', 'old', 'new'],
|
|
139
111
|
{ account: undefined },
|
|
140
112
|
);
|
|
141
113
|
});
|
|
142
114
|
|
|
143
115
|
it('includes --match-case when true', async () => {
|
|
144
|
-
vi.mocked(
|
|
116
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
145
117
|
const handlers = setupHandlers();
|
|
146
118
|
await handlers.get('gog_docs_edit')!({ docId: 'abc', find: 'old', replace: 'new', matchCase: true });
|
|
147
|
-
expect(
|
|
119
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
148
120
|
['docs', 'edit', 'abc', 'old', 'new', '--match-case'],
|
|
149
121
|
{ account: undefined },
|
|
150
122
|
);
|
|
151
123
|
});
|
|
152
124
|
|
|
153
125
|
it('omits --match-case when false', async () => {
|
|
154
|
-
vi.mocked(
|
|
126
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
155
127
|
const handlers = setupHandlers();
|
|
156
128
|
await handlers.get('gog_docs_edit')!({ docId: 'abc', find: 'old', replace: 'new', matchCase: false });
|
|
157
|
-
expect(
|
|
129
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
158
130
|
['docs', 'edit', 'abc', 'old', 'new'],
|
|
159
131
|
{ account: undefined },
|
|
160
132
|
);
|
|
161
133
|
});
|
|
162
|
-
|
|
163
|
-
it('returns error text on failure', async () => {
|
|
164
|
-
vi.mocked(run).mockRejectedValue(new Error('Edit failed'));
|
|
165
|
-
const handlers = setupHandlers();
|
|
166
|
-
const result = await handlers.get('gog_docs_edit')!({ docId: 'bad', find: 'x', replace: 'y' });
|
|
167
|
-
expect(result.content[0].text).toBe('Error: Edit failed');
|
|
168
|
-
});
|
|
169
134
|
});
|
|
170
135
|
|
|
171
136
|
// --- gog_docs_export ---
|
|
172
137
|
|
|
173
138
|
describe('gog_docs_export', () => {
|
|
174
|
-
it('calls
|
|
175
|
-
vi.mocked(
|
|
139
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
140
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
176
141
|
const handlers = setupHandlers();
|
|
177
|
-
|
|
178
|
-
expect(
|
|
179
|
-
expect(result.content[0].text).toContain('Exported');
|
|
142
|
+
await handlers.get('gog_docs_export')!({ docId: 'abc' });
|
|
143
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'export', 'abc'], { account: undefined });
|
|
180
144
|
});
|
|
181
145
|
|
|
182
146
|
it('includes --format when provided', async () => {
|
|
183
|
-
vi.mocked(
|
|
147
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
184
148
|
const handlers = setupHandlers();
|
|
185
149
|
await handlers.get('gog_docs_export')!({ docId: 'abc', format: 'html' });
|
|
186
|
-
expect(
|
|
150
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
187
151
|
['docs', 'export', 'abc', '--format=html'],
|
|
188
152
|
{ account: undefined },
|
|
189
153
|
);
|
|
190
154
|
});
|
|
191
155
|
|
|
192
156
|
it('includes --out when provided', async () => {
|
|
193
|
-
vi.mocked(
|
|
157
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
194
158
|
const handlers = setupHandlers();
|
|
195
159
|
await handlers.get('gog_docs_export')!({ docId: 'abc', out: '/tmp/doc.pdf' });
|
|
196
|
-
expect(
|
|
160
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
197
161
|
['docs', 'export', 'abc', '--out=/tmp/doc.pdf'],
|
|
198
162
|
{ account: undefined },
|
|
199
163
|
);
|
|
200
164
|
});
|
|
201
165
|
|
|
202
166
|
it('includes both --format and --out when provided', async () => {
|
|
203
|
-
vi.mocked(
|
|
167
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
204
168
|
const handlers = setupHandlers();
|
|
205
169
|
await handlers.get('gog_docs_export')!({ docId: 'abc', format: 'txt', out: '/tmp/doc.txt' });
|
|
206
|
-
expect(
|
|
170
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
207
171
|
['docs', 'export', 'abc', '--format=txt', '--out=/tmp/doc.txt'],
|
|
208
172
|
{ account: undefined },
|
|
209
173
|
);
|
|
210
174
|
});
|
|
211
175
|
|
|
212
176
|
it('omits optional flags when not provided', async () => {
|
|
213
|
-
vi.mocked(
|
|
177
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
214
178
|
const handlers = setupHandlers();
|
|
215
179
|
await handlers.get('gog_docs_export')!({ docId: 'abc' });
|
|
216
|
-
expect(
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('returns error text on failure', async () => {
|
|
220
|
-
vi.mocked(run).mockRejectedValue(new Error('Export failed'));
|
|
221
|
-
const handlers = setupHandlers();
|
|
222
|
-
const result = await handlers.get('gog_docs_export')!({ docId: 'bad' });
|
|
223
|
-
expect(result.content[0].text).toBe('Error: Export failed');
|
|
180
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'export', 'abc'], { account: undefined });
|
|
224
181
|
});
|
|
225
182
|
});
|
|
226
183
|
|
|
227
184
|
// --- gog_docs_insert ---
|
|
228
185
|
|
|
229
186
|
describe('gog_docs_insert', () => {
|
|
230
|
-
it('calls
|
|
231
|
-
vi.mocked(
|
|
187
|
+
it('calls runOrDiagnose with content', async () => {
|
|
188
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
232
189
|
const handlers = setupHandlers();
|
|
233
190
|
await handlers.get('gog_docs_insert')!({ docId: 'abc', content: 'Hello world' });
|
|
234
|
-
expect(
|
|
191
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
235
192
|
['docs', 'insert', 'abc', 'Hello world'],
|
|
236
193
|
{ account: undefined },
|
|
237
194
|
);
|
|
238
195
|
});
|
|
239
196
|
|
|
240
197
|
it('includes --index when provided', async () => {
|
|
241
|
-
vi.mocked(
|
|
198
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
242
199
|
const handlers = setupHandlers();
|
|
243
200
|
await handlers.get('gog_docs_insert')!({ docId: 'abc', content: 'text', index: 5 });
|
|
244
|
-
expect(
|
|
201
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
245
202
|
['docs', 'insert', 'abc', 'text', '--index=5'],
|
|
246
203
|
{ account: undefined },
|
|
247
204
|
);
|
|
248
205
|
});
|
|
249
206
|
|
|
250
207
|
it('includes --index=0 when index is zero', async () => {
|
|
251
|
-
vi.mocked(
|
|
208
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
252
209
|
const handlers = setupHandlers();
|
|
253
210
|
await handlers.get('gog_docs_insert')!({ docId: 'abc', content: 'text', index: 0 });
|
|
254
|
-
expect(
|
|
211
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
255
212
|
['docs', 'insert', 'abc', 'text', '--index=0'],
|
|
256
213
|
{ account: undefined },
|
|
257
214
|
);
|
|
258
215
|
});
|
|
259
216
|
|
|
260
217
|
it('includes --file when provided', async () => {
|
|
261
|
-
vi.mocked(
|
|
218
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
262
219
|
const handlers = setupHandlers();
|
|
263
220
|
await handlers.get('gog_docs_insert')!({ docId: 'abc', file: '/tmp/text.txt' });
|
|
264
|
-
expect(
|
|
221
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
265
222
|
['docs', 'insert', 'abc', '--file=/tmp/text.txt'],
|
|
266
223
|
{ account: undefined },
|
|
267
224
|
);
|
|
268
225
|
});
|
|
269
226
|
|
|
270
227
|
it('includes --tab-id when provided', async () => {
|
|
271
|
-
vi.mocked(
|
|
228
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
272
229
|
const handlers = setupHandlers();
|
|
273
230
|
await handlers.get('gog_docs_insert')!({ docId: 'abc', content: 'hi', tabId: 'tab1' });
|
|
274
|
-
expect(
|
|
231
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
275
232
|
['docs', 'insert', 'abc', 'hi', '--tab-id=tab1'],
|
|
276
233
|
{ account: undefined },
|
|
277
234
|
);
|
|
278
235
|
});
|
|
279
236
|
|
|
280
237
|
it('omits optional flags when not provided', async () => {
|
|
281
|
-
vi.mocked(
|
|
238
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
282
239
|
const handlers = setupHandlers();
|
|
283
240
|
await handlers.get('gog_docs_insert')!({ docId: 'abc' });
|
|
284
|
-
expect(
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('returns error text on failure', async () => {
|
|
288
|
-
vi.mocked(run).mockRejectedValue(new Error('Insert failed'));
|
|
289
|
-
const handlers = setupHandlers();
|
|
290
|
-
const result = await handlers.get('gog_docs_insert')!({ docId: 'bad' });
|
|
291
|
-
expect(result.content[0].text).toBe('Error: Insert failed');
|
|
241
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'insert', 'abc'], { account: undefined });
|
|
292
242
|
});
|
|
293
243
|
});
|
|
294
244
|
|
|
295
245
|
// --- gog_docs_list_tabs ---
|
|
296
246
|
|
|
297
247
|
describe('gog_docs_list_tabs', () => {
|
|
298
|
-
it('calls
|
|
299
|
-
vi.mocked(
|
|
248
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
249
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
300
250
|
const handlers = setupHandlers();
|
|
301
|
-
|
|
302
|
-
expect(
|
|
303
|
-
expect(result.content[0].text).toContain('Tab 1');
|
|
251
|
+
await handlers.get('gog_docs_list_tabs')!({ docId: 'abc' });
|
|
252
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'list-tabs', 'abc'], { account: undefined });
|
|
304
253
|
});
|
|
305
254
|
|
|
306
255
|
it('forwards account override', async () => {
|
|
307
|
-
vi.mocked(
|
|
256
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
308
257
|
const handlers = setupHandlers();
|
|
309
258
|
await handlers.get('gog_docs_list_tabs')!({ docId: 'abc', account: 'other@gmail.com' });
|
|
310
|
-
expect(
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it('returns error text on failure', async () => {
|
|
314
|
-
vi.mocked(run).mockRejectedValue(new Error('List tabs failed'));
|
|
315
|
-
const handlers = setupHandlers();
|
|
316
|
-
const result = await handlers.get('gog_docs_list_tabs')!({ docId: 'bad' });
|
|
317
|
-
expect(result.content[0].text).toBe('Error: List tabs failed');
|
|
259
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'list-tabs', 'abc'], { account: 'other@gmail.com' });
|
|
318
260
|
});
|
|
319
261
|
});
|
|
320
262
|
|
|
321
263
|
// --- gog_docs_sed ---
|
|
322
264
|
|
|
323
265
|
describe('gog_docs_sed', () => {
|
|
324
|
-
it('calls
|
|
325
|
-
vi.mocked(
|
|
266
|
+
it('calls runOrDiagnose with single expression', async () => {
|
|
267
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
326
268
|
const handlers = setupHandlers();
|
|
327
269
|
await handlers.get('gog_docs_sed')!({ docId: 'abc', expression: 's/old/new/g' });
|
|
328
|
-
expect(
|
|
270
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
329
271
|
['docs', 'sed', 'abc', 's/old/new/g'],
|
|
330
272
|
{ account: undefined },
|
|
331
273
|
);
|
|
332
274
|
});
|
|
333
275
|
|
|
334
|
-
it('calls
|
|
335
|
-
vi.mocked(
|
|
276
|
+
it('calls runOrDiagnose with multiple expressions', async () => {
|
|
277
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
336
278
|
const handlers = setupHandlers();
|
|
337
279
|
await handlers.get('gog_docs_sed')!({
|
|
338
280
|
docId: 'abc',
|
|
339
281
|
expressions: ['s/foo/bar/g', 's/baz/qux/g'],
|
|
340
282
|
});
|
|
341
|
-
expect(
|
|
283
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
342
284
|
['docs', 'sed', 'abc', '--expressions=s/foo/bar/g', '--expressions=s/baz/qux/g'],
|
|
343
285
|
{ account: undefined },
|
|
344
286
|
);
|
|
345
287
|
});
|
|
346
288
|
|
|
347
289
|
it('includes --file when provided', async () => {
|
|
348
|
-
vi.mocked(
|
|
290
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
349
291
|
const handlers = setupHandlers();
|
|
350
292
|
await handlers.get('gog_docs_sed')!({ docId: 'abc', file: '/tmp/sed.txt' });
|
|
351
|
-
expect(
|
|
293
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
352
294
|
['docs', 'sed', 'abc', '--file=/tmp/sed.txt'],
|
|
353
295
|
{ account: undefined },
|
|
354
296
|
);
|
|
355
297
|
});
|
|
356
298
|
|
|
357
299
|
it('includes --tab when provided', async () => {
|
|
358
|
-
vi.mocked(
|
|
300
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
359
301
|
const handlers = setupHandlers();
|
|
360
302
|
await handlers.get('gog_docs_sed')!({ docId: 'abc', expression: 's/a/b/', tab: 'Notes' });
|
|
361
|
-
expect(
|
|
303
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
362
304
|
['docs', 'sed', 'abc', 's/a/b/', '--tab=Notes'],
|
|
363
305
|
{ account: undefined },
|
|
364
306
|
);
|
|
365
307
|
});
|
|
366
308
|
|
|
367
309
|
it('omits optional flags when not provided', async () => {
|
|
368
|
-
vi.mocked(
|
|
310
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
369
311
|
const handlers = setupHandlers();
|
|
370
312
|
await handlers.get('gog_docs_sed')!({ docId: 'abc' });
|
|
371
|
-
expect(
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('returns error text on failure', async () => {
|
|
375
|
-
vi.mocked(run).mockRejectedValue(new Error('Sed failed'));
|
|
376
|
-
const handlers = setupHandlers();
|
|
377
|
-
const result = await handlers.get('gog_docs_sed')!({ docId: 'bad' });
|
|
378
|
-
expect(result.content[0].text).toBe('Error: Sed failed');
|
|
313
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'sed', 'abc'], { account: undefined });
|
|
379
314
|
});
|
|
380
315
|
});
|
|
381
316
|
|
|
382
317
|
// --- gog_docs_update ---
|
|
383
318
|
|
|
384
319
|
describe('gog_docs_update', () => {
|
|
385
|
-
it('calls
|
|
386
|
-
vi.mocked(
|
|
320
|
+
it('calls runOrDiagnose with --text flag', async () => {
|
|
321
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
387
322
|
const handlers = setupHandlers();
|
|
388
323
|
await handlers.get('gog_docs_update')!({ docId: 'abc', text: 'Hello' });
|
|
389
|
-
expect(
|
|
324
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
390
325
|
['docs', 'update', 'abc', '--text=Hello'],
|
|
391
326
|
{ account: undefined },
|
|
392
327
|
);
|
|
393
328
|
});
|
|
394
329
|
|
|
395
330
|
it('includes --file when provided', async () => {
|
|
396
|
-
vi.mocked(
|
|
331
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
397
332
|
const handlers = setupHandlers();
|
|
398
333
|
await handlers.get('gog_docs_update')!({ docId: 'abc', file: '/tmp/content.txt' });
|
|
399
|
-
expect(
|
|
334
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
400
335
|
['docs', 'update', 'abc', '--file=/tmp/content.txt'],
|
|
401
336
|
{ account: undefined },
|
|
402
337
|
);
|
|
403
338
|
});
|
|
404
339
|
|
|
405
340
|
it('includes --index when provided', async () => {
|
|
406
|
-
vi.mocked(
|
|
341
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
407
342
|
const handlers = setupHandlers();
|
|
408
343
|
await handlers.get('gog_docs_update')!({ docId: 'abc', text: 'hi', index: 10 });
|
|
409
|
-
expect(
|
|
344
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
410
345
|
['docs', 'update', 'abc', '--text=hi', '--index=10'],
|
|
411
346
|
{ account: undefined },
|
|
412
347
|
);
|
|
413
348
|
});
|
|
414
349
|
|
|
415
350
|
it('includes --index=0 when index is zero', async () => {
|
|
416
|
-
vi.mocked(
|
|
351
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
417
352
|
const handlers = setupHandlers();
|
|
418
353
|
await handlers.get('gog_docs_update')!({ docId: 'abc', text: 'hi', index: 0 });
|
|
419
|
-
expect(
|
|
354
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
420
355
|
['docs', 'update', 'abc', '--text=hi', '--index=0'],
|
|
421
356
|
{ account: undefined },
|
|
422
357
|
);
|
|
423
358
|
});
|
|
424
359
|
|
|
425
360
|
it('includes --tab-id when provided', async () => {
|
|
426
|
-
vi.mocked(
|
|
361
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
427
362
|
const handlers = setupHandlers();
|
|
428
363
|
await handlers.get('gog_docs_update')!({ docId: 'abc', text: 'hi', tabId: 'tab1' });
|
|
429
|
-
expect(
|
|
364
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
430
365
|
['docs', 'update', 'abc', '--text=hi', '--tab-id=tab1'],
|
|
431
366
|
{ account: undefined },
|
|
432
367
|
);
|
|
433
368
|
});
|
|
434
369
|
|
|
435
370
|
it('includes --pageless when true', async () => {
|
|
436
|
-
vi.mocked(
|
|
371
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
437
372
|
const handlers = setupHandlers();
|
|
438
373
|
await handlers.get('gog_docs_update')!({ docId: 'abc', pageless: true });
|
|
439
|
-
expect(
|
|
374
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
440
375
|
['docs', 'update', 'abc', '--pageless'],
|
|
441
376
|
{ account: undefined },
|
|
442
377
|
);
|
|
443
378
|
});
|
|
444
379
|
|
|
445
380
|
it('omits --pageless when false', async () => {
|
|
446
|
-
vi.mocked(
|
|
381
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
447
382
|
const handlers = setupHandlers();
|
|
448
383
|
await handlers.get('gog_docs_update')!({ docId: 'abc', pageless: false });
|
|
449
|
-
expect(
|
|
384
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
450
385
|
['docs', 'update', 'abc'],
|
|
451
386
|
{ account: undefined },
|
|
452
387
|
);
|
|
453
388
|
});
|
|
454
389
|
|
|
455
390
|
it('omits optional flags when not provided', async () => {
|
|
456
|
-
vi.mocked(
|
|
391
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
457
392
|
const handlers = setupHandlers();
|
|
458
393
|
await handlers.get('gog_docs_update')!({ docId: 'abc' });
|
|
459
|
-
expect(
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
it('returns error text on failure', async () => {
|
|
463
|
-
vi.mocked(run).mockRejectedValue(new Error('Update failed'));
|
|
464
|
-
const handlers = setupHandlers();
|
|
465
|
-
const result = await handlers.get('gog_docs_update')!({ docId: 'bad' });
|
|
466
|
-
expect(result.content[0].text).toBe('Error: Update failed');
|
|
394
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'update', 'abc'], { account: undefined });
|
|
467
395
|
});
|
|
468
396
|
});
|
|
469
397
|
|
|
470
398
|
// --- Dedicated comment tools ---
|
|
471
399
|
|
|
472
400
|
describe('gog_docs_comments_list', () => {
|
|
473
|
-
it('calls
|
|
474
|
-
vi.mocked(
|
|
401
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
402
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
475
403
|
const handlers = setupHandlers();
|
|
476
|
-
|
|
477
|
-
expect(
|
|
478
|
-
expect(result.content[0].text).toContain('Fix this');
|
|
404
|
+
await handlers.get('gog_docs_comments_list')!({ docId: 'abc' });
|
|
405
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'comments', 'list', 'abc'], { account: undefined });
|
|
479
406
|
});
|
|
480
407
|
|
|
481
408
|
it('includes --include-resolved when set', async () => {
|
|
482
|
-
vi.mocked(
|
|
409
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
483
410
|
const handlers = setupHandlers();
|
|
484
411
|
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', includeResolved: true });
|
|
485
|
-
expect(
|
|
412
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
486
413
|
['docs', 'comments', 'list', 'abc', '--include-resolved'],
|
|
487
414
|
{ account: undefined },
|
|
488
415
|
);
|
|
489
416
|
});
|
|
490
417
|
|
|
491
418
|
it('omits --include-resolved when false', async () => {
|
|
492
|
-
vi.mocked(
|
|
419
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
493
420
|
const handlers = setupHandlers();
|
|
494
421
|
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', includeResolved: false });
|
|
495
|
-
expect(
|
|
422
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'comments', 'list', 'abc'], { account: undefined });
|
|
496
423
|
});
|
|
497
424
|
|
|
498
425
|
it('forwards account override', async () => {
|
|
499
|
-
vi.mocked(
|
|
426
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
500
427
|
const handlers = setupHandlers();
|
|
501
428
|
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', account: 'other@gmail.com' });
|
|
502
|
-
expect(
|
|
429
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
503
430
|
['docs', 'comments', 'list', 'abc'],
|
|
504
431
|
{ account: 'other@gmail.com' },
|
|
505
432
|
);
|
|
506
433
|
});
|
|
507
|
-
|
|
508
|
-
it('returns error text on failure', async () => {
|
|
509
|
-
vi.mocked(run).mockRejectedValue(new Error('List failed'));
|
|
510
|
-
const handlers = setupHandlers();
|
|
511
|
-
const result = await handlers.get('gog_docs_comments_list')!({ docId: 'bad' });
|
|
512
|
-
expect(result.content[0].text).toContain('Error: List failed');
|
|
513
|
-
});
|
|
514
434
|
});
|
|
515
435
|
|
|
516
436
|
describe('gog_docs_comments_get', () => {
|
|
517
|
-
it('calls
|
|
518
|
-
vi.mocked(
|
|
519
|
-
const handlers = setupHandlers();
|
|
520
|
-
const result = await handlers.get('gog_docs_comments_get')!({ docId: 'abc', commentId: 'c1' });
|
|
521
|
-
expect(run).toHaveBeenCalledWith(['docs', 'comments', 'get', 'abc', 'c1'], { account: undefined });
|
|
522
|
-
expect(result.content[0].text).toContain('Fix this');
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it('returns error text on failure', async () => {
|
|
526
|
-
vi.mocked(run).mockRejectedValue(new Error('Not found'));
|
|
437
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
438
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
527
439
|
const handlers = setupHandlers();
|
|
528
|
-
|
|
529
|
-
expect(
|
|
440
|
+
await handlers.get('gog_docs_comments_get')!({ docId: 'abc', commentId: 'c1' });
|
|
441
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['docs', 'comments', 'get', 'abc', 'c1'], { account: undefined });
|
|
530
442
|
});
|
|
531
443
|
});
|
|
532
444
|
|
|
533
445
|
describe('gog_docs_comments_add', () => {
|
|
534
|
-
it('calls
|
|
535
|
-
vi.mocked(
|
|
446
|
+
it('calls runOrDiagnose with content', async () => {
|
|
447
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
536
448
|
const handlers = setupHandlers();
|
|
537
449
|
await handlers.get('gog_docs_comments_add')!({ docId: 'abc', content: 'Please review' });
|
|
538
|
-
expect(
|
|
450
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
539
451
|
['docs', 'comments', 'add', 'abc', 'Please review'],
|
|
540
452
|
{ account: undefined },
|
|
541
453
|
);
|
|
542
454
|
});
|
|
543
455
|
|
|
544
456
|
it('includes --quoted when provided', async () => {
|
|
545
|
-
vi.mocked(
|
|
457
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
546
458
|
const handlers = setupHandlers();
|
|
547
459
|
await handlers.get('gog_docs_comments_add')!({
|
|
548
460
|
docId: 'abc', content: 'Typo here', quoted: 'teh',
|
|
549
461
|
});
|
|
550
|
-
expect(
|
|
462
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
551
463
|
['docs', 'comments', 'add', 'abc', 'Typo here', '--quoted=teh'],
|
|
552
464
|
{ account: undefined },
|
|
553
465
|
);
|
|
554
466
|
});
|
|
555
467
|
|
|
556
468
|
it('omits --quoted when not provided', async () => {
|
|
557
|
-
vi.mocked(
|
|
469
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
558
470
|
const handlers = setupHandlers();
|
|
559
471
|
await handlers.get('gog_docs_comments_add')!({ docId: 'abc', content: 'Nice' });
|
|
560
|
-
expect(
|
|
472
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
561
473
|
['docs', 'comments', 'add', 'abc', 'Nice'],
|
|
562
474
|
{ account: undefined },
|
|
563
475
|
);
|
|
564
476
|
});
|
|
565
|
-
|
|
566
|
-
it('returns error text on failure', async () => {
|
|
567
|
-
vi.mocked(run).mockRejectedValue(new Error('Add failed'));
|
|
568
|
-
const handlers = setupHandlers();
|
|
569
|
-
const result = await handlers.get('gog_docs_comments_add')!({ docId: 'bad', content: 'x' });
|
|
570
|
-
expect(result.content[0].text).toContain('Error: Add failed');
|
|
571
|
-
});
|
|
572
477
|
});
|
|
573
478
|
|
|
574
479
|
describe('gog_docs_comments_reply', () => {
|
|
575
|
-
it('calls
|
|
576
|
-
vi.mocked(
|
|
480
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
481
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
577
482
|
const handlers = setupHandlers();
|
|
578
483
|
await handlers.get('gog_docs_comments_reply')!({ docId: 'abc', commentId: 'c1', content: 'Done' });
|
|
579
|
-
expect(
|
|
484
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
580
485
|
['docs', 'comments', 'reply', 'abc', 'c1', 'Done'],
|
|
581
486
|
{ account: undefined },
|
|
582
487
|
);
|
|
583
488
|
});
|
|
584
|
-
|
|
585
|
-
it('returns error text on failure', async () => {
|
|
586
|
-
vi.mocked(run).mockRejectedValue(new Error('Reply failed'));
|
|
587
|
-
const handlers = setupHandlers();
|
|
588
|
-
const result = await handlers.get('gog_docs_comments_reply')!({
|
|
589
|
-
docId: 'abc', commentId: 'c1', content: 'x',
|
|
590
|
-
});
|
|
591
|
-
expect(result.content[0].text).toContain('Error: Reply failed');
|
|
592
|
-
});
|
|
593
489
|
});
|
|
594
490
|
|
|
595
491
|
describe('gog_docs_comments_resolve', () => {
|
|
596
|
-
it('calls
|
|
597
|
-
vi.mocked(
|
|
492
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
493
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
598
494
|
const handlers = setupHandlers();
|
|
599
495
|
await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
600
|
-
expect(
|
|
496
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
601
497
|
['docs', 'comments', 'resolve', 'abc', 'c1'],
|
|
602
498
|
{ account: undefined },
|
|
603
499
|
);
|
|
604
500
|
});
|
|
605
501
|
|
|
606
502
|
it('includes --message when provided', async () => {
|
|
607
|
-
vi.mocked(
|
|
503
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
608
504
|
const handlers = setupHandlers();
|
|
609
505
|
await handlers.get('gog_docs_comments_resolve')!({
|
|
610
506
|
docId: 'abc', commentId: 'c1', message: 'Fixed in v2',
|
|
611
507
|
});
|
|
612
|
-
expect(
|
|
508
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
613
509
|
['docs', 'comments', 'resolve', 'abc', 'c1', '--message=Fixed in v2'],
|
|
614
510
|
{ account: undefined },
|
|
615
511
|
);
|
|
616
512
|
});
|
|
617
513
|
|
|
618
514
|
it('omits --message when not provided', async () => {
|
|
619
|
-
vi.mocked(
|
|
515
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
620
516
|
const handlers = setupHandlers();
|
|
621
517
|
await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
622
|
-
expect(
|
|
518
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
623
519
|
['docs', 'comments', 'resolve', 'abc', 'c1'],
|
|
624
520
|
{ account: undefined },
|
|
625
521
|
);
|
|
626
522
|
});
|
|
627
|
-
|
|
628
|
-
it('returns error text on failure', async () => {
|
|
629
|
-
vi.mocked(run).mockRejectedValue(new Error('Resolve failed'));
|
|
630
|
-
const handlers = setupHandlers();
|
|
631
|
-
const result = await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
632
|
-
expect(result.content[0].text).toContain('Error: Resolve failed');
|
|
633
|
-
});
|
|
634
523
|
});
|
|
635
524
|
|
|
636
525
|
describe('gog_docs_comments_delete', () => {
|
|
637
|
-
it('calls
|
|
638
|
-
vi.mocked(
|
|
526
|
+
it('calls runOrDiagnose with correct args', async () => {
|
|
527
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
639
528
|
const handlers = setupHandlers();
|
|
640
529
|
await handlers.get('gog_docs_comments_delete')!({ docId: 'abc', commentId: 'c1' });
|
|
641
|
-
expect(
|
|
530
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
642
531
|
['docs', 'comments', 'delete', 'abc', 'c1'],
|
|
643
532
|
{ account: undefined },
|
|
644
533
|
);
|
|
645
534
|
});
|
|
646
|
-
|
|
647
|
-
it('returns error text on failure', async () => {
|
|
648
|
-
vi.mocked(run).mockRejectedValue(new Error('Delete failed'));
|
|
649
|
-
const handlers = setupHandlers();
|
|
650
|
-
const result = await handlers.get('gog_docs_comments_delete')!({ docId: 'abc', commentId: 'c1' });
|
|
651
|
-
expect(result.content[0].text).toContain('Error: Delete failed');
|
|
652
|
-
});
|
|
653
535
|
});
|