diff --git a/test/auth.test.ts b/test/auth.test.ts index 951b443..ed28bc1 100644 --- a/test/auth.test.ts +++ b/test/auth.test.ts @@ -1,14 +1,16 @@ // Jest tests for ./src/auth.ts import fs from 'fs'; -import { google } from 'googleapis'; -import { OAuth2Client } from 'google-auth-library'; +import { authenticate } from '@google-cloud/local-auth'; +import { google, oauth2_v2 } from 'googleapis'; +import { OAuth2Client, JWT as JSONClient } from 'google-auth-library'; import * as auth from '../src/auth'; import { C2gError } from '../src/c2g-error'; import { MESSAGES } from '../src/messages'; jest.mock('fs'); +jest.mock('@google-cloud/local-auth'); jest.mock('googleapis'); jest.mock('google-auth-library'); @@ -169,10 +171,141 @@ describe('authorize', () => { // Arrange jest.spyOn(fs, 'existsSync').mockReturnValue(true); // isAuthorized jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(mockToken)); // loadSavedToken - jest.spyOn(google.auth, 'fromJSON').mockImplementation(); // loadSavedToken + jest + .spyOn(google.auth, 'fromJSON') + .mockImplementation(() => mockClient as unknown as JSONClient); // loadSavedToken + // Act + const result = await auth.authorize(); + // Assert + expect(result).toEqual(mockClient); + }); + + it('should create and return a new OAuth2Client after running `authenticate` and `saveToken`', async () => { + // Arrange + jest + .spyOn(fs, 'existsSync') + .mockReturnValueOnce(true) // isAuthorized > fs.existsSync(CREDENTIALS_PATH) + .mockReturnValueOnce(false); // isAuthorized > fs.existsSync(TOKEN_PATH) + const mockAuthenticate = authenticate as jest.MockedFunction< + typeof authenticate + >; + mockAuthenticate.mockResolvedValue(mockClient); + jest + .spyOn(fs, 'readFileSync') + .mockReturnValue(JSON.stringify(mockCredentials)); // saveToken + jest.spyOn(fs, 'writeFileSync').mockImplementation(); // saveToken // Act const result = await auth.authorize(); // Assert - expect(result).toEqual(mockToken); + expect(result).toEqual(mockClient); + expect(mockAuthenticate).toHaveBeenCalledTimes(1); + expect(fs.writeFileSync).toHaveBeenCalledTimes(1); + expect(fs.writeFileSync).toHaveBeenCalledWith( + auth.TOKEN_PATH, + JSON.stringify(mockToken), + ); + }); +}); + +describe('getUserEmail', () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should return null if the user is not authorized', async () => { + // Arrange + jest + .spyOn(fs, 'existsSync') + .mockReturnValueOnce(true) // isAuthorized > fs.existsSync(CREDENTIALS_PATH) + .mockReturnValueOnce(false); // isAuthorized > fs.existsSync(TOKEN_PATH) + // Act + const result = await auth.getUserEmail(); + // Assert + expect(result).toBeNull(); + }); + + it('should return the user email if the user is authorized', async () => { + // Arrange + const mockClient = { + credentials: { + access_token: 'mock-access-token', + refresh_token: 'mock-refresh-token', + }, + } as unknown as OAuth2Client; + const mockCredentials: auth.Credentials = { + installed: { + client_id: 'mock-client-id', + client_secret: 'mock-client-secret', + } as unknown as auth.CredentialsKey, + }; + const mockToken = { + type: 'authorized_user', + client_id: mockCredentials.installed?.client_id, + client_secret: mockCredentials.installed?.client_secret, + access_token: mockClient.credentials.access_token, + refresh_token: mockClient.credentials.refresh_token, + }; + const mockUserEmail = 'mock@user.email.com'; + jest.spyOn(fs, 'existsSync').mockReturnValue(true); // isAuthorized + jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(mockToken)); // loadSavedToken + jest + .spyOn(google.auth, 'fromJSON') + .mockImplementation(() => mockClient as unknown as JSONClient); // loadSavedToken + jest.spyOn(google, 'oauth2').mockImplementation(() => { + return { + userinfo: { + get: jest.fn().mockResolvedValue({ + data: { + email: mockUserEmail, + }, + }), + }, + } as unknown as oauth2_v2.Oauth2; + }); + // Act + const result = await auth.getUserEmail(); + // Assert + expect(result).toEqual(mockUserEmail); + }); + + it('should return null if there is a error in retrieving user email', async () => { + // Arrange + jest.spyOn(google, 'oauth2').mockImplementation(() => { + return { + userinfo: { + get: jest.fn().mockRejectedValue(new Error('mock-error')), + }, + } as unknown as oauth2_v2.Oauth2; + }); + // Other arrangements are the same as the previous test: + // 'should return the user email if the user is authorized' + const mockClient = { + credentials: { + access_token: 'mock-access-token', + refresh_token: 'mock-refresh-token', + }, + } as unknown as OAuth2Client; + const mockCredentials: auth.Credentials = { + installed: { + client_id: 'mock-client-id', + client_secret: 'mock-client-secret', + } as unknown as auth.CredentialsKey, + }; + const mockToken = { + type: 'authorized_user', + client_id: mockCredentials.installed?.client_id, + client_secret: mockCredentials.installed?.client_secret, + access_token: mockClient.credentials.access_token, + refresh_token: mockClient.credentials.refresh_token, + }; + jest.spyOn(fs, 'existsSync').mockReturnValue(true); // isAuthorized + jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(mockToken)); // loadSavedToken + jest + .spyOn(google.auth, 'fromJSON') + .mockImplementation(() => mockClient as unknown as JSONClient); // loadSavedToken + // Act + const result = await auth.getUserEmail(); + // Assert + expect(result).toBeNull(); }); });