Skip to content

Commit f1a5e2e

Browse files
authored
Enable firestore sdk to talk to emulator (#1007)
* Enable firestore sdk to talk to emulator * [AUTOMATED]: Prettier Code Styling * Revert firestore sdk changes * [AUTOMATED]: Prettier Code Styling * Revert credentials.ts * Cleanup * [AUTOMATED]: Prettier Code Styling * Set webSafe=false * Combine initializeTestApp and initializeFirestoreTestApp * [AUTOMATED]: Prettier Code Styling * Cleanup * [AUTOMATED]: Prettier Code Styling * Update major version since this is a breaking change that will cause the testing sdk to no longer work with old versions of the RTDB emulator * Completely remove admin sdk * Change version back to 0.1.0
1 parent e125588 commit f1a5e2e

File tree

4 files changed

+80
-60
lines changed

4 files changed

+80
-60
lines changed

packages/testing/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export {
2424
apps,
2525
assertFails,
2626
assertSucceeds,
27-
initializeAdminApp,
2827
initializeTestApp,
2928
loadDatabaseRules
3029
} from './src/api';

packages/testing/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
},
1717
"license": "Apache-2.0",
1818
"dependencies": {
19-
"firebase-admin": "5.12.0",
2019
"request-promise": "4.2.2"
2120
},
2221
"devDependencies": {

packages/testing/src/api/index.ts

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
import * as admin from 'firebase-admin';
17+
import { firebase } from '@firebase/app';
1818
import request from 'request-promise';
1919
import * as fs from 'fs';
20+
import { FirebaseApp, FirebaseOptions } from '@firebase/app-types';
21+
import { base64 } from '@firebase/util';
2022

2123
const DBURL = 'http://localhost:9000';
2224

@@ -32,36 +34,43 @@ class FakeCredentials {
3234
}
3335
}
3436

