gogcli-mcp-sheets 2.6.1 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
10
- "version": "2.6.1"
10
+ "version": "2.7.1"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "gogcli (Sheets)",
16
16
  "source": "./",
17
17
  "description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
18
- "version": "2.6.1",
18
+ "version": "2.7.1",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gogcli-mcp-sheets",
3
3
  "displayName": "gogcli (Sheets)",
4
- "version": "2.6.1",
4
+ "version": "2.7.1",
5
5
  "description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chris Hall
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -31399,7 +31399,7 @@ function registerSheetsTools(server2) {
31399
31399
  }
31400
31400
 
31401
31401
  // ../gogcli-mcp/src/server.ts
31402
- var VERSION = true ? "2.6.1" : "0.0.0";
31402
+ var VERSION = true ? "2.7.1" : "0.0.0";
31403
31403
  function createServer(options) {
31404
31404
  return new McpServer({
31405
31405
  name: options?.name ?? "gogcli",
@@ -31815,6 +31815,71 @@ ${result.content[0].text}` }] };
31815
31815
  if (cellsJson) args.push(`--cells-json=${cellsJson}`);
31816
31816
  return runOrDiagnose(args, { account });
31817
31817
  });
31818
+ server2.registerTool("gog_sheets_validation_get", {
31819
+ description: "Read the data-validation rules (dropdowns, checkboxes, number/date conditions, custom formulas) applied to a range.",
31820
+ annotations: { readOnlyHint: true },
31821
+ inputSchema: {
31822
+ spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
31823
+ range: external_exports.string().describe("Range to inspect (e.g. Sheet1!A1:A10)"),
31824
+ account: accountParam
31825
+ }
31826
+ }, async ({ spreadsheetId, range, account }) => {
31827
+ return runOrDiagnose(["sheets", "validation", "get", spreadsheetId, range], { account });
31828
+ });
31829
+ server2.registerTool("gog_sheets_validation_set", {
31830
+ description: "Set a data-validation rule on a range \u2014 dropdowns (ONE_OF_LIST / ONE_OF_RANGE), checkboxes (BOOLEAN), number/date conditions, or custom formulas. Overwrites any existing rule on the range. Repeat values for list entries or between-bounds.",
31831
+ annotations: { destructiveHint: true },
31832
+ inputSchema: {
31833
+ spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
31834
+ range: external_exports.string().describe("Range to apply the rule to (e.g. Sheet1!A1:A10)"),
31835
+ type: external_exports.string().describe("Condition type, e.g. ONE_OF_LIST, ONE_OF_RANGE, NUMBER_BETWEEN, NUMBER_GREATER, DATE_AFTER, BOOLEAN, CUSTOM_FORMULA"),
31836
+ values: external_exports.array(external_exports.string()).optional().describe("Condition values (repeatable): list entries for ONE_OF_LIST, two bounds for *_BETWEEN, a range for ONE_OF_RANGE, a formula for CUSTOM_FORMULA"),
31837
+ strict: external_exports.boolean().optional().describe("Reject invalid input instead of showing a warning"),
31838
+ inputMessage: external_exports.string().optional().describe("Message shown when the cell is selected"),
31839
+ showCustomUi: external_exports.boolean().optional().describe("Show dropdown or checkbox UI where supported"),
31840
+ filteredRowsIncluded: external_exports.boolean().optional().describe("Apply the rule to filtered rows too; required for table-managed dropdown columns"),
31841
+ account: accountParam
31842
+ }
31843
+ }, async ({ spreadsheetId, range, type, values, strict, inputMessage, showCustomUi, filteredRowsIncluded, account }) => {
31844
+ const args = ["sheets", "validation", "set", spreadsheetId, range, `--type=${type}`];
31845
+ if (values) for (const v of values) args.push(`--value=${v}`);
31846
+ if (strict) args.push("--strict");
31847
+ if (inputMessage) args.push(`--input-message=${inputMessage}`);
31848
+ if (showCustomUi) args.push("--show-custom-ui");
31849
+ if (filteredRowsIncluded) args.push("--filtered-rows-included");
31850
+ return runOrDiagnose(args, { account });
31851
+ });
31852
+ server2.registerTool("gog_sheets_validation_clear", {
31853
+ description: "Remove all data-validation rules from a range.",
31854
+ annotations: { destructiveHint: true },
31855
+ inputSchema: {
31856
+ spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
31857
+ range: external_exports.string().describe("Range to clear (e.g. Sheet1!A1:A10)"),
31858
+ filteredRowsIncluded: external_exports.boolean().optional().describe("Clear rules from filtered rows too; required for table-managed dropdown columns"),
31859
+ account: accountParam
31860
+ }
31861
+ }, async ({ spreadsheetId, range, filteredRowsIncluded, account }) => {
31862
+ const args = ["sheets", "validation", "clear", spreadsheetId, range];
31863
+ if (filteredRowsIncluded) args.push("--filtered-rows-included");
31864
+ return runOrDiagnose(args, { account });
31865
+ });
31866
+ server2.registerTool("gog_sheets_delete_dimension", {
31867
+ description: "Delete a span of rows or columns, table-aware: intersecting table objects are preserved (shrunk) along with their remaining data, instead of being corrupted as with a raw DeleteDimension batch update. Target by A1 range (e.g. Sheet1!5:7 or Sheet1!C:D) or by sheet name plus start/end.",
31868
+ annotations: { destructiveHint: true },
31869
+ inputSchema: {
31870
+ spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
31871
+ rangeOrSheet: external_exports.string().describe("A1 range covering the rows/columns to delete, or a sheet name (then start/end are required)"),
31872
+ dimension: external_exports.enum(["ROWS", "COLUMNS"]).describe("Dimension to delete"),
31873
+ start: external_exports.number().int().optional().describe("First row/column to delete (1-based, inclusive; required with a sheet-name target)"),
31874
+ end: external_exports.number().int().optional().describe("Last row/column to delete (1-based, inclusive; required with a sheet-name target)"),
31875
+ account: accountParam
31876
+ }
31877
+ }, async ({ spreadsheetId, rangeOrSheet, dimension, start, end, account }) => {
31878
+ const args = ["sheets", "delete-dimension", spreadsheetId, rangeOrSheet, `--dimension=${dimension}`];
31879
+ if (start !== void 0) args.push(`--start=${start}`);
31880
+ if (end !== void 0) args.push(`--end=${end}`);
31881
+ return runOrDiagnose(args, { account });
31882
+ });
31818
31883
  server2.registerTool("gog_sheets_named_ranges_list", {
31819
31884
  description: "List all named ranges in a spreadsheet.",
31820
31885
  annotations: { readOnlyHint: true },
@@ -32037,7 +32102,7 @@ ${result.content[0].text}` }] };
32037
32102
  return runOrDiagnose(["sheets", "table", "clear", spreadsheetId, tableId], { account });
