Skip to content

Commit

Permalink
feat: add rename worksheet capability
Browse files Browse the repository at this point in the history
  • Loading branch information
jroehl committed May 25, 2023
1 parent 8786892 commit 31ddbf7
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 28 deletions.
32 changes: 32 additions & 0 deletions docs/worksheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Manage worksheets
* [`google-sheet worksheet:add`](#google-sheet-worksheetadd)
* [`google-sheet worksheet:get`](#google-sheet-worksheetget)
* [`google-sheet worksheet:remove`](#google-sheet-worksheetremove)
* [`google-sheet worksheet:rename`](#google-sheet-worksheetrename)

## `google-sheet worksheet:add`

Expand Down Expand Up @@ -96,3 +97,34 @@ EXAMPLES
```

_See code: [src/commands/worksheet/remove.ts](https://github.com/jroehl/google-sheet-cli/blob/master/src/commands/worksheet/remove.ts)_

## `google-sheet worksheet:rename`

Add a worksheet with the specified title to the spreadsheet

```
USAGE
$ google-sheet worksheet:rename -t <value> --newWorksheetTitle <value> -s <value> [-h] [-r] [-c <value>] [-p <value>]
FLAGS
-h, --help Show CLI help.
-r, --rawOutput Get the raw output as a JSON string
-s, --spreadsheetId=<value> (required) ID of the spreadsheet to use
-t, --worksheetTitle=<value> (required) Title of the worksheet to use
--newWorksheetTitle=<value> (required) New title of the worksheet to use
AUTHENTICATION FLAGS
-c, --clientEmail=<value> The client email to use for authentication. Uses the GSHEET_CLIENT_EMAIL env variable if
not provided.
-p, --privateKey=<value> The private key to use for authentication. Uses the GSHEET_PRIVATE_KEY env variable if not
provided.
DESCRIPTION
Add a worksheet with the specified title to the spreadsheet
EXAMPLES
$ gsheet worksheet:add --spreadsheetId=<spreadsheetId> --worksheetTitle=<worksheetTitle>
Worksheet "<worksheetTitle>" (<id>) successfully created
```

_See code: [src/commands/worksheet/rename.ts](https://github.com/jroehl/google-sheet-cli/blob/master/src/commands/worksheet/rename.ts)_
34 changes: 34 additions & 0 deletions src/commands/worksheet/rename.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Flags } from '@oclif/core';
import Command, { spreadsheetId, worksheetTitle } from '../../lib/base-class';

export default class Add extends Command {
static description = 'Add a worksheet with the specified title to the spreadsheet';

static examples = [
`$ gsheet worksheet:add --spreadsheetId=<spreadsheetId> --worksheetTitle=<worksheetTitle>
Worksheet "<worksheetTitle>" (<id>) successfully created
`,
];

static flags = {
...Command.flags,
worksheetTitle,
newWorksheetTitle: Flags.string({
description: 'New title of the worksheet to use',
required: true,
}),
spreadsheetId,
};

async run() {
const {
flags: { worksheetTitle = '', spreadsheetId, newWorksheetTitle },
} = await this.parse(Add);

this.start('Renaming worksheet');
await this.gsheet.renameWorksheet(worksheetTitle, newWorksheetTitle, spreadsheetId);
this.stop();
this.logRaw(`Worksheet "${worksheetTitle}" successfully renamed to "${newWorksheetTitle}"`, { operation: this.id });
}
}
30 changes: 30 additions & 0 deletions src/lib/google-sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,36 @@ export default class GoogleSheet {
this.worksheetTitle = '';
}

/**
* Rename a worksheet by title
*
* @param {string} title
* @param {string} newTitle
* @param {string} [spreadsheetId]
* @returns {Promise<void>}
* @memberof GoogleSheet
*/
async renameWorksheet(title: string, newTitle: string, spreadsheetId?: string): Promise<void> {
const worksheet = await this.getWorksheet(title, spreadsheetId);
await this.sheets.spreadsheets.batchUpdate({
spreadsheetId: spreadsheetId || this.spreadsheetId,
requestBody: {
requests: [
{
updateSheetProperties: {
properties: {
sheetId: worksheet.properties?.sheetId || -1,
title: newTitle,
},
fields: 'title',
},
},
],
},
});
this.worksheetTitle = newTitle;
}

/**
* Add a spreadsheet with title
*
Expand Down
6 changes: 3 additions & 3 deletions test/commands/data/append.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ const DATA = [
const DATA_STRING = JSON.stringify(DATA);

describe(baseCommand, () => {
testRun([baseCommand, DATA_STRING], worksheetTitle, (stdout: string) => {
testRun([baseCommand, DATA_STRING], { worksheetTitle }, (stdout: string) => {
expect(stdout).to.contain(`Data successfully appended to "${worksheetTitle}"`);
});
testRun([baseCommand, DATA_STRING, '--rawOutput'], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, DATA_STRING, '--rawOutput'], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:append',
worksheetTitle,
data: DATA,
});
});
testRun(['data:get', '--rawOutput'], worksheetTitle, (parsed: {}) => {
testRun(['data:get', '--rawOutput'], { worksheetTitle }, (parsed: {}) => {
expect((parsed as any).rawData).to.eql([...DATA, ...DATA]);
});
});
14 changes: 7 additions & 7 deletions test/commands/data/get.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { expect } from '@oclif/test';
import { testRun, DATA_GET as worksheetTitle, RAW_DATA } from '../helper';
import { RAW_DATA, testRun, DATA_GET as worksheetTitle } from '../helper';

const baseCommand = 'data:get';

describe(baseCommand, () => {
testRun([baseCommand], worksheetTitle, (stdout: string) => {
testRun([baseCommand], { worksheetTitle }, (stdout: string) => {
expect(stdout).to.contain('(a)');
expect(stdout).to.contain('(b)');
expect(stdout).to.contain('(c)');
Expand All @@ -13,7 +13,7 @@ describe(baseCommand, () => {
expect(stdout).to.contain('C3');
});

testRun([baseCommand, '--rawOutput'], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, '--rawOutput'], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:get',
rawData: RAW_DATA,
Expand Down Expand Up @@ -59,7 +59,7 @@ describe(baseCommand, () => {
});
});

testRun([baseCommand, '--rawOutput', '--hasHeaderRow'], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, '--rawOutput', '--hasHeaderRow'], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:get',
rawData: [
Expand Down Expand Up @@ -107,7 +107,7 @@ describe(baseCommand, () => {
});
});

testRun([baseCommand, '--rawOutput', '--hasHeaderRow', '--minCol=2', '--minRow=2', '--maxCol=2', '--maxRow=2'], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, '--rawOutput', '--hasHeaderRow', '--minCol=2', '--minRow=2', '--maxCol=2', '--maxRow=2'], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:get',
rawData: [['B2']],
Expand All @@ -121,7 +121,7 @@ describe(baseCommand, () => {
});
});

testRun([baseCommand, '--rawOutput', '--hasHeaderRow', `--range='${worksheetTitle}'!C3`], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, '--rawOutput', '--hasHeaderRow', `--range='${worksheetTitle}'!C3`], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:get',
rawData: [['C3']],
Expand All @@ -135,7 +135,7 @@ describe(baseCommand, () => {
});
});

testRun([baseCommand, '--rawOutput', '--hasHeaderRow', `--range='${worksheetTitle}'!A2`], worksheetTitle, (parsed: {}) => {
testRun([baseCommand, '--rawOutput', '--hasHeaderRow', `--range='${worksheetTitle}'!A2`], { worksheetTitle }, (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:get',
rawData: [],
Expand Down
4 changes: 2 additions & 2 deletions test/commands/data/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const DATA = [['1', '2'], ['foo']];
const DATA_STRING = JSON.stringify(DATA);

describe(baseCommand, () => {
testRun([baseCommand, DATA_STRING], worksheetTitle, async (stdout: string) => {
testRun([baseCommand, DATA_STRING], { worksheetTitle }, async (stdout: string) => {
expect(stdout).to.contain(`Data successfully updated in "${worksheetTitle}"`);
});
testRun([baseCommand, DATA_STRING, '--rawOutput'], worksheetTitle, async (parsed: {}) => {
testRun([baseCommand, DATA_STRING, '--rawOutput'], { worksheetTitle }, async (parsed: {}) => {
expect(parsed).to.eql({
operation: 'data:update',
worksheetTitle,
Expand Down
29 changes: 23 additions & 6 deletions test/commands/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export const DATA_GET = getID('data_get_');
export const WORKSHEET_GET = getID('worksheet_get_');
export const WORKSHEET_ADD = getID('worksheet_add_');
export const WORKSHEET_REMOVE = getID('worksheet_remove_');
export const WORKSHEET_RENAME = getID('worksheet_rename_');
export const WORKSHEET_RENAMED = getID('worksheet_rename_');

const authorize = async (): Promise<GoogleSheet> => {
const gsheet = new GoogleSheet();
await gsheet.authorize({ client_email, private_key });
return gsheet;
};

const worksheetsToAdd = [DATA_APPEND, DATA_UPDATE, WORKSHEET_GET, WORKSHEET_REMOVE];
const worksheetsToRemove = [DATA_APPEND, DATA_UPDATE, WORKSHEET_GET, WORKSHEET_ADD, DATA_GET];
const worksheetsToAdd = [DATA_APPEND, DATA_UPDATE, WORKSHEET_GET, WORKSHEET_REMOVE, WORKSHEET_RENAME];
const worksheetsToRemove = [DATA_APPEND, DATA_UPDATE, WORKSHEET_GET, WORKSHEET_ADD, WORKSHEET_RENAMED, DATA_GET];

export const RAW_DATA = [
['A1', 'B1', 'C1'],
Expand Down Expand Up @@ -74,17 +76,32 @@ export const addTestData = async () => {
console.log('');
};

export const getCmd = (parts: string[], worksheetTitle?: string): string[] => {
interface Args {
[key: string]: string | undefined;
spreadsheetId?: string;
worksheetTitle?: string;
}

export const getCmd = (parts: string[], args: Args = {}): string[] => {
const [base, ...flags] = parts;
return [base, `--spreadsheetId=${SPREADSHEET_ID}`, worksheetTitle ? `--worksheetTitle=${worksheetTitle}` : '', ...flags].filter(Boolean);
if (!args.spreadsheetId) {
args.spreadsheetId = SPREADSHEET_ID;
}
return [
base,
...Object.entries(args || {}).reduce<string[]>((acc, [key, value]) => {
return value === undefined ? acc : [...acc, `--${key}=${value}`];
}, []),
...flags,
].filter(Boolean);
};

export const getRun = (parts: string[]): string => {
return `runs "${parts.join(' ')}"`;
};

export const testRun = (cmd: string[], worksheetTitle?: string, cb: Function = () => {}) => {
const parsedCommand = getCmd(cmd, worksheetTitle);
export const testRun = (cmd: string[], args?: Args, cb: Function = () => {}) => {
const parsedCommand = getCmd(cmd, args);
const commandString = `runs "${parsedCommand.join(' ')}"`;
test
.stdout()
Expand Down
6 changes: 3 additions & 3 deletions test/commands/spreadsheet/get.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { expect } from '@oclif/test';
import { testRun, SPREADSHEET_ID } from '../helper';
import { sheets_v4 } from 'googleapis';
import { SPREADSHEET_ID, testRun } from '../helper';

const baseCommand = 'spreadsheet:get';

describe(baseCommand, () => {
testRun([baseCommand], '', (stdout: string) => {
testRun([baseCommand], undefined, (stdout: string) => {
expect(stdout).to.contain(`Fetched spreadsheet "github-actions-test" (${SPREADSHEET_ID})`);
});
testRun([baseCommand, '--rawOutput'], '', (parsed: sheets_v4.Schema$Spreadsheet) => {
testRun([baseCommand, '--rawOutput'], undefined, (parsed: sheets_v4.Schema$Spreadsheet) => {
expect(parsed.spreadsheetId).to.equal(SPREADSHEET_ID);
expect(parsed.spreadsheetUrl).to.equal(`https://docs.google.com/spreadsheets/d/${SPREADSHEET_ID}/edit`);
expect(parsed).to.haveOwnProperty('properties');
Expand Down
4 changes: 2 additions & 2 deletions test/commands/worksheet/add.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expect } from '@oclif/test';
import { testRun, WORKSHEET_ADD as worksheetTitle } from '../helper';
import { sheets_v4 } from 'googleapis';
import { testRun, WORKSHEET_ADD as worksheetTitle } from '../helper';

const baseCommand = 'worksheet:add';

describe(baseCommand, () => {
testRun([baseCommand, '--rawOutput'], worksheetTitle, (parsed: sheets_v4.Schema$Sheet) => {
testRun([baseCommand, '--rawOutput'], { worksheetTitle }, (parsed: sheets_v4.Schema$Sheet) => {
if (!parsed.properties) throw parsed;
expect(parsed.properties.title).to.equal(worksheetTitle);
expect(parsed.properties).to.haveOwnProperty('sheetId');
Expand Down
6 changes: 3 additions & 3 deletions test/commands/worksheet/get.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { expect } from '@oclif/test';
import { testRun, WORKSHEET_GET as worksheetTitle } from '../helper';
import { sheets_v4 } from 'googleapis';
import { testRun, WORKSHEET_GET as worksheetTitle } from '../helper';

const baseCommand = 'worksheet:get';

describe(baseCommand, () => {
testRun([baseCommand], worksheetTitle, (stdout: string) => {
testRun([baseCommand], { worksheetTitle }, (stdout: string) => {
expect(stdout).to.contain(`Fetched "${worksheetTitle}" (`);
});
testRun([baseCommand, '--rawOutput'], worksheetTitle, (parsed: sheets_v4.Schema$Sheet) => {
testRun([baseCommand, '--rawOutput'], { worksheetTitle }, (parsed: sheets_v4.Schema$Sheet) => {
if (!parsed.properties) throw parsed;
expect(parsed.properties.sheetId).to.not.be.undefined;
expect(parsed.properties.title).to.equal(worksheetTitle);
Expand Down
4 changes: 2 additions & 2 deletions test/commands/worksheet/remove.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expect } from '@oclif/test';
import { testRun, WORKSHEET_REMOVE as worksheetTitle } from '../helper';
import { sheets_v4 } from 'googleapis';
import { testRun, WORKSHEET_REMOVE as worksheetTitle } from '../helper';

const baseCommand = 'worksheet:remove';

describe(baseCommand, () => {
testRun([baseCommand], worksheetTitle, (stdout: sheets_v4.Schema$Sheet) => {
testRun([baseCommand], { worksheetTitle }, (stdout: sheets_v4.Schema$Sheet) => {
expect(stdout).to.contain(`Worksheet "${worksheetTitle}" successfully removed`);
});
});
11 changes: 11 additions & 0 deletions test/commands/worksheet/rename.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { expect } from '@oclif/test';
import { sheets_v4 } from 'googleapis';
import { WORKSHEET_RENAMED as newWorksheetTitle, testRun, WORKSHEET_RENAME as worksheetTitle } from '../helper';

const baseCommand = 'worksheet:rename';

describe(baseCommand, () => {
testRun([baseCommand], { worksheetTitle, newWorksheetTitle }, (stdout: sheets_v4.Schema$Sheet) => {
expect(stdout).to.contain(`Worksheet "${worksheetTitle}" successfully renamed to "${newWorksheetTitle}"`);
});
});

0 comments on commit 31ddbf7

Please sign in to comment.