35-
export function apps(): (admin.app.App | null)[] {
36-
return admin.apps;
37+
export function apps(): (FirebaseApp | null)[] {
38+
return firebase.apps;
3739
}
3840

39-
export function initializeAdminApp(options: any): admin.app.App {
40-
if (!('databaseName' in options)) {
41-
throw new Error('databaseName not specified');
42-
}
43-
return admin.initializeApp(
44-
{
45-
credential: new FakeCredentials(),
41+
export type AppOptions = {
42+
databaseName?: string;
43+
projectId?: string;
44+
auth: object;
45+
};
46+
export function initializeTestApp(options: AppOptions): FirebaseApp {
47+
let appOptions: FirebaseOptions;
48+
if ('databaseName' in options) {
49+
appOptions = {
4650
databaseURL: DBURL + '?ns=' + options.databaseName
47-
},
48-
'app-' + (new Date().getTime() + Math.random())
49-
);
50-
}
51-
52-
export function initializeTestApp(options: any): admin.app.App {
53-
if (!('databaseName' in options)) {
54-
throw new Error('databaseName not specified');
51+
};
52+
} else if ('projectId' in options) {
53+
appOptions = {
54+
projectId: options.projectId
55+
};
56+
} else {
57+
throw new Error('neither databaseName or projectId were specified');
5558
}
56-
// if options.auth is not present, we will construct an app with auth == null
57-
return admin.initializeApp(
58-
{
59-
credential: new FakeCredentials(),
60-
databaseURL: DBURL + '?ns=' + options.databaseName,
61-
databaseAuthVariableOverride: options.auth || null
62-
},
63-
'app-' + (new Date().getTime() + Math.random())
64-
);
59+
const header = {
60+
alg: 'RS256',
61+
kid: 'fakekid'
62+
};
63+
const fakeToken = [
64+
base64.encodeString(JSON.stringify(header), /*webSafe=*/ false),
65+
base64.encodeString(JSON.stringify(options.auth), /*webSafe=*/ false),
66+
'fakesignature'
67+
].join('.');
68+
const appName = 'app-' + new Date().getTime() + '-' + Math.random();
69+
const app = firebase.initializeApp(appOptions, appName);
70+
// hijacking INTERNAL.getToken to bypass FirebaseAuth and allows specifying of auth headers
71+
(app as any).INTERNAL.getToken = () =>
72+
Promise.resolve({ accessToken: fakeToken });
73+
return app;
6574
}
6675

6776
export type LoadDatabaseRulesOptions = {

packages/testing/test/database.test.ts

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import { expect } from 'chai';
1818
import * as firebase from '../src/api';
19+
import { base64 } from '@firebase/util';
1920

2021
describe('Testing Module Tests', function() {
2122
it('assertSucceeds() iff success', async function() {
@@ -46,42 +47,56 @@ describe('Testing Module Tests', function() {
4647
});
4748
});
4849

49-
it('initializeAdminApp() throws if no databaseName', function() {
50-
expect(firebase.initializeAdminApp.bind(null, {})).to.throw(
51-
/databaseName not specified/
50+
it('initializeTestApp() with DatabaseAppOptions uses specified auth.', async function() {
51+
let app = firebase.initializeTestApp({
52+
projectId: 'foo',
53+
auth: {}
54+
});
55+
let token = await (app as any).INTERNAL.getToken();
56+
expect(token).to.have.any.keys('accessToken');
57+
let claims = base64.decodeString(
58+
token.accessToken.split('.')[1],
59+
/*webSafe=*/ false
5260
);
53-
expect(
54-
firebase.initializeAdminApp.bind(null, { databaseName: 'foo' })
55-
).to.not.throw();
56-
});
61+
expect(claims).to.equal('{}');
5762

58-
it('initializeAdminApp() provides admin', function() {
59-
const app = firebase.initializeAdminApp({ databaseName: 'foo' });
60-
expect(app.options).to.not.have.any.keys('databaseAuthVariableOverride');
61-
});
62-
63-
it('initializeTestApp() throws if no databaseName', function() {
64-
expect(firebase.initializeTestApp.bind(null, {})).to.throw(
65-
/databaseName not specified/
63+
app = firebase.initializeTestApp({
64+
projectId: 'foo',
65+
auth: { uid: 'alice' }
66+
});
67+
token = await (app as any).INTERNAL.getToken();
68+
expect(token).to.have.any.keys('accessToken');
69+
claims = base64.decodeString(
70+
token.accessToken.split('.')[1],
71+
/*webSafe=*/ false
6672
);
67-
expect(
68-
firebase.initializeTestApp.bind(null, { databaseName: 'foo' })
69-
).to.not.throw();
73+
expect(claims).to.equal('{"uid":"alice"}');
7074
});
7175

72-
it('initializeTestApp() uses specified auth.', function() {
73-
let app = firebase.initializeTestApp({ databaseName: 'foo' });
74-
expect(app.options).to.have.any.keys('databaseAuthVariableOverride');
76+
it('initializeTestApp() with FirestoreAppOptions uses specified auth.', async function() {
77+
let app = firebase.initializeTestApp({
78+
projectId: 'foo',
79+
auth: {}
80+
});
81+
let token = await (app as any).INTERNAL.getToken();
82+
expect(token).to.have.any.keys('accessToken');
83+
let claims = base64.decodeString(
84+
token.accessToken.split('.')[1],
85+
/*webSafe=*/ false
86+
);
87+
expect(claims).to.equal('{}');
7588

7689
app = firebase.initializeTestApp({
77-
databaseName: 'foo',
90+
projectId: 'foo',
7891
auth: { uid: 'alice' }
7992
});
80-
expect(app.options).to.have.any.keys('databaseAuthVariableOverride');
81-
expect(app.options.databaseAuthVariableOverride).to.have.all.keys('uid');
82-
expect(app.options.databaseAuthVariableOverride['uid']).to.be.equal(
83-
'alice'
93+
token = await (app as any).INTERNAL.getToken();
94+
expect(token).to.have.any.keys('accessToken');
95+
claims = base64.decodeString(
96+
token.accessToken.split('.')[1],
97+
/*webSafe=*/ false
8498
);
99+
expect(claims).to.equal('{"uid":"alice"}');
85100
});
86101

87102
it('loadDatabaseRules() throws if no databaseName or rulesPath', async function() {
@@ -108,13 +123,11 @@ describe('Testing Module Tests', function() {
108123
).to.throw(/Could not find file/);
109124
});
110125

111-
it('apps() returns all created apps', async function() {
126+
it('apps() returns apps created with initializeTestApp', async function() {
112127
const numApps = firebase.apps().length;
113-
await firebase.initializeAdminApp({ databaseName: 'foo' });
128+
await firebase.initializeTestApp({ databaseName: 'foo', auth: {} });
114129
expect(firebase.apps().length).to.equal(numApps + 1);
115-
await firebase.initializeAdminApp({ databaseName: 'foo' });
130+
await firebase.initializeTestApp({ databaseName: 'bar', auth: {} });
116131
expect(firebase.apps().length).to.equal(numApps + 2);
117-
await firebase.initializeTestApp({ databaseName: 'foo' });
118-
expect(firebase.apps().length).to.equal(numApps + 3);
119132
});
120133
});

0 commit comments

Comments
 (0)