32038
32103
  });
32039
32104
  server2.registerTool("gog_sheets_table_delete", {
32040
- description: "Delete a Google Sheets table. WARNING: the underlying `gog`/Sheets behaviour is that deleting a table also DESTROYS every cell value in the table range \u2014 not just the table styling/columns. By default this tool prevents that data loss by emulating the Sheets UI's \"Convert to range\": it reads the table's cells (values AND formulas) first, deletes the table, then restores the data into the now-plain range. Formatting, banding, and data-validation dropdowns are still lost (gog cannot round-trip those yet). Set keep_data=false to delete the table AND wipe its cell data (the raw destructive behaviour). To preserve everything, snapshot the whole spreadsheet first with gog_sheets_snapshot.",
32105
+ description: "Delete a Google Sheets table. WARNING: the underlying `gog`/Sheets behaviour is that deleting a table also DESTROYS every cell value in the table range \u2014 not just the table styling/columns. By default this tool prevents that data loss by emulating the Sheets UI's \"Convert to range\": it reads the table's cells (values AND formulas) first, deletes the table, then restores the data into the now-plain range. Formatting and banding are still lost; data-validation dropdowns are also not restored automatically, but you can snapshot them first with gog_sheets_validation_get and re-apply with gog_sheets_validation_set. Set keep_data=false to delete the table AND wipe its cell data (the raw destructive behaviour). To preserve everything, snapshot the whole spreadsheet first with gog_sheets_snapshot.",
32041
32106
  annotations: { destructiveHint: true },
32042
32107
  inputSchema: {
32043
32108
  spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
package/manifest.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifest_version": "0.3",
4
4
  "name": "gogcli-mcp-sheets",
5
5
  "display_name": "gogcli (Sheets)",
6
- "version": "2.6.1",
6
+ "version": "2.7.1",
7
7
  "description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
8
8
  "author": {
9
9
  "name": "Chris Hall",
@@ -184,6 +184,22 @@
184
184
  "name": "gog_sheets_links_set",
185
185
  "description": "Set native cell hyperlinks: single link, multi-link rich-text cell (runsJson), or batch (cellsJson)."
186
186
  },
187
+ {
188
+ "name": "gog_sheets_validation_get",
189
+ "description": "Read data-validation rules (dropdowns, checkboxes, conditions) on a range."
190
+ },
191
+ {
192
+ "name": "gog_sheets_validation_set",
193
+ "description": "Set a data-validation rule on a range: dropdowns, checkboxes, number/date conditions, or custom formulas."
194
+ },
195
+ {
196
+ "name": "gog_sheets_validation_clear",
197
+ "description": "Remove all data-validation rules from a range."
198
+ },
199
+ {
200
+ "name": "gog_sheets_delete_dimension",
201
+ "description": "Delete a row or column span, table-aware: intersecting tables are shrunk and their remaining data preserved."
202
+ },
187
203
  {
188
204
  "name": "gog_sheets_named_ranges_list",
189
205
  "description": "List all named ranges in a spreadsheet."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gogcli-mcp-sheets",
3
- "version": "2.6.1",
3
+ "version": "2.7.1",
4
4
  "mcpName": "io.github.chrischall/gogcli-mcp-sheets",
5
5
  "description": "Extended Google Sheets MCP server via gogcli — all base tools plus full Sheets support",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "source": "github",
8
8
  "subfolder": "packages/gogcli-mcp-sheets"
9
9
  },
10
- "version": "2.6.1",
10
+ "version": "2.7.1",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "gogcli-mcp-sheets",
15
- "version": "2.6.1",
15
+ "version": "2.7.1",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
@@ -466,6 +466,75 @@ export function registerExtraSheetsTools(server: McpServer): void {
466
466
  return runOrDiagnose(args, { account });
467
467
  });
468
468
 
469
+ server.registerTool('gog_sheets_validation_get', {
470
+ description: 'Read the data-validation rules (dropdowns, checkboxes, number/date conditions, custom formulas) applied to a range.',
471
+ annotations: { readOnlyHint: true },
472
+ inputSchema: {
473
+ spreadsheetId: z.string().describe('Spreadsheet ID'),
474
+ range: z.string().describe('Range to inspect (e.g. Sheet1!A1:A10)'),
475
+ account: accountParam,
476
+ },
477
+ }, async ({ spreadsheetId, range, account }) => {
478
+ return runOrDiagnose(['sheets', 'validation', 'get', spreadsheetId, range], { account });
479
+ });
480
+
481
+ server.registerTool('gog_sheets_validation_set', {
482
+ description: 'Set a data-validation rule on a range — dropdowns (ONE_OF_LIST / ONE_OF_RANGE), checkboxes (BOOLEAN), number/date conditions, or custom formulas. Overwrites any existing rule on the range. Repeat values for list entries or between-bounds.',
483
+ annotations: { destructiveHint: true },
484
+ inputSchema: {
485
+ spreadsheetId: z.string().describe('Spreadsheet ID'),
486
+ range: z.string().describe('Range to apply the rule to (e.g. Sheet1!A1:A10)'),
487
+ type: z.string().describe('Condition type, e.g. ONE_OF_LIST, ONE_OF_RANGE, NUMBER_BETWEEN, NUMBER_GREATER, DATE_AFTER, BOOLEAN, CUSTOM_FORMULA'),
488
+ values: z.array(z.string()).optional().describe('Condition values (repeatable): list entries for ONE_OF_LIST, two bounds for *_BETWEEN, a range for ONE_OF_RANGE, a formula for CUSTOM_FORMULA'),
489
+ strict: z.boolean().optional().describe('Reject invalid input instead of showing a warning'),
490
+ inputMessage: z.string().optional().describe('Message shown when the cell is selected'),
491
+ showCustomUi: z.boolean().optional().describe('Show dropdown or checkbox UI where supported'),
492
+ filteredRowsIncluded: z.boolean().optional().describe('Apply the rule to filtered rows too; required for table-managed dropdown columns'),
493
+ account: accountParam,
494
+ },
495
+ }, async ({ spreadsheetId, range, type, values, strict, inputMessage, showCustomUi, filteredRowsIncluded, account }) => {
496
+ const args = ['sheets', 'validation', 'set', spreadsheetId, range, `--type=${type}`];
497
+ if (values) for (const v of values) args.push(`--value=${v}`);
498
+ if (strict) args.push('--strict');
499
+ if (inputMessage) args.push(`--input-message=${inputMessage}`);
500
+ if (showCustomUi) args.push('--show-custom-ui');
501
+ if (filteredRowsIncluded) args.push('--filtered-rows-included');
502
+ return runOrDiagnose(args, { account });
503
+ });
504
+
505
+ server.registerTool('gog_sheets_validation_clear', {
506
+ description: 'Remove all data-validation rules from a range.',
507
+ annotations: { destructiveHint: true },
508
+ inputSchema: {
509
+ spreadsheetId: z.string().describe('Spreadsheet ID'),
510
+ range: z.string().describe('Range to clear (e.g. Sheet1!A1:A10)'),
511
+ filteredRowsIncluded: z.boolean().optional().describe('Clear rules from filtered rows too; required for table-managed dropdown columns'),
512
+ account: accountParam,
513
+ },
514
+ }, async ({ spreadsheetId, range, filteredRowsIncluded, account }) => {
515
+ const args = ['sheets', 'validation', 'clear', spreadsheetId, range];
516
+ if (filteredRowsIncluded) args.push('--filtered-rows-included');
517
+ return runOrDiagnose(args, { account });
518
+ });
519
+
520
+ server.registerTool('gog_sheets_delete_dimension', {
521
+ description: 'Delete a span of rows or columns, table-aware: intersecting table objects are preserved (shrunk) along with their remaining data, instead of being corrupted as with a raw DeleteDimension batch update. Target by A1 range (e.g. Sheet1!5:7 or Sheet1!C:D) or by sheet name plus start/end.',
522
+ annotations: { destructiveHint: true },
523
+ inputSchema: {
524
+ spreadsheetId: z.string().describe('Spreadsheet ID'),
525
+ rangeOrSheet: z.string().describe('A1 range covering the rows/columns to delete, or a sheet name (then start/end are required)'),
526
+ dimension: z.enum(['ROWS', 'COLUMNS']).describe('Dimension to delete'),
527
+ start: z.number().int().optional().describe('First row/column to delete (1-based, inclusive; required with a sheet-name target)'),
528
+ end: z.number().int().optional().describe('Last row/column to delete (1-based, inclusive; required with a sheet-name target)'),
529
+ account: accountParam,
530
+ },
531
+ }, async ({ spreadsheetId, rangeOrSheet, dimension, start, end, account }) => {
532
+ const args = ['sheets', 'delete-dimension', spreadsheetId, rangeOrSheet, `--dimension=${dimension}`];
533
+ if (start !== undefined) args.push(`--start=${start}`);
534
+ if (end !== undefined) args.push(`--end=${end}`);
535
+ return runOrDiagnose(args, { account });
536
+ });
537
+
469
538
  server.registerTool('gog_sheets_named_ranges_list', {
470
539
  description: 'List all named ranges in a spreadsheet.',
471
540
  annotations: { readOnlyHint: true },
@@ -712,7 +781,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
712
781
  description:
713
782
  'Delete a Google Sheets table. WARNING: the underlying `gog`/Sheets behaviour is that deleting a table also DESTROYS every cell value in the table range — not just the table styling/columns. ' +
714
783
  'By default this tool prevents that data loss by emulating the Sheets UI\'s "Convert to range": it reads the table\'s cells (values AND formulas) first, deletes the table, then restores the data into the now-plain range. ' +
715
- 'Formatting, banding, and data-validation dropdowns are still lost (gog cannot round-trip those yet). ' +
784
+ 'Formatting and banding are still lost; data-validation dropdowns are also not restored automatically, but you can snapshot them first with gog_sheets_validation_get and re-apply with gog_sheets_validation_set. ' +
716
785
  'Set keep_data=false to delete the table AND wipe its cell data (the raw destructive behaviour). To preserve everything, snapshot the whole spreadsheet first with gog_sheets_snapshot.',
717
786
  annotations: { destructiveHint: true },
718
787
  inputSchema: {
@@ -1284,3 +1284,82 @@ describe('gog_sheets_snapshot', () => {
1284
1284
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', 'sid', 'Backup A', '--parent=folder1'], { account: 'a@b.com' });
1285
1285
  });
1286
1286
  });
1287
+
1288
+ // gog 0.24.0
1289
+ describe('gog_sheets_validation_get', () => {
1290
+ it('reads validation rules for a range', async () => {
1291
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1292
+ const handlers = setupHandlers();
1293
+ await handlers.get('gog_sheets_validation_get')!({ spreadsheetId: 'sid', range: 'Sheet1!A1:A10' });
1294
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1295
+ ['sheets', 'validation', 'get', 'sid', 'Sheet1!A1:A10'],
1296
+ { account: undefined },
1297
+ );
1298
+ });
1299
+ });
1300
+
1301
+ describe('gog_sheets_validation_set', () => {
1302
+ it('sets a dropdown rule with repeated values', async () => {
1303
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1304
+ const handlers = setupHandlers();
1305
+ await handlers.get('gog_sheets_validation_set')!({
1306
+ spreadsheetId: 'sid', range: 'A1:A10', type: 'ONE_OF_LIST', values: ['Red', 'Green'],
1307
+ });
1308
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1309
+ ['sheets', 'validation', 'set', 'sid', 'A1:A10', '--type=ONE_OF_LIST', '--value=Red', '--value=Green'],
1310
+ { account: undefined },
1311
+ );
1312
+ });
1313
+
1314
+ it('passes strict, input message, custom UI and filtered-rows flags', async () => {
1315
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1316
+ const handlers = setupHandlers();
1317
+ await handlers.get('gog_sheets_validation_set')!({
1318
+ spreadsheetId: 'sid', range: 'A1', type: 'NUMBER_BETWEEN', values: ['1', '10'],
1319
+ strict: true, inputMessage: 'Pick 1-10', showCustomUi: true, filteredRowsIncluded: true,
1320
+ });
1321
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1322
+ ['sheets', 'validation', 'set', 'sid', 'A1', '--type=NUMBER_BETWEEN', '--value=1', '--value=10',
1323
+ '--strict', '--input-message=Pick 1-10', '--show-custom-ui', '--filtered-rows-included'],
1324
+ { account: undefined },
1325
+ );
1326
+ });
1327
+ });
1328
+
1329
+ describe('gog_sheets_validation_clear', () => {
1330
+ it('clears rules from a range', async () => {
1331
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1332
+ const handlers = setupHandlers();
1333
+ await handlers.get('gog_sheets_validation_clear')!({ spreadsheetId: 'sid', range: 'A1:A10', filteredRowsIncluded: true });
1334
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1335
+ ['sheets', 'validation', 'clear', 'sid', 'A1:A10', '--filtered-rows-included'],
1336
+ { account: undefined },
1337
+ );
1338
+ });
1339
+ });
1340
+
1341
+ describe('gog_sheets_delete_dimension', () => {
1342
+ it('deletes a row span from a sheet target', async () => {
1343
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1344
+ const handlers = setupHandlers();
1345
+ await handlers.get('gog_sheets_delete_dimension')!({
1346
+ spreadsheetId: 'sid', rangeOrSheet: 'Sheet1', dimension: 'ROWS', start: 5, end: 7,
1347
+ });
1348
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1349
+ ['sheets', 'delete-dimension', 'sid', 'Sheet1', '--dimension=ROWS', '--start=5', '--end=7'],
1350
+ { account: undefined },
1351
+ );
1352
+ });
1353
+
1354
+ it('deletes columns by A1 range without start/end', async () => {
1355
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
1356
+ const handlers = setupHandlers();
1357
+ await handlers.get('gog_sheets_delete_dimension')!({
1358
+ spreadsheetId: 'sid', rangeOrSheet: 'Sheet1!C:D', dimension: 'COLUMNS', account: 'a@b.com',
1359
+ });
1360
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
1361
+ ['sheets', 'delete-dimension', 'sid', 'Sheet1!C:D', '--dimension=COLUMNS'],
1362
+ { account: 'a@b.com' },
1363
+ );
1364
+ });
1365
+ });