Skip to content

Commit

Permalink
chore(PPDSC-2643): add missing unit tests for getSheets
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnTParsons authored and JohnTParsons committed Jan 4, 2023
1 parent d928f01 commit 443da6c
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 9 deletions.
76 changes: 76 additions & 0 deletions site/utils/google-sheet/__tests__/get-sheets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {google} from 'googleapis';
import {getSheets} from '../get-sheets';

const homePageContent = [
['hero_card_link_text', 'Read on Medium'],
['hero_card_link', 'https://medium.com/test'],
];

// The google.sheets() constructor returns a sheets function instance
const mockGoogleSheets = (values: string[][]) => () => ({
spreadsheets: {
values: {
get: jest.fn(() => ({
data: {
values: Promise.resolve(values),
},
})),
},
},
});

describe('getSheets', () => {
const {env} = process;
let googleSheetsSpy: jest.SpyInstance;
let consoleErrorSpy: jest.SpyInstance;

beforeEach(() => {
jest.resetModules();
process.env = {...env};
googleSheetsSpy = jest
// @ts-ignore
.spyOn(google, 'sheets');
consoleErrorSpy = jest
.spyOn(console, 'error')
.mockImplementation(jest.fn());
});

afterEach(() => {
process.env = env;
jest.restoreAllMocks();
});

it('should returned populated array on success', async () => {
process.env.GOOGLE_SHEETS_CLIENT_EMAIL = 'test';
process.env.GOOGLE_SHEETS_PRIVATE_KEY = 'test';
process.env.SPREADSHEET_ID = 'test';
googleSheetsSpy.mockImplementation(mockGoogleSheets(homePageContent));
const result = await getSheets('Homepage');
expect(googleSheetsSpy).toBeCalled();
expect(consoleErrorSpy).not.toBeCalled();
expect(result).toEqual(homePageContent);
});

it('should return empty array when unset env vars', async () => {
process.env.GOOGLE_SHEETS_CLIENT_EMAIL = undefined;
process.env.GOOGLE_SHEETS_PRIVATE_KEY = undefined;
process.env.SPREADSHEET_ID = undefined;
const result = await getSheets('Homepage');
expect(googleSheetsSpy).not.toBeCalled();
expect(consoleErrorSpy).toBeCalled();
expect(result).toEqual([]);
});

it('should return empty array on google failure', async () => {
process.env.GOOGLE_SHEETS_CLIENT_EMAIL = 'test';
process.env.GOOGLE_SHEETS_PRIVATE_KEY = 'test';
process.env.SPREADSHEET_ID = 'test';
googleSheetsSpy.mockImplementation(() => () =>
Promise.reject(new Error('Google error')),
);
const result = await getSheets('Homepage');
expect(googleSheetsSpy).toBeCalled();
expect(consoleErrorSpy).toBeCalled();
expect(result).toEqual([]);
});
});
32 changes: 25 additions & 7 deletions site/utils/google-sheet/get-sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,47 @@ require('dotenv').config();
// Define the required scopes. In our case we only need read access.
const SCOPE = ['https://www.googleapis.com/auth/spreadsheets.readonly'];

const handleError = (err: unknown) => {
console.error('>> ERROR: Cannot fetch data from googlesheet API.', err);
};

