Skip to content

Commit

Permalink
Tests for google-sheets.ts (#49)
Browse files Browse the repository at this point in the history
Added tests to the functions that are used by summarize handler for now (`getAuthClient`, `getTotalRows`, `getLastNComments`). Updated getTotalRows functionality to handle when the spreadsheet has
less comments than requested amount
  • Loading branch information
jasnoo authored Mar 12, 2024
1 parent 9f18cd1 commit 7134de1
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 5 deletions.
3 changes: 2 additions & 1 deletion jest-setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
process.env['AZURE_OPENAI_ENDPOINT'] = 'test_endpoint';
process.env['AZURE_OPENAI_KEY'] = 'test_api_key';
process.env['CLIENT_EMAIL'] = '[email protected]';
process.env['GOOGLE_PRIVATE_KEY'] = 'test_private_key';
process.env['GOOGLE_PRIVATE_KEY'] = 'test-key\\n';
process.env['SHEET_ID'] = 'test_sheet_id';
124 changes: 124 additions & 0 deletions src/libs/google-sheets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { google } from 'googleapis';
import { getAuthClient, getLastNComments } from './google-sheets';

const MOCK_AUTHORIZE = jest.fn().mockResolvedValue(undefined);
const MOCK_SHEETS = {
spreadsheets: {
values: {
get: jest.fn(),
append: jest.fn(),
update: jest.fn()
}
}
};

jest.mock('googleapis', () => {
const originalModule = jest.requireActual('googleapis');
return {
...originalModule,
google: {
...originalModule.google,
auth: {
JWT: jest.fn().mockImplementation(() => ({ authorize: MOCK_AUTHORIZE }))
},
sheets: jest.fn().mockImplementation(() => MOCK_SHEETS)
}
};
});

describe('google-sheets', () => {
afterEach(() => {
jest.clearAllMocks();
});

describe('getAuthClient', () => {
it('should successfully create and authorize a Google Sheets API client', async () => {
const client = await getAuthClient();
expect(google.auth.JWT).toHaveBeenCalledWith(
process.env.CLIENT_EMAIL,
null,
'test-key\n',
['https://www.googleapis.com/auth/spreadsheets']
);
expect(MOCK_AUTHORIZE).toHaveBeenCalled();
expect(google.sheets).toHaveBeenCalledWith({
version: 'v4',
auth: { authorize: MOCK_AUTHORIZE }
});
expect(client).toEqual(MOCK_SHEETS);
});

it('should throw an error if authorization fails', async () => {
MOCK_AUTHORIZE.mockRejectedValueOnce(new Error('Failed to authorize'));
await expect(getAuthClient()).rejects.toThrow(
'Google Sheets API failed to authorize: Failed to authorize'
);
});
});

describe('getLastNComments', () => {
const testCases = [
{
totalRows: 3,
n: 2,
expectedRange: 'Sheet1!A2:D3',
expectedComments: [['Comment 1'], ['Comment 2']],
description:
'should retrieve comments from expected range when n is less or equal than available comments'
},
{
totalRows: 3,
n: 1000,
expectedRange: 'Sheet1!A2:D3',
expectedComments: [['Comment 1'], ['Comment 2']],
description:
'should retrieve comments from expected range when n is greater than available comments (returns all rows excluding header row)'
}
];

it.each(testCases)(
'$description',
async ({ n, expectedRange, expectedComments, totalRows }) => {
MOCK_SHEETS.spreadsheets.values.get
.mockResolvedValueOnce({ data: { values: [[`${totalRows}`]] } }) // called in getTotalRows
.mockResolvedValueOnce({ data: { values: expectedComments } }); // called in getLastNComments
const sheetsClient = google.sheets('v4');
const comments = await getLastNComments(sheetsClient, n);
expect(MOCK_SHEETS.spreadsheets.values.get.mock.calls[0][0]).toEqual({
spreadsheetId: process.env.SHEET_ID,
range: 'Metadata!A2'
});
expect(MOCK_SHEETS.spreadsheets.values.get.mock.calls[1][0]).toEqual({
spreadsheetId: process.env.SHEET_ID,
range: expectedRange
});
expect(comments).toEqual(expectedComments);
}
);

it('should throw an error when failing to get row count from getTotalRows', async () => {
// first call within getTotalRows fails
MOCK_SHEETS.spreadsheets.values.get.mockRejectedValueOnce(
new Error('Failed to get row count')
);
const sheetsClient = google.sheets('v4');
await expect(getLastNComments(sheetsClient, 2)).rejects.toThrow(
'Google Sheets API failed to get data size: Failed to get row count'
);
});

it('should throw an error when failing to get comments', async () => {
// first call within getTotalRows is successful
MOCK_SHEETS.spreadsheets.values.get.mockResolvedValueOnce({
data: { values: [['2']] }
});
MOCK_SHEETS.spreadsheets.values.get.mockRejectedValueOnce(
new Error('Failed to fetch comments')
);
const sheetsClient = google.sheets('v4');
await expect(getLastNComments(sheetsClient, 2)).rejects.toThrow(
'Google Sheets API failed to get input data: Failed to fetch comments'
);
});
});
});
9 changes: 5 additions & 4 deletions src/libs/google-sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export async function getAuthClient() {
}
}

// only used within getLastNComments function
async function getTotalRows(sheetsClient: sheets_v4.Sheets) {
try {
const result = await sheetsClient.spreadsheets.values.get({
Expand All @@ -52,12 +53,12 @@ export async function getLastNComments(
): Promise<string[][]> {
try {
const totalRows = await getTotalRows(sheetsClient);

const startRow = totalRows - 1 < n ? 2 : totalRows - (n - 1);
const result = await sheetsClient.spreadsheets.values.get({
spreadsheetId: process.env.SHEET_ID,
range: `${SHEET_NAME}!${SHEETS_COLUMN_MAP[Feedback.Timestamp]}${
totalRows - (n - 1)
}:${SHEETS_COLUMN_MAP[Feedback.Comment]}${totalRows}`
range: `${SHEET_NAME}!${
SHEETS_COLUMN_MAP[Feedback.Timestamp]
}${startRow}:${SHEETS_COLUMN_MAP[Feedback.Comment]}${totalRows}`
});
return result.data.values ?? [];
} catch (e) {
Expand Down

0 comments on commit 7134de1

Please sign in to comment.