Skip to content

Commit

Permalink
chore: Increase test coverage for service account impersonation suppo…
Browse files Browse the repository at this point in the history
…rt (#2047)

* chore: Increase test coverage for service account impersonation support

* fix typo
  • Loading branch information
lahirumaramba committed Jan 19, 2023
1 parent dd98704 commit 1896500
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/app/credential-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export class ImpersonatedServiceAccountCredential implements Credential {
* @param impersonatedServiceAccountPathOrObject - Impersonated Service account json object or
* path to a service account json file.
* @param httpAgent - Optional http.Agent to use when calling the remote token server.
* @param implicit - An optinal boolean indicating whether this credential was implicitly
* @param implicit - An optional boolean indicating whether this credential was implicitly
* discovered from the environment, as opposed to being explicitly specified by the developer.
*
* @constructor
Expand Down
70 changes: 70 additions & 0 deletions test/unit/app/credential-internal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import { HttpClient } from '../../../src/utils/api-request';
import { Agent } from 'https';
import { FirebaseAppError } from '../../../src/utils/error';
import { deepCopy } from '../../../src/utils/deep-copy';

chai.should();
chai.use(sinonChai);
Expand Down Expand Up @@ -420,6 +421,75 @@ describe('Credential', () => {
});
});

describe('ImpersonatedServiceAccountCredential', () => {
it('should throw if called with the path to an invalid file', () => {
const invalidPath = path.resolve(__dirname, '../../resources/unparsable.key.json');
expect(() => new ImpersonatedServiceAccountCredential(invalidPath))
.to.throw('Failed to parse impersonated service account file');
});

it('should throw given an object without a "clientId" property', () => {
const invalidCredential = deepCopy(MOCK_IMPERSONATED_TOKEN_CONFIG);
invalidCredential.source_credentials.client_id = '';
expect(() => new ImpersonatedServiceAccountCredential(invalidCredential as any))
.to.throw('Impersonated Service Account must contain a "source_credentials.client_id" property.');
});

it('should throw given an object without a "clientSecret" property', () => {
const invalidCredential = deepCopy(MOCK_IMPERSONATED_TOKEN_CONFIG);
invalidCredential.source_credentials.client_secret = '';
expect(() => new ImpersonatedServiceAccountCredential(invalidCredential as any))
.to.throw('Impersonated Service Account must contain a "source_credentials.client_secret" property.');
});

it('should throw given an object without a "refreshToken" property', () => {
const invalidCredential = deepCopy(MOCK_IMPERSONATED_TOKEN_CONFIG);
invalidCredential.source_credentials.refresh_token = '';
expect(() => new ImpersonatedServiceAccountCredential(invalidCredential as any))
.to.throw('Impersonated Service Account must contain a "source_credentials.refresh_token" property.');
});

it('should throw given an object without a "type" property', () => {
const invalidCredential = deepCopy(MOCK_IMPERSONATED_TOKEN_CONFIG);
invalidCredential.source_credentials.type = '';
expect(() => new ImpersonatedServiceAccountCredential(invalidCredential as any))
.to.throw('Impersonated Service Account must contain a "source_credentials.type" property.');
});

it('should return a Credential', () => {
const c = new ImpersonatedServiceAccountCredential(MOCK_IMPERSONATED_TOKEN_CONFIG);
expect(c).to.deep.include({
implicit: false,
});
});

it('should return an implicit Credential', () => {
const c = new ImpersonatedServiceAccountCredential(MOCK_IMPERSONATED_TOKEN_CONFIG, undefined, true);
expect(c).to.deep.include({
implicit: true,
});
});

it('should create access tokens', () => {
const scope = nock('https://www.googleapis.com')
.post('/oauth2/v4/token')
.reply(200, {
access_token: 'token',
token_type: 'Bearer',
expires_in: 60 * 60,
}, {
'cache-control': 'no-cache, no-store, max-age=0, must-revalidate',
});
mockedRequests.push(scope);

const c = new ImpersonatedServiceAccountCredential(MOCK_IMPERSONATED_TOKEN_CONFIG);
return c.getAccessToken().then((token) => {
expect(token.access_token).to.be.a('string').and.to.not.be.empty;
expect(token.expires_in).to.greaterThan(FIVE_MINUTES_IN_SECONDS);
});
});
});

describe('getApplicationDefault()', () => {
let fsStub: sinon.SinonStub;

Expand Down

0 comments on commit 1896500

Please sign in to comment.