diff --git a/packages/testing/index.ts b/packages/testing/index.ts index 771308161a0..c3a1aa3ba0f 100644 --- a/packages/testing/index.ts +++ b/packages/testing/index.ts @@ -24,7 +24,6 @@ export { apps, assertFails, assertSucceeds, - initializeAdminApp, initializeTestApp, loadDatabaseRules } from './src/api'; diff --git a/packages/testing/package.json b/packages/testing/package.json index 3244a9b8892..8a7c5add0a1 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -16,7 +16,6 @@ }, "license": "Apache-2.0", "dependencies": { - "firebase-admin": "5.12.0", "request-promise": "4.2.2" }, "devDependencies": { diff --git a/packages/testing/src/api/index.ts b/packages/testing/src/api/index.ts index 9239ba34bfc..31bc5049d0b 100644 --- a/packages/testing/src/api/index.ts +++ b/packages/testing/src/api/index.ts @@ -14,9 +14,11 @@ * limitations under the License. */ -import * as admin from 'firebase-admin'; +import { firebase } from '@firebase/app'; import request from 'request-promise'; import * as fs from 'fs'; +import { FirebaseApp, FirebaseOptions } from '@firebase/app-types'; +import { base64 } from '@firebase/util'; const DBURL = 'http://localhost:9000'; @@ -32,36 +34,43 @@ class FakeCredentials { } } -export function apps(): (admin.app.App | null)[] { - return admin.apps; +export function apps(): (FirebaseApp | null)[] { + return firebase.apps; } -export function initializeAdminApp(options: any): admin.app.App { - if (!('databaseName' in options)) { - throw new Error('databaseName not specified'); - } - return admin.initializeApp( - { - credential: new FakeCredentials(), +export type AppOptions = { + databaseName?: string; + projectId?: string; + auth: object; +}; +export function initializeTestApp(options: AppOptions): FirebaseApp { + let appOptions: FirebaseOptions; + if ('databaseName' in options) { + appOptions = { databaseURL: DBURL + '?ns=' + options.databaseName - }, - 'app-' + (new Date().getTime() + Math.random()) - ); -} - -export function initializeTestApp(options: any): admin.app.App { - if (!('databaseName' in options)) { - throw new Error('databaseName not specified'); + }; + } else if ('projectId' in options) { + appOptions = { + projectId: options.projectId + }; + } else { + throw new Error('neither databaseName or projectId were specified'); } - // if options.auth is not present, we will construct an app with auth == null - return admin.initializeApp( - { - credential: new FakeCredentials(), - databaseURL: DBURL + '?ns=' + options.databaseName, - databaseAuthVariableOverride: options.auth || null - }, - 'app-' + (new Date().getTime() + Math.random()) - ); + const header = { + alg: 'RS256', + kid: 'fakekid' + }; + const fakeToken = [ + base64.encodeString(JSON.stringify(header), /*webSafe=*/ false), + base64.encodeString(JSON.stringify(options.auth), /*webSafe=*/ false), + 'fakesignature' + ].join('.'); + const appName = 'app-' + new Date().getTime() + '-' + Math.random(); + const app = firebase.initializeApp(appOptions, appName); + // hijacking INTERNAL.getToken to bypass FirebaseAuth and allows specifying of auth headers + (app as any).INTERNAL.getToken = () => + Promise.resolve({ accessToken: fakeToken }); + return app; } export type LoadDatabaseRulesOptions = { diff --git a/packages/testing/test/database.test.ts b/packages/testing/test/database.test.ts index 9e7f6bb9f76..a89aa185963 100644 --- a/packages/testing/test/database.test.ts +++ b/packages/testing/test/database.test.ts @@ -16,6 +16,7 @@ import { expect } from 'chai'; import * as firebase from '../src/api'; +import { base64 } from '@firebase/util'; describe('Testing Module Tests', function() { it('assertSucceeds() iff success', async function() { @@ -46,42 +47,56 @@ describe('Testing Module Tests', function() { }); }); - it('initializeAdminApp() throws if no databaseName', function() { - expect(firebase.initializeAdminApp.bind(null, {})).to.throw( - /databaseName not specified/ + it('initializeTestApp() with DatabaseAppOptions uses specified auth.', async function() { + let app = firebase.initializeTestApp({ + projectId: 'foo', + auth: {} + }); + let token = await (app as any).INTERNAL.getToken(); + expect(token).to.have.any.keys('accessToken'); + let claims = base64.decodeString( + token.accessToken.split('.')[1], + /*webSafe=*/ false ); - expect( - firebase.initializeAdminApp.bind(null, { databaseName: 'foo' }) - ).to.not.throw(); - }); + expect(claims).to.equal('{}'); - it('initializeAdminApp() provides admin', function() { - const app = firebase.initializeAdminApp({ databaseName: 'foo' }); - expect(app.options).to.not.have.any.keys('databaseAuthVariableOverride'); - }); - - it('initializeTestApp() throws if no databaseName', function() { - expect(firebase.initializeTestApp.bind(null, {})).to.throw( - /databaseName not specified/ + app = firebase.initializeTestApp({ + projectId: 'foo', + auth: { uid: 'alice' } + }); + token = await (app as any).INTERNAL.getToken(); + expect(token).to.have.any.keys('accessToken'); + claims = base64.decodeString( + token.accessToken.split('.')[1], + /*webSafe=*/ false ); - expect( - firebase.initializeTestApp.bind(null, { databaseName: 'foo' }) - ).to.not.throw(); + expect(claims).to.equal('{"uid":"alice"}'); }); - it('initializeTestApp() uses specified auth.', function() { - let app = firebase.initializeTestApp({ databaseName: 'foo' }); - expect(app.options).to.have.any.keys('databaseAuthVariableOverride'); + it('initializeTestApp() with FirestoreAppOptions uses specified auth.', async function() { + let app = firebase.initializeTestApp({ + projectId: 'foo', + auth: {} + }); + let token = await (app as any).INTERNAL.getToken(); + expect(token).to.have.any.keys('accessToken'); + let claims = base64.decodeString( + token.accessToken.split('.')[1], + /*webSafe=*/ false + ); + expect(claims).to.equal('{}'); app = firebase.initializeTestApp({ - databaseName: 'foo', + projectId: 'foo', auth: { uid: 'alice' } }); - expect(app.options).to.have.any.keys('databaseAuthVariableOverride'); - expect(app.options.databaseAuthVariableOverride).to.have.all.keys('uid'); - expect(app.options.databaseAuthVariableOverride['uid']).to.be.equal( - 'alice' + token = await (app as any).INTERNAL.getToken(); + expect(token).to.have.any.keys('accessToken'); + claims = base64.decodeString( + token.accessToken.split('.')[1], + /*webSafe=*/ false ); + expect(claims).to.equal('{"uid":"alice"}'); }); it('loadDatabaseRules() throws if no databaseName or rulesPath', async function() { @@ -108,13 +123,11 @@ describe('Testing Module Tests', function() { ).to.throw(/Could not find file/); }); - it('apps() returns all created apps', async function() { + it('apps() returns apps created with initializeTestApp', async function() { const numApps = firebase.apps().length; - await firebase.initializeAdminApp({ databaseName: 'foo' }); + await firebase.initializeTestApp({ databaseName: 'foo', auth: {} }); expect(firebase.apps().length).to.equal(numApps + 1); - await firebase.initializeAdminApp({ databaseName: 'foo' }); + await firebase.initializeTestApp({ databaseName: 'bar', auth: {} }); expect(firebase.apps().length).to.equal(numApps + 2); - await firebase.initializeTestApp({ databaseName: 'foo' }); - expect(firebase.apps().length).to.equal(numApps + 3); }); });