// Range is typically the sheet name
export async function getSheets(range: string) {
const {
GOOGLE_SHEETS_CLIENT_EMAIL,
GOOGLE_SHEETS_PRIVATE_KEY,
SPREADSHEET_ID,
} = process.env;
if (
!GOOGLE_SHEETS_CLIENT_EMAIL &&
!GOOGLE_SHEETS_PRIVATE_KEY &&
!SPREADSHEET_ID
) {
// Fail fast without a stacktrace
handleError('Have you added the .env file for local builds?');
return [];
}

try {
// generate a JWT
const jwt = new google.auth.JWT(
process.env.GOOGLE_SHEETS_CLIENT_EMAIL,
GOOGLE_SHEETS_CLIENT_EMAIL,
undefined,
// we need to replace the escaped newline characters
// https://stackoverflow.com/questions/50299329/node-js-firebase-service-account-private-key-wont-parse
process.env.GOOGLE_SHEETS_PRIVATE_KEY!.replace(/\\n/g, '\n'),
GOOGLE_SHEETS_PRIVATE_KEY!.replace(/\\n/g, '\n'),
SCOPE,
);

// initialize the Google Sheets API
const sheets = google.sheets({version: 'v4', auth: jwt});
const response = await sheets.spreadsheets.values.get({
spreadsheetId: process.env.SPREADSHEET_ID,
spreadsheetId: SPREADSHEET_ID,
range,
});
return response.data.values;
} catch (err) {
console.error('>> ERROR: Cannot fetch data from googlesheet api');
console.log('Have you added the .env file for local builds?');
console.error(err);
} catch (err: unknown) {
handleError(err);
}

return [];
Expand Down
8 changes: 8 additions & 0 deletions src/link/__tests__/utils.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ describe('isLinkExternal', () => {
windowSpy = jest.spyOn(global as any, 'window', 'get');
windowSpy.mockImplementation(() => ({location: {host: 'newskit.co.uk'}}));
});

afterEach(() => {
windowSpy.mockRestore();
});

it('should return false if the link is falsy', () => {
expect(isLinkExternal('')).toEqual(false);
});

it('should return false if the window is undefined', () => {
windowSpy.mockImplementation(() => undefined);
expect(isLinkExternal('http://www.google.com')).toEqual(false);
});

it('should return false if the window object is defined and the link is internal', () => {
expect(isLinkExternal('www.google.it')).toEqual(false);
expect(isLinkExternal('newskit.co.uk')).toEqual(false);
Expand All @@ -25,6 +32,7 @@ describe('isLinkExternal', () => {
expect(isLinkExternal('tel:+1-555-555-5555')).toEqual(false);
expect(isLinkExternal('#link')).toEqual(false);
});

it('should return true if the window is defined and the hosts of the current website and the target href do not match', () => {
expect(isLinkExternal('http://www.google.com')).toEqual(true);
expect(isLinkExternal('https://www.google.com')).toEqual(true);
Expand Down
3 changes: 2 additions & 1 deletion src/link/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import stylePresets from './style-presets';
import {withOwnTheme} from '../utils/with-own-theme';

export const isLinkExternal = (href: string) => {
const hostName = href.match(/^https?:\/\/(?:www\.)?([^/?#]+)(?:[/?#]|$)/i);
const hostName =
href && href.match(/^https?:\/\/(?:www\.)?([^/?#]+)(?:[/?#]|$)/i);

if (hostName && typeof window !== 'undefined') {
const hostLocation = window.location.host;
Expand Down
14 changes: 13 additions & 1 deletion src/test/__tests__/test-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React from 'react';
import {fireEvent} from '@testing-library/react';
import {renderWithImplementation} from '../test-utils';
import {renderWithImplementation, renderWithThemeInBody} from '../test-utils';
import {Link} from '../../link';
import {LinkProps} from '../../link/types';

const ThemedLink: React.FC = () =>
React.createElement('span', {id: 'a11y-status-message'}, 'test link text');

describe('Test utils', () => {
test('renderWithImplementation works correctly if fireEvent not provided as param', async () => {
const onClickHandler = jest.fn();
Expand All @@ -17,4 +21,12 @@ describe('Test utils', () => {
fireEvent.click(link);
expect(onClickHandler).toHaveBeenCalled();
});

test('renderWithThemeInBody renders correctly', async () => {
const {findByText, asFragment} = renderWithThemeInBody(ThemedLink, {});

await findByText('test link text');
expect(asFragment).toBeDefined();
expect(asFragment().getElementById('a11y-status-message')).toBeNull();
});
});

0 comments on commit 443da6c

Please sign in to comment.