Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(PPDSC-2643): add missing unit tests for getSheets #538

Merged
merged 1 commit into from
Jan 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
});
});