gogcli-mcp-sheets 4.2.5 → 4.3.0
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +468 -159
- package/manifest.json +9 -2
- package/package.json +2 -2
- package/server.json +2 -2
- package/src/tools/sheets-extra.ts +74 -69
- package/tests/tools/sheets-extra.test.ts +175 -137
- package/vitest.config.ts +5 -0
|
@@ -3,6 +3,7 @@ import { registerExtraSheetsTools } from '../../src/tools/sheets-extra.js';
|
|
|
3
3
|
import * as lib from '../../../gogcli-mcp/src/lib.js';
|
|
4
4
|
import { createTestHarness } from '@chrischall/mcp-utils/test';
|
|
5
5
|
import { rawTextResult } from '@chrischall/mcp-utils';
|
|
6
|
+
import { pos } from '../../../gogcli-mcp/src/argv.js';
|
|
6
7
|
|
|
7
8
|
vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
|
|
8
9
|
const actual = await importOriginal<typeof lib>();
|
|
@@ -24,14 +25,14 @@ describe('gog_sheets_add_tab', () => {
|
|
|
24
25
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
25
26
|
const harness = await setupHandlers();
|
|
26
27
|
await harness.callTool('gog_sheets_add_tab', { spreadsheetId: 'sid', tabName: 'NewTab' });
|
|
27
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'add-tab', 'sid', 'NewTab'], { account: undefined });
|
|
28
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'add-tab', pos('sid'), pos('NewTab')], { account: undefined });
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
it('forwards account', async () => {
|
|
31
32
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
32
33
|
const harness = await setupHandlers();
|
|
33
34
|
await harness.callTool('gog_sheets_add_tab', { spreadsheetId: 'sid', tabName: 'T', account: 'a@b.com' });
|
|
34
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'add-tab', 'sid', 'T'], { account: 'a@b.com' });
|
|
35
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'add-tab', pos('sid'), pos('T')], { account: 'a@b.com' });
|
|
35
36
|
});
|
|
36
37
|
});
|
|
37
38
|
|
|
@@ -41,7 +42,7 @@ describe('gog_sheets_delete_tab', () => {
|
|
|
41
42
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
42
43
|
const harness = await setupHandlers();
|
|
43
44
|
await harness.callTool('gog_sheets_delete_tab', { spreadsheetId: 'sid', tabName: 'OldTab' });
|
|
44
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'delete-tab', 'sid', 'OldTab', '--force'], { account: undefined });
|
|
45
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'delete-tab', pos('sid'), pos('OldTab'), '--force'], { account: undefined });
|
|
45
46
|
});
|
|
46
47
|
});
|
|
47
48
|
|
|
@@ -51,7 +52,7 @@ describe('gog_sheets_rename_tab', () => {
|
|
|
51
52
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
52
53
|
const harness = await setupHandlers();
|
|
53
54
|
await harness.callTool('gog_sheets_rename_tab', { spreadsheetId: 'sid', oldName: 'Old', newName: 'New' });
|
|
54
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'rename-tab', 'sid', 'Old', 'New'], { account: undefined });
|
|
55
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'rename-tab', pos('sid'), pos('Old'), pos('New')], { account: undefined });
|
|
55
56
|
});
|
|
56
57
|
});
|
|
57
58
|
|
|
@@ -61,14 +62,14 @@ describe('gog_sheets_copy', () => {
|
|
|
61
62
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
62
63
|
const harness = await setupHandlers();
|
|
63
64
|
await harness.callTool('gog_sheets_copy', { spreadsheetId: 'sid', title: 'Copy' });
|
|
64
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy', 'sid', 'Copy'], { account: undefined });
|
|
65
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy', pos('sid'), pos('Copy')], { account: undefined });
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
it('includes --parent when provided', async () => {
|
|
68
69
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
69
70
|
const harness = await setupHandlers();
|
|
70
71
|
await harness.callTool('gog_sheets_copy', { spreadsheetId: 'sid', title: 'Copy', parent: 'folderId' });
|
|
71
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy', 'sid', 'Copy', '--parent=folderId'], { account: undefined });
|
|
72
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy', pos('sid'), pos('Copy'), '--parent=folderId'], { account: undefined });
|
|
72
73
|
});
|
|
73
74
|
});
|
|
74
75
|
|
|
@@ -78,21 +79,21 @@ describe('gog_sheets_export', () => {
|
|
|
78
79
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
79
80
|
const harness = await setupHandlers();
|
|
80
81
|
await harness.callTool('gog_sheets_export', { spreadsheetId: 'sid' });
|
|
81
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', 'sid'], { account: undefined });
|
|
82
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', pos('sid')], { account: undefined });
|
|
82
83
|
});
|
|
83
84
|
|
|
84
85
|
it('includes --format and --out when provided', async () => {
|
|
85
86
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
86
87
|
const harness = await setupHandlers();
|
|
87
88
|
await harness.callTool('gog_sheets_export', { spreadsheetId: 'sid', format: 'pdf', out: '/tmp/out.pdf' });
|
|
88
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', 'sid', '--format=pdf', '--out=/tmp/out.pdf'], { account: undefined });
|
|
89
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', pos('sid'), '--format=pdf', '--out=/tmp/out.pdf'], { account: undefined });
|
|
89
90
|
});
|
|
90
91
|
|
|
91
92
|
it('includes --overwrite when requested', async () => {
|
|
92
93
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
93
94
|
const harness = await setupHandlers();
|
|
94
95
|
await harness.callTool('gog_sheets_export', { spreadsheetId: 'sid', out: '/tmp/out.csv', overwrite: true });
|
|
95
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', 'sid', '--out=/tmp/out.csv', '--overwrite'], { account: undefined });
|
|
96
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'export', pos('sid'), '--out=/tmp/out.csv', '--overwrite'], { account: undefined });
|
|
96
97
|
});
|
|
97
98
|
});
|
|
98
99
|
|
|
@@ -102,21 +103,21 @@ describe('gog_sheets_freeze', () => {
|
|
|
102
103
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
103
104
|
const harness = await setupHandlers();
|
|
104
105
|
await harness.callTool('gog_sheets_freeze', { spreadsheetId: 'sid' });
|
|
105
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', 'sid'], { account: undefined });
|
|
106
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', pos('sid')], { account: undefined });
|
|
106
107
|
});
|
|
107
108
|
|
|
108
109
|
it('includes --rows, --cols, --sheet when provided', async () => {
|
|
109
110
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
110
111
|
const harness = await setupHandlers();
|
|
111
112
|
await harness.callTool('gog_sheets_freeze', { spreadsheetId: 'sid', rows: 1, cols: 2, sheet: 'Data' });
|
|
112
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', 'sid', '--rows=1', '--cols=2', '--sheet=Data'], { account: undefined });
|
|
113
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', pos('sid'), '--rows=1', '--cols=2', '--sheet=Data'], { account: undefined });
|
|
113
114
|
});
|
|
114
115
|
|
|
115
116
|
it('includes --rows=0 when rows is 0', async () => {
|
|
116
117
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
117
118
|
const harness = await setupHandlers();
|
|
118
119
|
await harness.callTool('gog_sheets_freeze', { spreadsheetId: 'sid', rows: 0 });
|
|
119
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', 'sid', '--rows=0'], { account: undefined });
|
|
120
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'freeze', pos('sid'), '--rows=0'], { account: undefined });
|
|
120
121
|
});
|
|
121
122
|
});
|
|
122
123
|
|
|
@@ -129,7 +130,7 @@ describe('gog_sheets_insert', () => {
|
|
|
129
130
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
130
131
|
const harness = await setupHandlers();
|
|
131
132
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'Sheet1', dimension: 'ROWS', start: 5 });
|
|
132
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'Sheet1', 'ROWS', '6'], { account: undefined });
|
|
133
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('Sheet1'), pos('ROWS'), pos('6')], { account: undefined });
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
it('bug: start=1, after:false inserts before 0-based index 1 (new row 2), not at the top', async () => {
|
|
@@ -138,7 +139,7 @@ describe('gog_sheets_insert', () => {
|
|
|
138
139
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
139
140
|
const harness = await setupHandlers();
|
|
140
141
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'ROWS', start: 1, count: 1 });
|
|
141
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'ROWS', '2', '--count=1'], { account: undefined });
|
|
142
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('ROWS'), pos('2'), '--count=1'], { account: undefined });
|
|
142
143
|
});
|
|
143
144
|
|
|
144
145
|
it('shifts start by +1 when after:true so the new dimension lands AFTER start', async () => {
|
|
@@ -147,7 +148,7 @@ describe('gog_sheets_insert', () => {
|
|
|
147
148
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
148
149
|
const harness = await setupHandlers();
|
|
149
150
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'COLUMNS', start: 0, count: 3, after: true });
|
|
150
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'COLUMNS', '1', '--count=3', '--after'], { account: undefined });
|
|
151
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('COLUMNS'), pos('1'), '--count=3', '--after'], { account: undefined });
|
|
151
152
|
});
|
|
152
153
|
|
|
153
154
|
it('issue #42 acceptance: start=28, after:true leaves column 28 untouched (insertion lands at 29)', async () => {
|
|
@@ -155,14 +156,14 @@ describe('gog_sheets_insert', () => {
|
|
|
155
156
|
const harness = await setupHandlers();
|
|
156
157
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'COLUMNS', start: 28, after: true, count: 1 });
|
|
157
158
|
// CLI is 1-based; with --after CLI uses startIndex = c.Start, so passing 29 → API startIndex=29.
|
|
158
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'COLUMNS', '29', '--count=1', '--after'], { account: undefined });
|
|
159
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('COLUMNS'), pos('29'), '--count=1', '--after'], { account: undefined });
|
|
159
160
|
});
|
|
160
161
|
|
|
161
162
|
it('includes --count=0 when count is 0', async () => {
|
|
162
163
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
163
164
|
const harness = await setupHandlers();
|
|
164
165
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'ROWS', start: 0, count: 0 });
|
|
165
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'ROWS', '1', '--count=0'], { account: undefined });
|
|
166
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('ROWS'), pos('1'), '--count=0'], { account: undefined });
|
|
166
167
|
});
|
|
167
168
|
|
|
168
169
|
it('omits --after and sends start+1 so start=0 inserts at the very top (after:false)', async () => {
|
|
@@ -172,21 +173,21 @@ describe('gog_sheets_insert', () => {
|
|
|
172
173
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
173
174
|
const harness = await setupHandlers();
|
|
174
175
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'ROWS', start: 0, after: false });
|
|
175
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'ROWS', '1'], { account: undefined });
|
|
176
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('ROWS'), pos('1')], { account: undefined });
|
|
176
177
|
});
|
|
177
178
|
|
|
178
179
|
it('passes --inherit-from-before=true when set', async () => {
|
|
179
180
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
180
181
|
const harness = await setupHandlers();
|
|
181
182
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'ROWS', start: 5, after: true, inheritFromBefore: true });
|
|
182
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'ROWS', '6', '--after', '--inherit-from-before=true'], { account: undefined });
|
|
183
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('ROWS'), pos('6'), '--after', '--inherit-from-before=true'], { account: undefined });
|
|
183
184
|
});
|
|
184
185
|
|
|
185
186
|
it('passes --inherit-from-before=false to inherit from the following neighbor', async () => {
|
|
186
187
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
187
188
|
const harness = await setupHandlers();
|
|
188
189
|
await harness.callTool('gog_sheets_insert', { spreadsheetId: 'sid', sheet: 'S1', dimension: 'ROWS', start: 5, after: true, inheritFromBefore: false });
|
|
189
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', 'sid', 'S1', 'ROWS', '6', '--after', '--inherit-from-before=false'], { account: undefined });
|
|
190
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'insert', pos('sid'), pos('S1'), pos('ROWS'), pos('6'), '--after', '--inherit-from-before=false'], { account: undefined });
|
|
190
191
|
});
|
|
191
192
|
});
|
|
192
193
|
|
|
@@ -195,21 +196,21 @@ describe('gog_sheets_copy_paste', () => {
|
|
|
195
196
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
196
197
|
const harness = await setupHandlers();
|
|
197
198
|
await harness.callTool('gog_sheets_copy_paste', { spreadsheetId: 'sid', source: 'Sheet1!A2:H71', dest: 'Sheet1!A2:H120' });
|
|
198
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', 'sid', 'Sheet1!A2:H71', 'Sheet1!A2:H120'], { account: undefined });
|
|
199
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', pos('sid'), pos('Sheet1!A2:H71'), pos('Sheet1!A2:H120')], { account: undefined });
|
|
199
200
|
});
|
|
200
201
|
|
|
201
202
|
it('appends --type and --transpose when provided', async () => {
|
|
202
203
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
203
204
|
const harness = await setupHandlers();
|
|
204
205
|
await harness.callTool('gog_sheets_copy_paste', { spreadsheetId: 'sid', source: 'A1:B2', dest: 'D1:E2', type: 'FORMULA', transpose: true });
|
|
205
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', 'sid', 'A1:B2', 'D1:E2', '--type=FORMULA', '--transpose'], { account: undefined });
|
|
206
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', pos('sid'), pos('A1:B2'), pos('D1:E2'), '--type=FORMULA', '--transpose'], { account: undefined });
|
|
206
207
|
});
|
|
207
208
|
|
|
208
209
|
it('forwards account', async () => {
|
|
209
210
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
210
211
|
const harness = await setupHandlers();
|
|
211
212
|
await harness.callTool('gog_sheets_copy_paste', { spreadsheetId: 'sid', source: 'A1', dest: 'B1', account: 'a@b.com' });
|
|
212
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', 'sid', 'A1', 'B1'], { account: 'a@b.com' });
|
|
213
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'copy-paste', pos('sid'), pos('A1'), pos('B1')], { account: 'a@b.com' });
|
|
213
214
|
});
|
|
214
215
|
});
|
|
215
216
|
|
|
@@ -219,14 +220,14 @@ describe('gog_sheets_merge', () => {
|
|
|
219
220
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
220
221
|
const harness = await setupHandlers();
|
|
221
222
|
await harness.callTool('gog_sheets_merge', { spreadsheetId: 'sid', range: 'A1:C3' });
|
|
222
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'merge', 'sid', 'A1:C3'], { account: undefined });
|
|
223
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'merge', pos('sid'), pos('A1:C3')], { account: undefined });
|
|
223
224
|
});
|
|
224
225
|
|
|
225
226
|
it('includes --type when provided', async () => {
|
|
226
227
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
227
228
|
const harness = await setupHandlers();
|
|
228
229
|
await harness.callTool('gog_sheets_merge', { spreadsheetId: 'sid', range: 'A1:C3', type: 'MERGE_COLUMNS' });
|
|
229
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'merge', 'sid', 'A1:C3', '--type=MERGE_COLUMNS'], { account: undefined });
|
|
230
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'merge', pos('sid'), pos('A1:C3'), '--type=MERGE_COLUMNS'], { account: undefined });
|
|
230
231
|
});
|
|
231
232
|
});
|
|
232
233
|
|
|
@@ -236,7 +237,7 @@ describe('gog_sheets_unmerge', () => {
|
|
|
236
237
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
237
238
|
const harness = await setupHandlers();
|
|
238
239
|
await harness.callTool('gog_sheets_unmerge', { spreadsheetId: 'sid', range: 'A1:C3' });
|
|
239
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'unmerge', 'sid', 'A1:C3'], { account: undefined });
|
|
240
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'unmerge', pos('sid'), pos('A1:C3')], { account: undefined });
|
|
240
241
|
});
|
|
241
242
|
});
|
|
242
243
|
|
|
@@ -248,7 +249,7 @@ describe('gog_sheets_format', () => {
|
|
|
248
249
|
const fj = '{"textFormat":{"bold":true}}';
|
|
249
250
|
await harness.callTool('gog_sheets_format', { spreadsheetId: 'sid', range: 'A1:B2', formatJson: fj, formatFields: 'textFormat.bold' });
|
|
250
251
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
251
|
-
['sheets', 'format', 'sid', 'A1:B2', `--format-json=${fj}`, '--format-fields=textFormat.bold'],
|
|
252
|
+
['sheets', 'format', pos('sid'), pos('A1:B2'), `--format-json=${fj}`, '--format-fields=textFormat.bold'],
|
|
252
253
|
{ account: undefined },
|
|
253
254
|
);
|
|
254
255
|
});
|
|
@@ -258,7 +259,7 @@ describe('gog_sheets_format', () => {
|
|
|
258
259
|
const harness = await setupHandlers();
|
|
259
260
|
await harness.callTool('gog_sheets_format', { spreadsheetId: 'sid', range: 'A1', formatJson: '{}' });
|
|
260
261
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
261
|
-
['sheets', 'format', 'sid', 'A1', '--format-json={}'],
|
|
262
|
+
['sheets', 'format', pos('sid'), pos('A1'), '--format-json={}'],
|
|
262
263
|
{ account: undefined },
|
|
263
264
|
);
|
|
264
265
|
});
|
|
@@ -277,8 +278,8 @@ describe('gog_sheets_format', () => {
|
|
|
277
278
|
const argv = call[0];
|
|
278
279
|
expect(argv[0]).toBe('sheets');
|
|
279
280
|
expect(argv[1]).toBe('format');
|
|
280
|
-
expect(argv[2]).
|
|
281
|
-
expect(argv[3]).
|
|
281
|
+
expect(argv[2]).toEqual(pos('sid'));
|
|
282
|
+
expect(argv[3]).toEqual(pos('A1:C3'));
|
|
282
283
|
const fmtArg = (argv[4] as string).replace(/^--format-json=/, '');
|
|
283
284
|
const parsed = JSON.parse(fmtArg);
|
|
284
285
|
expect(parsed.textFormat.bold).toBe(true);
|
|
@@ -366,7 +367,7 @@ describe('gog_sheets_list_tabs', () => {
|
|
|
366
367
|
const harness = await setupHandlers();
|
|
367
368
|
await harness.callTool('gog_sheets_list_tabs', { spreadsheetId: 'sid' });
|
|
368
369
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
369
|
-
['sheets', 'metadata', 'sid', '--select=sheets.properties.sheetId,sheets.properties.title,sheets.properties.index,sheets.properties.gridProperties'],
|
|
370
|
+
['sheets', 'metadata', pos('sid'), '--select=sheets.properties.sheetId,sheets.properties.title,sheets.properties.index,sheets.properties.gridProperties'],
|
|
370
371
|
{ account: undefined },
|
|
371
372
|
);
|
|
372
373
|
});
|
|
@@ -378,14 +379,14 @@ describe('gog_sheets_number_format', () => {
|
|
|
378
379
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
379
380
|
const harness = await setupHandlers();
|
|
380
381
|
await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'A1:A10' });
|
|
381
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'number-format', 'sid', 'A1:A10'], { account: undefined });
|
|
382
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'number-format', pos('sid'), pos('A1:A10')], { account: undefined });
|
|
382
383
|
});
|
|
383
384
|
|
|
384
385
|
it('includes --type and --pattern when provided', async () => {
|
|
385
386
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
386
387
|
const harness = await setupHandlers();
|
|
387
388
|
await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'A1', type: 'CURRENCY', pattern: '#,##0.00' });
|
|
388
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'number-format', 'sid', 'A1', '--type=CURRENCY', '--pattern=#,##0.00'], { account: undefined });
|
|
389
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'number-format', pos('sid'), pos('A1'), '--type=CURRENCY', '--pattern=#,##0.00'], { account: undefined });
|
|
389
390
|
});
|
|
390
391
|
|
|
391
392
|
// Issue #43: warn when DATE/DATE_TIME format applied to small integers (silent 1899/1900 render).
|
|
@@ -401,12 +402,12 @@ describe('gog_sheets_number_format', () => {
|
|
|
401
402
|
const result = await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'Sheet1!A1:A3', type: 'DATE' });
|
|
402
403
|
// Peek call goes out first.
|
|
403
404
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
404
|
-
['sheets', 'get', 'sid', 'Sheet1!A1:A3', '--render=UNFORMATTED_VALUE'],
|
|
405
|
+
['sheets', 'get', pos('sid'), pos('Sheet1!A1:A3'), '--render=UNFORMATTED_VALUE'],
|
|
405
406
|
{ account: undefined },
|
|
406
407
|
);
|
|
407
408
|
// The format call still happens (warning is non-blocking).
|
|
408
409
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
409
|
-
['sheets', 'number-format', 'sid', 'Sheet1!A1:A3', '--type=DATE'],
|
|
410
|
+
['sheets', 'number-format', pos('sid'), pos('Sheet1!A1:A3'), '--type=DATE'],
|
|
410
411
|
{ account: undefined },
|
|
411
412
|
);
|
|
412
413
|
const text = result.content[0].text;
|
|
@@ -434,7 +435,7 @@ describe('gog_sheets_number_format', () => {
|
|
|
434
435
|
// Only the format call should fire — no peek.
|
|
435
436
|
expect(lib.runOrDiagnose).toHaveBeenCalledTimes(1);
|
|
436
437
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
437
|
-
['sheets', 'number-format', 'sid', 'Sheet1!A1:A3', '--type=DATE'],
|
|
438
|
+
['sheets', 'number-format', pos('sid'), pos('Sheet1!A1:A3'), '--type=DATE'],
|
|
438
439
|
{ account: undefined },
|
|
439
440
|
);
|
|
440
441
|
expect(result.content[0].text).not.toMatch(/warning/i);
|
|
@@ -459,7 +460,7 @@ describe('gog_sheets_number_format', () => {
|
|
|
459
460
|
await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'A1:A3', type: 'CURRENCY' });
|
|
460
461
|
expect(lib.runOrDiagnose).toHaveBeenCalledTimes(1);
|
|
461
462
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
462
|
-
['sheets', 'number-format', 'sid', 'A1:A3', '--type=CURRENCY'],
|
|
463
|
+
['sheets', 'number-format', pos('sid'), pos('A1:A3'), '--type=CURRENCY'],
|
|
463
464
|
{ account: undefined },
|
|
464
465
|
);
|
|
465
466
|
});
|
|
@@ -573,7 +574,7 @@ describe('gog_sheets_number_format', () => {
|
|
|
573
574
|
const result = await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'A1:A3', type: 'DATE' });
|
|
574
575
|
// Format call should still happen.
|
|
575
576
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
576
|
-
['sheets', 'number-format', 'sid', 'A1:A3', '--type=DATE'],
|
|
577
|
+
['sheets', 'number-format', pos('sid'), pos('A1:A3'), '--type=DATE'],
|
|
577
578
|
{ account: undefined },
|
|
578
579
|
);
|
|
579
580
|
// No warning emitted when peek didn't yield clear evidence.
|
|
@@ -590,11 +591,11 @@ describe('gog_sheets_number_format', () => {
|
|
|
590
591
|
});
|
|
591
592
|
await harness.callTool('gog_sheets_number_format', { spreadsheetId: 'sid', range: 'A1', type: 'DATE', account: 'a@b.com' });
|
|
592
593
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
593
|
-
['sheets', 'get', 'sid', 'A1', '--render=UNFORMATTED_VALUE'],
|
|
594
|
+
['sheets', 'get', pos('sid'), pos('A1'), '--render=UNFORMATTED_VALUE'],
|
|
594
595
|
{ account: 'a@b.com' },
|
|
595
596
|
);
|
|
596
597
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
597
|
-
['sheets', 'number-format', 'sid', 'A1', '--type=DATE'],
|
|
598
|
+
['sheets', 'number-format', pos('sid'), pos('A1'), '--type=DATE'],
|
|
598
599
|
{ account: 'a@b.com' },
|
|
599
600
|
);
|
|
600
601
|
});
|
|
@@ -607,21 +608,21 @@ describe('gog_sheets_read_format', () => {
|
|
|
607
608
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
608
609
|
const harness = await setupHandlers();
|
|
609
610
|
await harness.callTool('gog_sheets_read_format', { spreadsheetId: 'sid', range: 'A1:B2' });
|
|
610
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', 'sid', 'A1:B2'], { account: undefined });
|
|
611
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', pos('sid'), pos('A1:B2')], { account: undefined });
|
|
611
612
|
});
|
|
612
613
|
|
|
613
614
|
it('includes --effective when true', async () => {
|
|
614
615
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
615
616
|
const harness = await setupHandlers();
|
|
616
617
|
await harness.callTool('gog_sheets_read_format', { spreadsheetId: 'sid', range: 'A1', effective: true });
|
|
617
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', 'sid', 'A1', '--effective'], { account: undefined });
|
|
618
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', pos('sid'), pos('A1'), '--effective'], { account: undefined });
|
|
618
619
|
});
|
|
619
620
|
|
|
620
621
|
it('omits --effective when false', async () => {
|
|
621
622
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
622
623
|
const harness = await setupHandlers();
|
|
623
624
|
await harness.callTool('gog_sheets_read_format', { spreadsheetId: 'sid', range: 'A1', effective: false });
|
|
624
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', 'sid', 'A1'], { account: undefined });
|
|
625
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'read-format', pos('sid'), pos('A1')], { account: undefined });
|
|
625
626
|
});
|
|
626
627
|
});
|
|
627
628
|
|
|
@@ -631,21 +632,21 @@ describe('gog_sheets_resize_columns', () => {
|
|
|
631
632
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
632
633
|
const harness = await setupHandlers();
|
|
633
634
|
await harness.callTool('gog_sheets_resize_columns', { spreadsheetId: 'sid', columns: 'A:C' });
|
|
634
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', 'sid', 'A:C'], { account: undefined });
|
|
635
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', pos('sid'), pos('A:C')], { account: undefined });
|
|
635
636
|
});
|
|
636
637
|
|
|
637
638
|
it('includes --width and --auto when provided', async () => {
|
|
638
639
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
639
640
|
const harness = await setupHandlers();
|
|
640
641
|
await harness.callTool('gog_sheets_resize_columns', { spreadsheetId: 'sid', columns: 'A:C', width: 200, auto: true });
|
|
641
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', 'sid', 'A:C', '--width=200', '--auto'], { account: undefined });
|
|
642
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', pos('sid'), pos('A:C'), '--width=200', '--auto'], { account: undefined });
|
|
642
643
|
});
|
|
643
644
|
|
|
644
645
|
it('includes --width=0 when width is 0', async () => {
|
|
645
646
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
646
647
|
const harness = await setupHandlers();
|
|
647
648
|
await harness.callTool('gog_sheets_resize_columns', { spreadsheetId: 'sid', columns: 'A:A', width: 0 });
|
|
648
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', 'sid', 'A:A', '--width=0'], { account: undefined });
|
|
649
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-columns', pos('sid'), pos('A:A'), '--width=0'], { account: undefined });
|
|
649
650
|
});
|
|
650
651
|
});
|
|
651
652
|
|
|
@@ -655,21 +656,21 @@ describe('gog_sheets_resize_rows', () => {
|
|
|
655
656
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
656
657
|
const harness = await setupHandlers();
|
|
657
658
|
await harness.callTool('gog_sheets_resize_rows', { spreadsheetId: 'sid', rows: '1:10' });
|
|
658
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', 'sid', '1:10'], { account: undefined });
|
|
659
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', pos('sid'), pos('1:10')], { account: undefined });
|
|
659
660
|
});
|
|
660
661
|
|
|
661
662
|
it('includes --height and --auto when provided', async () => {
|
|
662
663
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
663
664
|
const harness = await setupHandlers();
|
|
664
665
|
await harness.callTool('gog_sheets_resize_rows', { spreadsheetId: 'sid', rows: '1:5', height: 40, auto: true });
|
|
665
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', 'sid', '1:5', '--height=40', '--auto'], { account: undefined });
|
|
666
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', pos('sid'), pos('1:5'), '--height=40', '--auto'], { account: undefined });
|
|
666
667
|
});
|
|
667
668
|
|
|
668
669
|
it('includes --height=0 when height is 0', async () => {
|
|
669
670
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
670
671
|
const harness = await setupHandlers();
|
|
671
672
|
await harness.callTool('gog_sheets_resize_rows', { spreadsheetId: 'sid', rows: '1:1', height: 0 });
|
|
672
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', 'sid', '1:1', '--height=0'], { account: undefined });
|
|
673
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'resize-rows', pos('sid'), pos('1:1'), '--height=0'], { account: undefined });
|
|
673
674
|
});
|
|
674
675
|
});
|
|
675
676
|
|
|
@@ -679,7 +680,7 @@ describe('gog_sheets_notes', () => {
|
|
|
679
680
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
680
681
|
const harness = await setupHandlers();
|
|
681
682
|
await harness.callTool('gog_sheets_notes', { spreadsheetId: 'sid', range: 'A1:B5' });
|
|
682
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'notes', 'sid', 'A1:B5'], { account: undefined });
|
|
683
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'notes', pos('sid'), pos('A1:B5')], { account: undefined });
|
|
683
684
|
});
|
|
684
685
|
});
|
|
685
686
|
|
|
@@ -689,14 +690,14 @@ describe('gog_sheets_update_note', () => {
|
|
|
689
690
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
690
691
|
const harness = await setupHandlers();
|
|
691
692
|
await harness.callTool('gog_sheets_update_note', { spreadsheetId: 'sid', range: 'A1', note: 'Hello' });
|
|
692
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'update-note', 'sid', 'A1', '--note=Hello'], { account: undefined });
|
|
693
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'update-note', pos('sid'), pos('A1'), '--note=Hello'], { account: undefined });
|
|
693
694
|
});
|
|
694
695
|
|
|
695
696
|
it('passes empty string to clear note', async () => {
|
|
696
697
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
697
698
|
const harness = await setupHandlers();
|
|
698
699
|
await harness.callTool('gog_sheets_update_note', { spreadsheetId: 'sid', range: 'A1', note: '' });
|
|
699
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'update-note', 'sid', 'A1', '--note='], { account: undefined });
|
|
700
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'update-note', pos('sid'), pos('A1'), '--note='], { account: undefined });
|
|
700
701
|
});
|
|
701
702
|
|
|
702
703
|
it('spills a large note to a --note-file payload arg', async () => {
|
|
@@ -705,7 +706,7 @@ describe('gog_sheets_update_note', () => {
|
|
|
705
706
|
const big = 'n'.repeat(lib.PAYLOAD_INLINE_MAX + 1);
|
|
706
707
|
await harness.callTool('gog_sheets_update_note', { spreadsheetId: 'sid', range: 'A1', note: big });
|
|
707
708
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
708
|
-
['sheets', 'update-note', 'sid', 'A1',
|
|
709
|
+
['sheets', 'update-note', pos('sid'), pos('A1'),
|
|
709
710
|
{ kind: 'file', flag: 'note-file', contents: big, ext: undefined }],
|
|
710
711
|
{ account: undefined },
|
|
711
712
|
);
|
|
@@ -718,7 +719,7 @@ describe('gog_sheets_links', () => {
|
|
|
718
719
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
719
720
|
const harness = await setupHandlers();
|
|
720
721
|
await harness.callTool('gog_sheets_links', { spreadsheetId: 'sid', range: 'A1:Z100' });
|
|
721
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'links', 'sid', 'A1:Z100'], { account: undefined });
|
|
722
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'links', pos('sid'), pos('A1:Z100')], { account: undefined });
|
|
722
723
|
});
|
|
723
724
|
});
|
|
724
725
|
|
|
@@ -729,7 +730,7 @@ describe('gog_sheets_links_set', () => {
|
|
|
729
730
|
const harness = await setupHandlers();
|
|
730
731
|
await harness.callTool('gog_sheets_links_set', { spreadsheetId: 'sid', cell: 'A1', url: 'https://x.com', text: 'Link' });
|
|
731
732
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
732
|
-
['sheets', 'links', 'set', 'sid', 'A1', 'https://x.com', 'Link'],
|
|
733
|
+
['sheets', 'links', 'set', pos('sid'), pos('A1'), pos('https://x.com'), pos('Link')],
|
|
733
734
|
{ account: undefined },
|
|
734
735
|
);
|
|
735
736
|
});
|
|
@@ -739,7 +740,7 @@ describe('gog_sheets_links_set', () => {
|
|
|
739
740
|
const harness = await setupHandlers();
|
|
740
741
|
await harness.callTool('gog_sheets_links_set', { spreadsheetId: 'sid', cell: 'B2', runsJson: '[{"text":"A","uri":"https://a"}]' });
|
|
741
742
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
742
|
-
['sheets', 'links', 'set', 'sid', 'B2', '--runs-json=[{"text":"A","uri":"https://a"}]'],
|
|
743
|
+
['sheets', 'links', 'set', pos('sid'), pos('B2'), '--runs-json=[{"text":"A","uri":"https://a"}]'],
|
|
743
744
|
{ account: undefined },
|
|
744
745
|
);
|
|
745
746
|
});
|
|
@@ -749,7 +750,7 @@ describe('gog_sheets_links_set', () => {
|
|
|
749
750
|
const harness = await setupHandlers();
|
|
750
751
|
await harness.callTool('gog_sheets_links_set', { spreadsheetId: 'sid', cellsJson: '[{"cell":"A1","url":"https://a"}]' });
|
|
751
752
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
752
|
-
['sheets', 'links', 'set', 'sid', '--cells-json=[{"cell":"A1","url":"https://a"}]'],
|
|
753
|
+
['sheets', 'links', 'set', pos('sid'), '--cells-json=[{"cell":"A1","url":"https://a"}]'],
|
|
753
754
|
{ account: undefined },
|
|
754
755
|
);
|
|
755
756
|
});
|
|
@@ -764,7 +765,7 @@ describe('gog_sheets_links_set', () => {
|
|
|
764
765
|
const harness = await setupHandlers();
|
|
765
766
|
await harness.callTool('gog_sheets_links_set', { spreadsheetId: 'sid', cellsJson: '@/tmp/cells.json' });
|
|
766
767
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
767
|
-
['sheets', 'links', 'set', 'sid', '--cells-json=@/tmp/cells.json'],
|
|
768
|
+
['sheets', 'links', 'set', pos('sid'), '--cells-json=@/tmp/cells.json'],
|
|
768
769
|
{ account: undefined },
|
|
769
770
|
);
|
|
770
771
|
});
|
|
@@ -788,7 +789,7 @@ describe('gog_sheets_named_ranges_list', () => {
|
|
|
788
789
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
789
790
|
const harness = await setupHandlers();
|
|
790
791
|
await harness.callTool('gog_sheets_named_ranges_list', { spreadsheetId: 'sid' });
|
|
791
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'list', 'sid'], { account: undefined });
|
|
792
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'list', pos('sid')], { account: undefined });
|
|
792
793
|
});
|
|
793
794
|
});
|
|
794
795
|
|
|
@@ -798,7 +799,7 @@ describe('gog_sheets_named_ranges_get', () => {
|
|
|
798
799
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
799
800
|
const harness = await setupHandlers();
|
|
800
801
|
await harness.callTool('gog_sheets_named_ranges_get', { spreadsheetId: 'sid', nameOrId: 'MyRange' });
|
|
801
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'get', 'sid', 'MyRange'], { account: undefined });
|
|
802
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'get', pos('sid'), pos('MyRange')], { account: undefined });
|
|
802
803
|
});
|
|
803
804
|
});
|
|
804
805
|
|
|
@@ -808,7 +809,7 @@ describe('gog_sheets_named_ranges_add', () => {
|
|
|
808
809
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
809
810
|
const harness = await setupHandlers();
|
|
810
811
|
await harness.callTool('gog_sheets_named_ranges_add', { spreadsheetId: 'sid', name: 'Totals', range: 'Sheet1!A1:B10' });
|
|
811
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'add', 'sid', 'Totals', 'Sheet1!A1:B10'], { account: undefined });
|
|
812
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'add', pos('sid'), pos('Totals'), pos('Sheet1!A1:B10')], { account: undefined });
|
|
812
813
|
});
|
|
813
814
|
});
|
|
814
815
|
|
|
@@ -818,14 +819,14 @@ describe('gog_sheets_named_ranges_update', () => {
|
|
|
818
819
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
819
820
|
const harness = await setupHandlers();
|
|
820
821
|
await harness.callTool('gog_sheets_named_ranges_update', { spreadsheetId: 'sid', nameOrId: 'MyRange' });
|
|
821
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'update', 'sid', 'MyRange'], { account: undefined });
|
|
822
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'update', pos('sid'), pos('MyRange')], { account: undefined });
|
|
822
823
|
});
|
|
823
824
|
|
|
824
825
|
it('includes --name and --range when provided', async () => {
|
|
825
826
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
826
827
|
const harness = await setupHandlers();
|
|
827
828
|
await harness.callTool('gog_sheets_named_ranges_update', { spreadsheetId: 'sid', nameOrId: 'MyRange', name: 'NewName', range: 'Sheet1!C1:D5' });
|
|
828
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'update', 'sid', 'MyRange', '--name=NewName', '--range=Sheet1!C1:D5'], { account: undefined });
|
|
829
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'update', pos('sid'), pos('MyRange'), '--name=NewName', '--range=Sheet1!C1:D5'], { account: undefined });
|
|
829
830
|
});
|
|
830
831
|
});
|
|
831
832
|
|
|
@@ -835,7 +836,7 @@ describe('gog_sheets_named_ranges_delete', () => {
|
|
|
835
836
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
836
837
|
const harness = await setupHandlers();
|
|
837
838
|
await harness.callTool('gog_sheets_named_ranges_delete', { spreadsheetId: 'sid', nameOrId: 'OldRange' });
|
|
838
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'delete', 'sid', 'OldRange'], { account: undefined });
|
|
839
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'delete', pos('sid'), pos('OldRange')], { account: undefined });
|
|
839
840
|
});
|
|
840
841
|
});
|
|
841
842
|
|
|
@@ -847,7 +848,7 @@ describe('gog_sheets_batch_update', () => {
|
|
|
847
848
|
const data = '[{"range":"Sheet1!A1:B1","values":[["a","b"]]}]';
|
|
848
849
|
await harness.callTool('gog_sheets_batch_update', { spreadsheetId: 'sid', dataJson: data });
|
|
849
850
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
850
|
-
['sheets', 'batch-update', 'sid', `--data-json=${data}`],
|
|
851
|
+
['sheets', 'batch-update', pos('sid'), `--data-json=${data}`],
|
|
851
852
|
{ account: undefined },
|
|
852
853
|
);
|
|
853
854
|
});
|
|
@@ -866,7 +867,7 @@ describe('gog_sheets_batch_update', () => {
|
|
|
866
867
|
});
|
|
867
868
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
868
869
|
[
|
|
869
|
-
'sheets', 'batch-update', 'sid',
|
|
870
|
+
'sheets', 'batch-update', pos('sid'),
|
|
870
871
|
'--data-json=[]',
|
|
871
872
|
'--input=RAW',
|
|
872
873
|
'--include-values-in-response',
|
|
@@ -884,7 +885,7 @@ describe('gog_sheets_batch_update', () => {
|
|
|
884
885
|
spreadsheetId: 'sid', dataJson: '[]', includeValuesInResponse: false,
|
|
885
886
|
});
|
|
886
887
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
887
|
-
['sheets', 'batch-update', 'sid', '--data-json=[]'],
|
|
888
|
+
['sheets', 'batch-update', pos('sid'), '--data-json=[]'],
|
|
888
889
|
{ account: undefined },
|
|
889
890
|
);
|
|
890
891
|
});
|
|
@@ -897,7 +898,7 @@ describe('gog_sheets_reorder_tab', () => {
|
|
|
897
898
|
const harness = await setupHandlers();
|
|
898
899
|
await harness.callTool('gog_sheets_reorder_tab', { spreadsheetId: 'sid', tab: 'Data', to: 2 });
|
|
899
900
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
900
|
-
['sheets', 'reorder-tab', 'sid', '--tab=Data', '--to=2'],
|
|
901
|
+
['sheets', 'reorder-tab', pos('sid'), '--tab=Data', '--to=2'],
|
|
901
902
|
{ account: undefined },
|
|
902
903
|
);
|
|
903
904
|
});
|
|
@@ -907,7 +908,7 @@ describe('gog_sheets_reorder_tab', () => {
|
|
|
907
908
|
const harness = await setupHandlers();
|
|
908
909
|
await harness.callTool('gog_sheets_reorder_tab', { spreadsheetId: 'sid', tab: '123', to: 0 });
|
|
909
910
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
910
|
-
['sheets', 'reorder-tab', 'sid', '--tab=123', '--to=0'],
|
|
911
|
+
['sheets', 'reorder-tab', pos('sid'), '--tab=123', '--to=0'],
|
|
911
912
|
{ account: undefined },
|
|
912
913
|
);
|
|
913
914
|
});
|
|
@@ -917,7 +918,7 @@ describe('gog_sheets_reorder_tab', () => {
|
|
|
917
918
|
const harness = await setupHandlers();
|
|
918
919
|
await harness.callTool('gog_sheets_reorder_tab', { spreadsheetId: 'sid', tab: 'Data', to: 1, account: 'a@b.com' });
|
|
919
920
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
920
|
-
['sheets', 'reorder-tab', 'sid', '--tab=Data', '--to=1'],
|
|
921
|
+
['sheets', 'reorder-tab', pos('sid'), '--tab=Data', '--to=1'],
|
|
921
922
|
{ account: 'a@b.com' },
|
|
922
923
|
);
|
|
923
924
|
});
|
|
@@ -929,14 +930,14 @@ describe('gog_sheets_chart_list', () => {
|
|
|
929
930
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
930
931
|
const harness = await setupHandlers();
|
|
931
932
|
await harness.callTool('gog_sheets_chart_list', { spreadsheetId: 'sid' });
|
|
932
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'list', 'sid'], { account: undefined });
|
|
933
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'list', pos('sid')], { account: undefined });
|
|
933
934
|
});
|
|
934
935
|
|
|
935
936
|
it('forwards account', async () => {
|
|
936
937
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
937
938
|
const harness = await setupHandlers();
|
|
938
939
|
await harness.callTool('gog_sheets_chart_list', { spreadsheetId: 'sid', account: 'a@b.com' });
|
|
939
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'list', 'sid'], { account: 'a@b.com' });
|
|
940
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'list', pos('sid')], { account: 'a@b.com' });
|
|
940
941
|
});
|
|
941
942
|
});
|
|
942
943
|
|
|
@@ -946,7 +947,7 @@ describe('gog_sheets_chart_get', () => {
|
|
|
946
947
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
947
948
|
const harness = await setupHandlers();
|
|
948
949
|
await harness.callTool('gog_sheets_chart_get', { spreadsheetId: 'sid', chartId: '12345' });
|
|
949
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'get', 'sid', '12345'], { account: undefined });
|
|
950
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'get', pos('sid'), pos('12345')], { account: undefined });
|
|
950
951
|
});
|
|
951
952
|
});
|
|
952
953
|
|
|
@@ -958,7 +959,7 @@ describe('gog_sheets_chart_create', () => {
|
|
|
958
959
|
const spec = '{"basicChart":{"chartType":"COLUMN"}}';
|
|
959
960
|
await harness.callTool('gog_sheets_chart_create', { spreadsheetId: 'sid', specJson: spec });
|
|
960
961
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
961
|
-
['sheets', 'chart', 'create', 'sid', `--spec-json=${spec}`],
|
|
962
|
+
['sheets', 'chart', 'create', pos('sid'), `--spec-json=${spec}`],
|
|
962
963
|
{ account: undefined },
|
|
963
964
|
);
|
|
964
965
|
});
|
|
@@ -970,7 +971,7 @@ describe('gog_sheets_chart_create', () => {
|
|
|
970
971
|
spreadsheetId: 'sid', specJson: '{}', sheet: 'Data', anchor: 'E10', width: 800, height: 400,
|
|
971
972
|
});
|
|
972
973
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
973
|
-
['sheets', 'chart', 'create', 'sid', '--spec-json={}', '--sheet=Data', '--anchor=E10', '--width=800', '--height=400'],
|
|
974
|
+
['sheets', 'chart', 'create', pos('sid'), '--spec-json={}', '--sheet=Data', '--anchor=E10', '--width=800', '--height=400'],
|
|
974
975
|
{ account: undefined },
|
|
975
976
|
);
|
|
976
977
|
});
|
|
@@ -980,7 +981,7 @@ describe('gog_sheets_chart_create', () => {
|
|
|
980
981
|
const harness = await setupHandlers();
|
|
981
982
|
await harness.callTool('gog_sheets_chart_create', { spreadsheetId: 'sid', specJson: '{}', width: 0, height: 0 });
|
|
982
983
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
983
|
-
['sheets', 'chart', 'create', 'sid', '--spec-json={}', '--width=0', '--height=0'],
|
|
984
|
+
['sheets', 'chart', 'create', pos('sid'), '--spec-json={}', '--width=0', '--height=0'],
|
|
984
985
|
{ account: undefined },
|
|
985
986
|
);
|
|
986
987
|
});
|
|
@@ -993,7 +994,7 @@ describe('gog_sheets_chart_update', () => {
|
|
|
993
994
|
const harness = await setupHandlers();
|
|
994
995
|
await harness.callTool('gog_sheets_chart_update', { spreadsheetId: 'sid', chartId: '99', specJson: '{}' });
|
|
995
996
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
996
|
-
['sheets', 'chart', 'update', 'sid', '99', '--spec-json={}'],
|
|
997
|
+
['sheets', 'chart', 'update', pos('sid'), pos('99'), '--spec-json={}'],
|
|
997
998
|
{ account: undefined },
|
|
998
999
|
);
|
|
999
1000
|
});
|
|
@@ -1005,7 +1006,7 @@ describe('gog_sheets_chart_delete', () => {
|
|
|
1005
1006
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1006
1007
|
const harness = await setupHandlers();
|
|
1007
1008
|
await harness.callTool('gog_sheets_chart_delete', { spreadsheetId: 'sid', chartId: '7' });
|
|
1008
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'delete', 'sid', '7', '--force'], { account: undefined });
|
|
1009
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'chart', 'delete', pos('sid'), pos('7'), '--force'], { account: undefined });
|
|
1009
1010
|
});
|
|
1010
1011
|
});
|
|
1011
1012
|
|
|
@@ -1015,7 +1016,7 @@ describe('gog_sheets_table_list', () => {
|
|
|
1015
1016
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1016
1017
|
const harness = await setupHandlers();
|
|
1017
1018
|
await harness.callTool('gog_sheets_table_list', { spreadsheetId: 'sid' });
|
|
1018
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'list', 'sid'], { account: undefined });
|
|
1019
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'list', pos('sid')], { account: undefined });
|
|
1019
1020
|
});
|
|
1020
1021
|
});
|
|
1021
1022
|
|
|
@@ -1025,7 +1026,7 @@ describe('gog_sheets_table_get', () => {
|
|
|
1025
1026
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1026
1027
|
const harness = await setupHandlers();
|
|
1027
1028
|
await harness.callTool('gog_sheets_table_get', { spreadsheetId: 'sid', tableId: 't1' });
|
|
1028
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'get', 'sid', 't1'], { account: undefined });
|
|
1029
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'get', pos('sid'), pos('t1')], { account: undefined });
|
|
1029
1030
|
});
|
|
1030
1031
|
});
|
|
1031
1032
|
|
|
@@ -1037,7 +1038,7 @@ describe('gog_sheets_table_create', () => {
|
|
|
1037
1038
|
const cols = '[{"columnName":"Name","columnType":"TEXT"}]';
|
|
1038
1039
|
await harness.callTool('gog_sheets_table_create', { spreadsheetId: 'sid', range: 'Sheet1!A1:B10', name: 'People', columnsJson: cols });
|
|
1039
1040
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1040
|
-
['sheets', 'table', 'create', 'sid', 'Sheet1!A1:B10', '--name=People', `--columns-json=${cols}`],
|
|
1041
|
+
['sheets', 'table', 'create', pos('sid'), pos('Sheet1!A1:B10'), '--name=People', `--columns-json=${cols}`],
|
|
1041
1042
|
{ account: undefined },
|
|
1042
1043
|
);
|
|
1043
1044
|
});
|
|
@@ -1050,7 +1051,7 @@ describe('gog_sheets_table_append', () => {
|
|
|
1050
1051
|
const harness = await setupHandlers();
|
|
1051
1052
|
await harness.callTool('gog_sheets_table_append', { spreadsheetId: 'sid', tableId: 't1', valuesJson: '[["a",1]]' });
|
|
1052
1053
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1053
|
-
['sheets', 'table', 'append', 'sid', 't1', '--values-json=[["a",1]]'],
|
|
1054
|
+
['sheets', 'table', 'append', pos('sid'), pos('t1'), '--values-json=[["a",1]]'],
|
|
1054
1055
|
{ account: undefined },
|
|
1055
1056
|
);
|
|
1056
1057
|
});
|
|
@@ -1060,7 +1061,7 @@ describe('gog_sheets_table_append', () => {
|
|
|
1060
1061
|
const harness = await setupHandlers();
|
|
1061
1062
|
await harness.callTool('gog_sheets_table_append', { spreadsheetId: 'sid', tableId: 't1', valuesJson: '[]', input: 'RAW' });
|
|
1062
1063
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1063
|
-
['sheets', 'table', 'append', 'sid', 't1', '--values-json=[]', '--input=RAW'],
|
|
1064
|
+
['sheets', 'table', 'append', pos('sid'), pos('t1'), '--values-json=[]', '--input=RAW'],
|
|
1064
1065
|
{ account: undefined },
|
|
1065
1066
|
);
|
|
1066
1067
|
});
|
|
@@ -1072,7 +1073,7 @@ describe('gog_sheets_table_clear', () => {
|
|
|
1072
1073
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1073
1074
|
const harness = await setupHandlers();
|
|
1074
1075
|
await harness.callTool('gog_sheets_table_clear', { spreadsheetId: 'sid', tableId: 't1' });
|
|
1075
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'clear', 'sid', 't1', '--force'], { account: undefined });
|
|
1076
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'clear', pos('sid'), pos('t1'), '--force'], { account: undefined });
|
|
1076
1077
|
});
|
|
1077
1078
|
});
|
|
1078
1079
|
|
|
@@ -1082,7 +1083,7 @@ describe('gog_sheets_table_delete', () => {
|
|
|
1082
1083
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1083
1084
|
const harness = await setupHandlers();
|
|
1084
1085
|
await harness.callTool('gog_sheets_table_delete', { spreadsheetId: 'sid', tableId: 't1', keep_data: false });
|
|
1085
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'delete', 'sid', 't1', '--discard-data', '--force'], { account: undefined });
|
|
1086
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'table', 'delete', pos('sid'), pos('t1'), '--discard-data', '--force'], { account: undefined });
|
|
1086
1087
|
expect(lib.run).not.toHaveBeenCalled();
|
|
1087
1088
|
});
|
|
1088
1089
|
|
|
@@ -1094,10 +1095,10 @@ describe('gog_sheets_table_delete', () => {
|
|
|
1094
1095
|
.mockResolvedValueOnce('{"updatedRows":2}'); // update restore
|
|
1095
1096
|
const harness = await setupHandlers();
|
|
1096
1097
|
const res = await harness.callTool('gog_sheets_table_delete', { spreadsheetId: 'sid', tableId: 't1', account: 'a@b.com' });
|
|
1097
|
-
expect(lib.run).toHaveBeenNthCalledWith(1, ['sheets', 'table', 'get', 'sid', 't1'], { account: 'a@b.com' });
|
|
1098
|
-
expect(lib.run).toHaveBeenNthCalledWith(2, ['sheets', 'get', 'sid', 'Sheet1!A1:C2', '--render=FORMULA'], { account: 'a@b.com' });
|
|
1099
|
-
expect(lib.run).toHaveBeenNthCalledWith(3, ['sheets', 'table', 'delete', 'sid', 't1', '--discard-data', '--force'], { account: 'a@b.com' });
|
|
1100
|
-
expect(lib.run).toHaveBeenNthCalledWith(4, ['sheets', 'update', 'sid', 'Sheet1!A1:C2', '--values-json=[["Name","City","N"],["A","NYC","=1+1"]]'], { account: 'a@b.com' });
|
|
1098
|
+
expect(lib.run).toHaveBeenNthCalledWith(1, ['sheets', 'table', 'get', pos('sid'), pos('t1')], { account: 'a@b.com' });
|
|
1099
|
+
expect(lib.run).toHaveBeenNthCalledWith(2, ['sheets', 'get', pos('sid'), pos('Sheet1!A1:C2'), '--render=FORMULA'], { account: 'a@b.com' });
|
|
1100
|
+
expect(lib.run).toHaveBeenNthCalledWith(3, ['sheets', 'table', 'delete', pos('sid'), pos('t1'), '--discard-data', '--force'], { account: 'a@b.com' });
|
|
1101
|
+
expect(lib.run).toHaveBeenNthCalledWith(4, ['sheets', 'update', pos('sid'), pos('Sheet1!A1:C2'), '--values-json=[["Name","City","N"],["A","NYC","=1+1"]]'], { account: 'a@b.com' });
|
|
1101
1102
|
expect(res.content[0].text).toContain('2 row');
|
|
1102
1103
|
expect(res.content[0].text).toContain('Sheet1!A1:C2');
|
|
1103
1104
|
});
|
|
@@ -1163,14 +1164,14 @@ describe('gog_sheets_banding_list', () => {
|
|
|
1163
1164
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1164
1165
|
const harness = await setupHandlers();
|
|
1165
1166
|
await harness.callTool('gog_sheets_banding_list', { spreadsheetId: 'sid' });
|
|
1166
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'list', 'sid'], { account: undefined });
|
|
1167
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'list', pos('sid')], { account: undefined });
|
|
1167
1168
|
});
|
|
1168
1169
|
|
|
1169
1170
|
it('includes --sheet when provided', async () => {
|
|
1170
1171
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1171
1172
|
const harness = await setupHandlers();
|
|
1172
1173
|
await harness.callTool('gog_sheets_banding_list', { spreadsheetId: 'sid', sheet: 'Data' });
|
|
1173
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'list', 'sid', '--sheet=Data'], { account: undefined });
|
|
1174
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'list', pos('sid'), '--sheet=Data'], { account: undefined });
|
|
1174
1175
|
});
|
|
1175
1176
|
});
|
|
1176
1177
|
|
|
@@ -1180,7 +1181,7 @@ describe('gog_sheets_banding_set', () => {
|
|
|
1180
1181
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1181
1182
|
const harness = await setupHandlers();
|
|
1182
1183
|
await harness.callTool('gog_sheets_banding_set', { spreadsheetId: 'sid', range: 'Sheet1!A1:D20' });
|
|
1183
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'set', 'sid', 'Sheet1!A1:D20'], { account: undefined });
|
|
1184
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'set', pos('sid'), pos('Sheet1!A1:D20')], { account: undefined });
|
|
1184
1185
|
});
|
|
1185
1186
|
|
|
1186
1187
|
it('includes --row-properties-json and --column-properties-json when provided', async () => {
|
|
@@ -1192,7 +1193,7 @@ describe('gog_sheets_banding_set', () => {
|
|
|
1192
1193
|
columnPropertiesJson: '{"secondBandColor":{}}',
|
|
1193
1194
|
});
|
|
1194
1195
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1195
|
-
['sheets', 'banding', 'set', 'sid', 'A1:D20', '--row-properties-json={"firstBandColor":{}}', '--column-properties-json={"secondBandColor":{}}'],
|
|
1196
|
+
['sheets', 'banding', 'set', pos('sid'), pos('A1:D20'), '--row-properties-json={"firstBandColor":{}}', '--column-properties-json={"secondBandColor":{}}'],
|
|
1196
1197
|
{ account: undefined },
|
|
1197
1198
|
);
|
|
1198
1199
|
});
|
|
@@ -1204,28 +1205,28 @@ describe('gog_sheets_banding_clear', () => {
|
|
|
1204
1205
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1205
1206
|
const harness = await setupHandlers();
|
|
1206
1207
|
await harness.callTool('gog_sheets_banding_clear', { spreadsheetId: 'sid' });
|
|
1207
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', 'sid', '--force'], { account: undefined });
|
|
1208
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', pos('sid'), '--force'], { account: undefined });
|
|
1208
1209
|
});
|
|
1209
1210
|
|
|
1210
1211
|
it('includes --id when provided (including 0)', async () => {
|
|
1211
1212
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1212
1213
|
const harness = await setupHandlers();
|
|
1213
1214
|
await harness.callTool('gog_sheets_banding_clear', { spreadsheetId: 'sid', id: 0 });
|
|
1214
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', 'sid', '--id=0', '--force'], { account: undefined });
|
|
1215
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', pos('sid'), '--id=0', '--force'], { account: undefined });
|
|
1215
1216
|
});
|
|
1216
1217
|
|
|
1217
1218
|
it('includes --all and --sheet when clearing a whole sheet', async () => {
|
|
1218
1219
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1219
1220
|
const harness = await setupHandlers();
|
|
1220
1221
|
await harness.callTool('gog_sheets_banding_clear', { spreadsheetId: 'sid', all: true, sheet: 'Data' });
|
|
1221
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', 'sid', '--all', '--sheet=Data', '--force'], { account: undefined });
|
|
1222
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', pos('sid'), '--all', '--sheet=Data', '--force'], { account: undefined });
|
|
1222
1223
|
});
|
|
1223
1224
|
|
|
1224
1225
|
it('omits --all when false', async () => {
|
|
1225
1226
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1226
1227
|
const harness = await setupHandlers();
|
|
1227
1228
|
await harness.callTool('gog_sheets_banding_clear', { spreadsheetId: 'sid', all: false, id: 5 });
|
|
1228
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', 'sid', '--id=5', '--force'], { account: undefined });
|
|
1229
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'banding', 'clear', pos('sid'), '--id=5', '--force'], { account: undefined });
|
|
1229
1230
|
});
|
|
1230
1231
|
});
|
|
1231
1232
|
|
|
@@ -1235,14 +1236,14 @@ describe('gog_sheets_conditional_format_list', () => {
|
|
|
1235
1236
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1236
1237
|
const harness = await setupHandlers();
|
|
1237
1238
|
await harness.callTool('gog_sheets_conditional_format_list', { spreadsheetId: 'sid' });
|
|
1238
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'list', 'sid'], { account: undefined });
|
|
1239
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'list', pos('sid')], { account: undefined });
|
|
1239
1240
|
});
|
|
1240
1241
|
|
|
1241
1242
|
it('includes --sheet when provided', async () => {
|
|
1242
1243
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1243
1244
|
const harness = await setupHandlers();
|
|
1244
1245
|
await harness.callTool('gog_sheets_conditional_format_list', { spreadsheetId: 'sid', sheet: 'Data' });
|
|
1245
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'list', 'sid', '--sheet=Data'], { account: undefined });
|
|
1246
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'list', pos('sid'), '--sheet=Data'], { account: undefined });
|
|
1246
1247
|
});
|
|
1247
1248
|
});
|
|
1248
1249
|
|
|
@@ -1255,7 +1256,7 @@ describe('gog_sheets_conditional_format_add', () => {
|
|
|
1255
1256
|
spreadsheetId: 'sid', range: 'A1:A100', type: 'not-blank', formatJson: '{"backgroundColor":{}}',
|
|
1256
1257
|
});
|
|
1257
1258
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1258
|
-
['sheets', 'conditional-format', 'add', 'sid', 'A1:A100', '--type=not-blank', '--format-json={"backgroundColor":{}}'],
|
|
1259
|
+
['sheets', 'conditional-format', 'add', pos('sid'), pos('A1:A100'), '--type=not-blank', '--format-json={"backgroundColor":{}}'],
|
|
1259
1260
|
{ account: undefined },
|
|
1260
1261
|
);
|
|
1261
1262
|
});
|
|
@@ -1267,7 +1268,7 @@ describe('gog_sheets_conditional_format_add', () => {
|
|
|
1267
1268
|
spreadsheetId: 'sid', range: 'B1:B50', type: 'number-gt', expr: '100', formatJson: '{}', formatFields: 'backgroundColor,textFormat.bold',
|
|
1268
1269
|
});
|
|
1269
1270
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1270
|
-
['sheets', 'conditional-format', 'add', 'sid', 'B1:B50', '--type=number-gt', '--format-json={}', '--expr=100', '--format-fields=backgroundColor,textFormat.bold'],
|
|
1271
|
+
['sheets', 'conditional-format', 'add', pos('sid'), pos('B1:B50'), '--type=number-gt', '--format-json={}', '--expr=100', '--format-fields=backgroundColor,textFormat.bold'],
|
|
1271
1272
|
{ account: undefined },
|
|
1272
1273
|
);
|
|
1273
1274
|
});
|
|
@@ -1279,7 +1280,7 @@ describe('gog_sheets_conditional_format_add', () => {
|
|
|
1279
1280
|
spreadsheetId: 'sid', range: 'A1', type: 'text-eq', expr: '', formatJson: '{}',
|
|
1280
1281
|
});
|
|
1281
1282
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1282
|
-
['sheets', 'conditional-format', 'add', 'sid', 'A1', '--type=text-eq', '--format-json={}', '--expr='],
|
|
1283
|
+
['sheets', 'conditional-format', 'add', pos('sid'), pos('A1'), '--type=text-eq', '--format-json={}', '--expr='],
|
|
1283
1284
|
{ account: undefined },
|
|
1284
1285
|
);
|
|
1285
1286
|
});
|
|
@@ -1291,7 +1292,7 @@ describe('gog_sheets_conditional_format_add', () => {
|
|
|
1291
1292
|
spreadsheetId: 'sid', range: 'Sheet1!A1:A100', gradientRuleJson: '{"minpoint":{},"maxpoint":{}}',
|
|
1292
1293
|
});
|
|
1293
1294
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1294
|
-
['sheets', 'conditional-format', 'add', 'sid', 'Sheet1!A1:A100', '--gradient-rule-json={"minpoint":{},"maxpoint":{}}'],
|
|
1295
|
+
['sheets', 'conditional-format', 'add', pos('sid'), pos('Sheet1!A1:A100'), '--gradient-rule-json={"minpoint":{},"maxpoint":{}}'],
|
|
1295
1296
|
{ account: undefined },
|
|
1296
1297
|
);
|
|
1297
1298
|
});
|
|
@@ -1304,7 +1305,7 @@ describe('gog_sheets_filter_set', () => {
|
|
|
1304
1305
|
const harness = await setupHandlers();
|
|
1305
1306
|
await harness.callTool('gog_sheets_filter_set', { spreadsheetId: 'sid', range: 'Sheet1!A1:C10' });
|
|
1306
1307
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1307
|
-
['sheets', 'filter', 'set', 'sid', 'Sheet1!A1:C10'],
|
|
1308
|
+
['sheets', 'filter', 'set', pos('sid'), pos('Sheet1!A1:C10')],
|
|
1308
1309
|
{ account: undefined },
|
|
1309
1310
|
);
|
|
1310
1311
|
});
|
|
@@ -1314,7 +1315,7 @@ describe('gog_sheets_filter_set', () => {
|
|
|
1314
1315
|
const harness = await setupHandlers();
|
|
1315
1316
|
await harness.callTool('gog_sheets_filter_set', { spreadsheetId: 'sid', range: 'Sheet1!A1:C10', replace: true });
|
|
1316
1317
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1317
|
-
['sheets', 'filter', 'set', 'sid', 'Sheet1!A1:C10', '--force'],
|
|
1318
|
+
['sheets', 'filter', 'set', pos('sid'), pos('Sheet1!A1:C10'), '--force'],
|
|
1318
1319
|
{ account: undefined },
|
|
1319
1320
|
);
|
|
1320
1321
|
});
|
|
@@ -1324,7 +1325,7 @@ describe('gog_sheets_filter_set', () => {
|
|
|
1324
1325
|
const harness = await setupHandlers();
|
|
1325
1326
|
await harness.callTool('gog_sheets_filter_set', { spreadsheetId: 'sid', range: 'Named', account: 'x@y.com' });
|
|
1326
1327
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1327
|
-
['sheets', 'filter', 'set', 'sid', 'Named'],
|
|
1328
|
+
['sheets', 'filter', 'set', pos('sid'), pos('Named')],
|
|
1328
1329
|
{ account: 'x@y.com' },
|
|
1329
1330
|
);
|
|
1330
1331
|
});
|
|
@@ -1336,28 +1337,28 @@ describe('gog_sheets_conditional_format_clear', () => {
|
|
|
1336
1337
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1337
1338
|
const harness = await setupHandlers();
|
|
1338
1339
|
await harness.callTool('gog_sheets_conditional_format_clear', { spreadsheetId: 'sid', sheet: 'Data' });
|
|
1339
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', 'sid', '--sheet=Data', '--force'], { account: undefined });
|
|
1340
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', pos('sid'), '--sheet=Data', '--force'], { account: undefined });
|
|
1340
1341
|
});
|
|
1341
1342
|
|
|
1342
1343
|
it('includes --index when provided (including 0)', async () => {
|
|
1343
1344
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1344
1345
|
const harness = await setupHandlers();
|
|
1345
1346
|
await harness.callTool('gog_sheets_conditional_format_clear', { spreadsheetId: 'sid', sheet: 'Data', index: 0 });
|
|
1346
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', 'sid', '--sheet=Data', '--index=0', '--force'], { account: undefined });
|
|
1347
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', pos('sid'), '--sheet=Data', '--index=0', '--force'], { account: undefined });
|
|
1347
1348
|
});
|
|
1348
1349
|
|
|
1349
1350
|
it('includes --all when true', async () => {
|
|
1350
1351
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1351
1352
|
const harness = await setupHandlers();
|
|
1352
1353
|
await harness.callTool('gog_sheets_conditional_format_clear', { spreadsheetId: 'sid', sheet: 'Data', all: true });
|
|
1353
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', 'sid', '--sheet=Data', '--all', '--force'], { account: undefined });
|
|
1354
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', pos('sid'), '--sheet=Data', '--all', '--force'], { account: undefined });
|
|
1354
1355
|
});
|
|
1355
1356
|
|
|
1356
1357
|
it('omits --all when false', async () => {
|
|
1357
1358
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1358
1359
|
const harness = await setupHandlers();
|
|
1359
1360
|
await harness.callTool('gog_sheets_conditional_format_clear', { spreadsheetId: 'sid', sheet: 'Data', all: false, index: 2 });
|
|
1360
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', 'sid', '--sheet=Data', '--index=2', '--force'], { account: undefined });
|
|
1361
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'conditional-format', 'clear', pos('sid'), '--sheet=Data', '--index=2', '--force'], { account: undefined });
|
|
1361
1362
|
});
|
|
1362
1363
|
});
|
|
1363
1364
|
|
|
@@ -1367,14 +1368,14 @@ describe('gog_sheets_snapshot', () => {
|
|
|
1367
1368
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1368
1369
|
const harness = await setupHandlers();
|
|
1369
1370
|
await harness.callTool('gog_sheets_snapshot', { spreadsheetId: 'sid', name: 'Backup A' });
|
|
1370
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', 'sid', 'Backup A'], { account: undefined });
|
|
1371
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', pos('sid'), pos('Backup A')], { account: undefined });
|
|
1371
1372
|
});
|
|
1372
1373
|
|
|
1373
1374
|
it('includes --parent and forwards account', async () => {
|
|
1374
1375
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1375
1376
|
const harness = await setupHandlers();
|
|
1376
1377
|
await harness.callTool('gog_sheets_snapshot', { spreadsheetId: 'sid', name: 'Backup A', parent: 'folder1', account: 'a@b.com' });
|
|
1377
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', 'sid', 'Backup A', '--parent=folder1'], { account: 'a@b.com' });
|
|
1378
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', pos('sid'), pos('Backup A'), '--parent=folder1'], { account: 'a@b.com' });
|
|
1378
1379
|
});
|
|
1379
1380
|
});
|
|
1380
1381
|
|
|
@@ -1385,7 +1386,7 @@ describe('gog_sheets_validation_get', () => {
|
|
|
1385
1386
|
const harness = await setupHandlers();
|
|
1386
1387
|
await harness.callTool('gog_sheets_validation_get', { spreadsheetId: 'sid', range: 'Sheet1!A1:A10' });
|
|
1387
1388
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1388
|
-
['sheets', 'validation', 'get', 'sid', 'Sheet1!A1:A10'],
|
|
1389
|
+
['sheets', 'validation', 'get', pos('sid'), pos('Sheet1!A1:A10')],
|
|
1389
1390
|
{ account: undefined },
|
|
1390
1391
|
);
|
|
1391
1392
|
});
|
|
@@ -1399,7 +1400,7 @@ describe('gog_sheets_validation_set', () => {
|
|
|
1399
1400
|
spreadsheetId: 'sid', range: 'A1:A10', type: 'ONE_OF_LIST', values: ['Red', 'Green'],
|
|
1400
1401
|
});
|
|
1401
1402
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1402
|
-
['sheets', 'validation', 'set', 'sid', 'A1:A10', '--type=ONE_OF_LIST', '--value=Red', '--value=Green'],
|
|
1403
|
+
['sheets', 'validation', 'set', pos('sid'), pos('A1:A10'), '--type=ONE_OF_LIST', '--value=Red', '--value=Green'],
|
|
1403
1404
|
{ account: undefined },
|
|
1404
1405
|
);
|
|
1405
1406
|
});
|
|
@@ -1412,7 +1413,7 @@ describe('gog_sheets_validation_set', () => {
|
|
|
1412
1413
|
strict: true, inputMessage: 'Pick 1-10', showCustomUi: true, filteredRowsIncluded: true,
|
|
1413
1414
|
});
|
|
1414
1415
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1415
|
-
['sheets', 'validation', 'set', 'sid', 'A1', '--type=NUMBER_BETWEEN', '--value=1', '--value=10',
|
|
1416
|
+
['sheets', 'validation', 'set', pos('sid'), pos('A1'), '--type=NUMBER_BETWEEN', '--value=1', '--value=10',
|
|
1416
1417
|
'--strict', '--input-message=Pick 1-10', '--show-custom-ui', '--filtered-rows-included'],
|
|
1417
1418
|
{ account: undefined },
|
|
1418
1419
|
);
|
|
@@ -1425,7 +1426,7 @@ describe('gog_sheets_validation_clear', () => {
|
|
|
1425
1426
|
const harness = await setupHandlers();
|
|
1426
1427
|
await harness.callTool('gog_sheets_validation_clear', { spreadsheetId: 'sid', range: 'A1:A10', filteredRowsIncluded: true });
|
|
1427
1428
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1428
|
-
['sheets', 'validation', 'clear', 'sid', 'A1:A10', '--filtered-rows-included'],
|
|
1429
|
+
['sheets', 'validation', 'clear', pos('sid'), pos('A1:A10'), '--filtered-rows-included'],
|
|
1429
1430
|
{ account: undefined },
|
|
1430
1431
|
);
|
|
1431
1432
|
});
|
|
@@ -1439,7 +1440,7 @@ describe('gog_sheets_delete_dimension', () => {
|
|
|
1439
1440
|
spreadsheetId: 'sid', rangeOrSheet: 'Sheet1', dimension: 'ROWS', start: 5, end: 7,
|
|
1440
1441
|
});
|
|
1441
1442
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1442
|
-
['sheets', 'delete-dimension', 'sid', 'Sheet1', '--dimension=ROWS', '--start=5', '--end=7', '--force'],
|
|
1443
|
+
['sheets', 'delete-dimension', pos('sid'), pos('Sheet1'), '--dimension=ROWS', '--start=5', '--end=7', '--force'],
|
|
1443
1444
|
{ account: undefined },
|
|
1444
1445
|
);
|
|
1445
1446
|
});
|
|
@@ -1451,7 +1452,7 @@ describe('gog_sheets_delete_dimension', () => {
|
|
|
1451
1452
|
spreadsheetId: 'sid', rangeOrSheet: 'Sheet1!C:D', dimension: 'COLUMNS', account: 'a@b.com',
|
|
1452
1453
|
});
|
|
1453
1454
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1454
|
-
['sheets', 'delete-dimension', 'sid', 'Sheet1!C:D', '--dimension=COLUMNS', '--force'],
|
|
1455
|
+
['sheets', 'delete-dimension', pos('sid'), pos('Sheet1!C:D'), '--dimension=COLUMNS', '--force'],
|
|
1455
1456
|
{ account: 'a@b.com' },
|
|
1456
1457
|
);
|
|
1457
1458
|
});
|
|
@@ -1464,7 +1465,7 @@ describe('validation tools bare calls', () => {
|
|
|
1464
1465
|
const harness = await setupHandlers();
|
|
1465
1466
|
await harness.callTool('gog_sheets_validation_set', { spreadsheetId: 'sid', range: 'A1', type: 'BOOLEAN' });
|
|
1466
1467
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1467
|
-
['sheets', 'validation', 'set', 'sid', 'A1', '--type=BOOLEAN'],
|
|
1468
|
+
['sheets', 'validation', 'set', pos('sid'), pos('A1'), '--type=BOOLEAN'],
|
|
1468
1469
|
{ account: undefined },
|
|
1469
1470
|
);
|
|
1470
1471
|
});
|
|
@@ -1474,7 +1475,7 @@ describe('validation tools bare calls', () => {
|
|
|
1474
1475
|
const harness = await setupHandlers();
|
|
1475
1476
|
await harness.callTool('gog_sheets_validation_clear', { spreadsheetId: 'sid', range: 'A1' });
|
|
1476
1477
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1477
|
-
['sheets', 'validation', 'clear', 'sid', 'A1'],
|
|
1478
|
+
['sheets', 'validation', 'clear', pos('sid'), pos('A1')],
|
|
1478
1479
|
{ account: undefined },
|
|
1479
1480
|
);
|
|
1480
1481
|
});
|
|
@@ -1517,14 +1518,14 @@ describe('gog_sheets_datasource_list', () => {
|
|
|
1517
1518
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1518
1519
|
const harness = await setupHandlers();
|
|
1519
1520
|
await harness.callTool('gog_sheets_datasource_list', { spreadsheetId: 'sid' });
|
|
1520
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'datasource', 'list', 'sid'], { account: undefined });
|
|
1521
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'datasource', 'list', pos('sid')], { account: undefined });
|
|
1521
1522
|
});
|
|
1522
1523
|
|
|
1523
1524
|
it('forwards account', async () => {
|
|
1524
1525
|
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
1525
1526
|
const harness = await setupHandlers();
|
|
1526
1527
|
await harness.callTool('gog_sheets_datasource_list', { spreadsheetId: 'sid', account: 'me@x.com' });
|
|
1527
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'datasource', 'list', 'sid'], { account: 'me@x.com' });
|
|
1528
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'datasource', 'list', pos('sid')], { account: 'me@x.com' });
|
|
1528
1529
|
});
|
|
1529
1530
|
});
|
|
1530
1531
|
|
|
@@ -1534,7 +1535,7 @@ describe('gog_sheets_datasource_describe', () => {
|
|
|
1534
1535
|
const harness = await setupHandlers();
|
|
1535
1536
|
await harness.callTool('gog_sheets_datasource_describe', { spreadsheetId: 'sid', dataSourceId: 'ds1' });
|
|
1536
1537
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1537
|
-
['sheets', 'datasource', 'describe', 'sid', 'ds1'],
|
|
1538
|
+
['sheets', 'datasource', 'describe', pos('sid'), pos('ds1')],
|
|
1538
1539
|
{ account: undefined },
|
|
1539
1540
|
);
|
|
1540
1541
|
});
|
|
@@ -1546,7 +1547,7 @@ describe('gog_sheets_datasource_table_list', () => {
|
|
|
1546
1547
|
const harness = await setupHandlers();
|
|
1547
1548
|
await harness.callTool('gog_sheets_datasource_table_list', { spreadsheetId: 'sid' });
|
|
1548
1549
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1549
|
-
['sheets', 'datasource', 'table', 'list', 'sid'],
|
|
1550
|
+
['sheets', 'datasource', 'table', 'list', pos('sid')],
|
|
1550
1551
|
{ account: undefined },
|
|
1551
1552
|
);
|
|
1552
1553
|
});
|
|
@@ -1556,7 +1557,7 @@ describe('gog_sheets_datasource_table_list', () => {
|
|
|
1556
1557
|
const harness = await setupHandlers();
|
|
1557
1558
|
await harness.callTool('gog_sheets_datasource_table_list', { spreadsheetId: 'sid', dataSourceId: 'ds1' });
|
|
1558
1559
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1559
|
-
['sheets', 'datasource', 'table', 'list', 'sid', '--data-source-id=ds1'],
|
|
1560
|
+
['sheets', 'datasource', 'table', 'list', pos('sid'), '--data-source-id=ds1'],
|
|
1560
1561
|
{ account: undefined },
|
|
1561
1562
|
);
|
|
1562
1563
|
});
|
|
@@ -1568,7 +1569,7 @@ describe('gog_sheets_datasource_table_describe', () => {
|
|
|
1568
1569
|
const harness = await setupHandlers();
|
|
1569
1570
|
await harness.callTool('gog_sheets_datasource_table_describe', { spreadsheetId: 'sid', anchor: 'Extracts!B3' });
|
|
1570
1571
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1571
|
-
['sheets', 'datasource', 'table', 'describe', 'sid', 'Extracts!B3'],
|
|
1572
|
+
['sheets', 'datasource', 'table', 'describe', pos('sid'), pos('Extracts!B3')],
|
|
1572
1573
|
{ account: undefined },
|
|
1573
1574
|
);
|
|
1574
1575
|
});
|
|
@@ -1580,7 +1581,7 @@ describe('gog_sheets_datasource_table_read', () => {
|
|
|
1580
1581
|
const harness = await setupHandlers();
|
|
1581
1582
|
await harness.callTool('gog_sheets_datasource_table_read', { spreadsheetId: 'sid', anchor: 'Extracts!B3' });
|
|
1582
1583
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1583
|
-
['sheets', 'datasource', 'table', 'read', 'sid', 'Extracts!B3'],
|
|
1584
|
+
['sheets', 'datasource', 'table', 'read', pos('sid'), pos('Extracts!B3')],
|
|
1584
1585
|
{ account: undefined },
|
|
1585
1586
|
);
|
|
1586
1587
|
});
|
|
@@ -1592,7 +1593,7 @@ describe('gog_sheets_datasource_table_read', () => {
|
|
|
1592
1593
|
spreadsheetId: 'sid', anchor: 'Extracts!B3', maxRows: 250, render: 'UNFORMATTED_VALUE',
|
|
1593
1594
|
});
|
|
1594
1595
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1595
|
-
['sheets', 'datasource', 'table', 'read', 'sid', 'Extracts!B3', '--max-rows=250', '--render=UNFORMATTED_VALUE'],
|
|
1596
|
+
['sheets', 'datasource', 'table', 'read', pos('sid'), pos('Extracts!B3'), '--max-rows=250', '--render=UNFORMATTED_VALUE'],
|
|
1596
1597
|
{ account: undefined },
|
|
1597
1598
|
);
|
|
1598
1599
|
});
|
|
@@ -1615,7 +1616,7 @@ describe('gog_sheets_datasource_add', () => {
|
|
|
1615
1616
|
spreadsheetId: 'sid', billingProject: 'my-proj', query: 'SELECT 1',
|
|
1616
1617
|
});
|
|
1617
1618
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1618
|
-
['sheets', 'datasource', 'add', 'sid', '--billing-project=my-proj', '--query=SELECT 1'],
|
|
1619
|
+
['sheets', 'datasource', 'add', pos('sid'), '--billing-project=my-proj', '--query=SELECT 1'],
|
|
1619
1620
|
{ account: undefined },
|
|
1620
1621
|
);
|
|
1621
1622
|
});
|
|
@@ -1627,7 +1628,7 @@ describe('gog_sheets_datasource_add', () => {
|
|
|
1627
1628
|
spreadsheetId: 'sid', billingProject: 'billing', dataset: 'ds', table: 'tbl', tableProject: 'owner',
|
|
1628
1629
|
});
|
|
1629
1630
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1630
|
-
['sheets', 'datasource', 'add', 'sid', '--billing-project=billing', '--table-project=owner', '--dataset=ds', '--table=tbl'],
|
|
1631
|
+
['sheets', 'datasource', 'add', pos('sid'), '--billing-project=billing', '--table-project=owner', '--dataset=ds', '--table=tbl'],
|
|
1631
1632
|
{ account: undefined },
|
|
1632
1633
|
);
|
|
1633
1634
|
});
|
|
@@ -1661,7 +1662,7 @@ describe('gog_sheets_datasource_update', () => {
|
|
|
1661
1662
|
spreadsheetId: 'sid', dataSourceId: 'ds1', query: 'SELECT 2',
|
|
1662
1663
|
});
|
|
1663
1664
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1664
|
-
['sheets', 'datasource', 'update', 'sid', 'ds1', '--query=SELECT 2'],
|
|
1665
|
+
['sheets', 'datasource', 'update', pos('sid'), pos('ds1'), '--query=SELECT 2'],
|
|
1665
1666
|
{ account: undefined },
|
|
1666
1667
|
);
|
|
1667
1668
|
});
|
|
@@ -1673,7 +1674,7 @@ describe('gog_sheets_datasource_update', () => {
|
|
|
1673
1674
|
spreadsheetId: 'sid', dataSourceId: 'ds1', billingProject: 'new-proj', dataset: 'ds2', table: 't2',
|
|
1674
1675
|
});
|
|
1675
1676
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1676
|
-
['sheets', 'datasource', 'update', 'sid', 'ds1', '--billing-project=new-proj', '--dataset=ds2', '--table=t2'],
|
|
1677
|
+
['sheets', 'datasource', 'update', pos('sid'), pos('ds1'), '--billing-project=new-proj', '--dataset=ds2', '--table=t2'],
|
|
1677
1678
|
{ account: undefined },
|
|
1678
1679
|
);
|
|
1679
1680
|
});
|
|
@@ -1685,7 +1686,7 @@ describe('gog_sheets_datasource_update', () => {
|
|
|
1685
1686
|
spreadsheetId: 'sid', dataSourceId: 'ds1', tableProject: 'other-owner',
|
|
1686
1687
|
});
|
|
1687
1688
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1688
|
-
['sheets', 'datasource', 'update', 'sid', 'ds1', '--table-project=other-owner'],
|
|
1689
|
+
['sheets', 'datasource', 'update', pos('sid'), pos('ds1'), '--table-project=other-owner'],
|
|
1689
1690
|
{ account: undefined },
|
|
1690
1691
|
);
|
|
1691
1692
|
});
|
|
@@ -1715,7 +1716,7 @@ describe('gog_sheets_datasource_refresh', () => {
|
|
|
1715
1716
|
const harness = await setupHandlers();
|
|
1716
1717
|
await harness.callTool('gog_sheets_datasource_refresh', { spreadsheetId: 'sid', dataSourceId: 'ds1' });
|
|
1717
1718
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1718
|
-
['sheets', 'datasource', 'refresh', 'sid', 'ds1'],
|
|
1719
|
+
['sheets', 'datasource', 'refresh', pos('sid'), pos('ds1')],
|
|
1719
1720
|
{ account: undefined },
|
|
1720
1721
|
);
|
|
1721
1722
|
});
|
|
@@ -1727,7 +1728,7 @@ describe('gog_sheets_datasource_refresh', () => {
|
|
|
1727
1728
|
spreadsheetId: 'sid', dataSourceId: 'ds1', forceRefresh: true,
|
|
1728
1729
|
});
|
|
1729
1730
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1730
|
-
['sheets', 'datasource', 'refresh', 'sid', 'ds1', '--force-refresh'],
|
|
1731
|
+
['sheets', 'datasource', 'refresh', pos('sid'), pos('ds1'), '--force-refresh'],
|
|
1731
1732
|
{ account: undefined },
|
|
1732
1733
|
);
|
|
1733
1734
|
});
|
|
@@ -1768,7 +1769,7 @@ describe('gog_sheets_datasource_delete', () => {
|
|
|
1768
1769
|
const harness = await setupHandlers();
|
|
1769
1770
|
await harness.callTool('gog_sheets_datasource_delete', { spreadsheetId: 'sid', dataSourceId: 'ds1' });
|
|
1770
1771
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1771
|
-
['sheets', 'datasource', 'delete', 'sid', 'ds1', '--force'],
|
|
1772
|
+
['sheets', 'datasource', 'delete', pos('sid'), pos('ds1'), '--force'],
|
|
1772
1773
|
{ account: undefined },
|
|
1773
1774
|
);
|
|
1774
1775
|
});
|
|
@@ -1780,8 +1781,45 @@ describe('gog_sheets_datasource_delete', () => {
|
|
|
1780
1781
|
spreadsheetId: 'sid', dataSourceId: 'ds1', account: 'me@x.com',
|
|
1781
1782
|
});
|
|
1782
1783
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
1783
|
-
['sheets', 'datasource', 'delete', 'sid', 'ds1', '--force'],
|
|
1784
|
+
['sheets', 'datasource', 'delete', pos('sid'), pos('ds1'), '--force'],
|
|
1784
1785
|
{ account: 'me@x.com' },
|
|
1785
1786
|
);
|
|
1786
1787
|
});
|
|
1787
1788
|
});
|
|
1789
|
+
|
|
1790
|
+
// SEC-3/SEC-4: every model-supplied server path must resolve inside an
|
|
1791
|
+
// operator-configured root (GOG_FILE_ROOTS). The suite runs with '/' so the
|
|
1792
|
+
// arg-shape tests can use any path; these narrow it.
|
|
1793
|
+
async function withFileRoots<T>(roots: string, fn: () => Promise<T>): Promise<T> {
|
|
1794
|
+
const prev = process.env.GOG_FILE_ROOTS;
|
|
1795
|
+
process.env.GOG_FILE_ROOTS = roots;
|
|
1796
|
+
try {
|
|
1797
|
+
return await fn();
|
|
1798
|
+
} finally {
|
|
1799
|
+
process.env.GOG_FILE_ROOTS = prev;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
describe('server paths are confined to GOG_FILE_ROOTS', () => {
|
|
1804
|
+
it.each([
|
|
1805
|
+
['gog_sheets_export', {"spreadsheetId": "s1", "out": "/Users/me/.zshrc"}, 'out'],
|
|
1806
|
+
['gog_sheets_links_set', {"spreadsheetId": "s1", "cellsJson": "@/etc/passwd"}, 'cellsJson'],
|
|
1807
|
+
['gog_sheets_batch_update', {"spreadsheetId": "s1", "dataJson": "@/etc/passwd"}, 'dataJson'],
|
|
1808
|
+
] as Array<[string, Record<string, unknown>, string]>)('%s refuses %j outside the roots', async (tool, args, param) => {
|
|
1809
|
+
const h = await setupHandlers();
|
|
1810
|
+
const result = await withFileRoots('/srv/gog-files', () => h.callTool(tool, args));
|
|
1811
|
+
expect(result.isError).toBe(true);
|
|
1812
|
+
expect(result.content[0].text).toMatch(new RegExp(`${param} ".*" is outside the directories`));
|
|
1813
|
+
expect(lib.runOrDiagnose).not.toHaveBeenCalled();
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1816
|
+
// Clients auto-approve readOnlyHint tools; these write (and can overwrite)
|
|
1817
|
+
// files on the gog host, so they must not claim to be read-only.
|
|
1818
|
+
it.each(["gog_sheets_export"])('%s is not advertised as read-only and is marked destructive', async (name) => {
|
|
1819
|
+
const h = await setupHandlers();
|
|
1820
|
+
const { tools } = await h.client.listTools();
|
|
1821
|
+
const tool = tools.find((t) => t.name === name)!;
|
|
1822
|
+
expect(tool.annotations?.readOnlyHint).not.toBe(true);
|
|
1823
|
+
expect(tool.annotations?.destructiveHint).toBe(true);
|
|
1824
|
+
});
|
|
1825
|
+
});
|