-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0cf98bf
commit 7d842df
Showing
99 changed files
with
1,027 additions
and
727 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
const logger = require('../lib/logger') | ||
const config = require('../../project.config') | ||
|
||
logger.info('Starting server...') | ||
require('../../server/main').listen(3000, () => { | ||
logger.success('Server is running at http://localhost:3000') | ||
require('../../server/main').listen(config.port, () => { | ||
logger.success(`Server is running at http://localhost:${config.port}`) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,5 +48,8 @@ | |
"mocha": "^5.0.4", | ||
"rimraf": "^2.6.2", | ||
"sinon": "^4.1.2" | ||
}, | ||
"engines": { | ||
"node": "6.14.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,32 @@ | ||
/** | ||
* Async await wrapper for easy error handling | ||
* @param {Promise} promise - Promise to wrap responses of | ||
* @return {Promise} Resolves and rejects with an array | ||
* @example | ||
* async function asyncFunctionWithThrow() { | ||
* const [err, snap] = await to( | ||
* admin.database().ref('some').once('value') | ||
* ); | ||
* if (err) { | ||
* console.error('Error getting data:', err.message || err) | ||
* throw err | ||
* } | ||
* if (!snap.val()) throw new Error('Data not found'); | ||
* console.log('Data found:', snap.val()) | ||
* } | ||
*/ | ||
export function to(promise) { | ||
return promise | ||
.then(data => { | ||
return [null, data] | ||
}) | ||
.catch(err => [err]) | ||
return promise.then(data => [null, data]).catch(err => [err]) | ||
} | ||
|
||
/** | ||
* Run promises in a waterfall instead of all the same time (Promise.all) | ||
* @param {Array} callbacks - List of promises to run in order | ||
* @return {Promise} Resolves when all promises have completed in order | ||
*/ | ||
export function promiseWaterfall(callbacks) { | ||
// Don't assume we're running in an environment with promises | ||
return callbacks.reduce(function(accumulator, callback) { | ||
return accumulator.then(callback) | ||
}, Promise.resolve()) | ||
return callbacks.reduce( | ||
(accumulator, callback) => accumulator.then(callback), | ||
Promise.resolve() | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as admin from 'firebase-admin' // eslint-disable-line no-unused-vars | ||
|
||
describe('Cloud Functions', () => { | ||
let myFunctions | ||
let configStub | ||
let adminInitStub | ||
let admin | ||
|
||
before(() => { | ||
/* eslint-disable global-require */ | ||
adminInitStub = sinon.stub(admin, 'initializeApp') | ||
myFunctions = require(`${__dirname}/../../index`) | ||
/* eslint-enable global-require */ | ||
}) | ||
|
||
after(() => { | ||
// Restoring our stubs to the original methods. | ||
configStub.restore() | ||
adminInitStub.restore() | ||
}) | ||
|
||
it('exports an object', () => { | ||
expect(myFunctions).to.be.an('object') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
const firebasemock = require('firebase-mock') | ||
let mockauth = new firebasemock.MockFirebase() | ||
let mockdatabase = new firebasemock.MockFirebase() | ||
let mockfirestore = new firebasemock.MockFirestore() | ||
let mocksdk = firebasemock.MockFirebaseSdk( | ||
function() { | ||
return mockdatabase | ||
}, | ||
function() { | ||
return mockauth | ||
}, | ||
function() { | ||
return mockfirestore | ||
} | ||
) | ||
|
||
let mockapp = mocksdk.initializeApp() | ||
|
||
describe('indexUsers Cloud Function', () => { | ||
let myFunctions | ||
let configStub | ||
let adminInitStub | ||
let functions | ||
|
||
beforeEach(() => { | ||
// Since index.js makes calls to functions.config and admin.initializeApp at the top of the file, | ||
// we need to stub both of these functions before requiring index.js. This is because the | ||
// functions will be executed as a part of the require process. | ||
// Here we stub admin.initializeApp to be a dummy function that doesn't do anything. | ||
/* eslint-disable global-require */ | ||
process.env.GCLOUD_PROJECT = 'FakeProjectId' | ||
mockdatabase = new firebasemock.MockFirebase() | ||
mockauth = new firebasemock.MockFirebase() | ||
mockfirestore = new firebasemock.MockFirestore() | ||
adminInitStub = sinon.stub(mocksdk, 'initializeApp') | ||
// Next we stub functions.config(). Normally config values are loaded from Cloud Runtime Config; | ||
// here we'll just provide some fake values for firebase.databaseURL and firebase.storageBucket | ||
// so that an error is not thrown during admin.initializeApp's parameter check | ||
functions = require('firebase-functions') | ||
configStub = sinon.stub(functions, 'config').returns({ | ||
firebase: { | ||
databaseURL: 'https://not-a-project.firebaseio.com', | ||
storageBucket: 'not-a-project.appspot.com', | ||
projectId: 'not-a-project.appspot', | ||
messagingSenderId: '823357791673' | ||
} | ||
// You can stub any other config values needed by your functions here, for example: | ||
// foo: 'bar' | ||
}) | ||
// Now we require index.js and save the exports inside a namespace called myFunctions | ||
// if we use ../ without dirname here, it can not be run with --prefix from parent folder | ||
myFunctions = require(`${__dirname}/../../index`) | ||
mockdatabase.autoFlush() | ||
mockauth.autoFlush() | ||
mockfirestore.autoFlush() | ||
/* eslint-enable global-require */ | ||
}) | ||
|
||
afterEach(() => { | ||
// Restoring stubs to the original methods | ||
configStub.restore() | ||
adminInitStub.restore() | ||
}) | ||
|
||
it('adds display name if it did not exist before', async () => { | ||
const fakeEvent = { | ||
data: new firebasemock.DeltaDocumentSnapshot( | ||
mockapp, | ||
null, | ||
{ | ||
displayName: 'bob', | ||
createdTime: new Date() | ||
}, | ||
'users/123' | ||
), | ||
params: { | ||
userId: '123ABC' | ||
} | ||
} | ||
// Invoke function with fake event | ||
try { | ||
await myFunctions.indexUser(fakeEvent) | ||
} catch (err) { | ||
expect(err).to.exist | ||
expect( | ||
err.message.indexOf('The project not-a-project.appspot does not exist') | ||
).to.not.equal(-1) | ||
} | ||
}) | ||
|
||
it('returns null if display name is not changed', async () => { | ||
const fakeEvent = { | ||
// The DeltaSnapshot constructor is used by the Functions SDK to transform a raw event from | ||
// your database into an object with utility functions such as .val(). | ||
// Its signature is: DeltaSnapshot(app: firebase.app.App, adminApp: firebase.app.App, | ||
// data: any, delta: any, path?: string); | ||
// We can pass null for the first 2 parameters. The data parameter represents the state of | ||
// the database item before the event, while the delta parameter represents the change that | ||
// occured to cause the event to fire. The last parameter is the database path, which we are | ||
// not making use of in this test. So we will omit it. | ||
data: new firebasemock.DeltaDocumentSnapshot( | ||
mockapp, | ||
{ | ||
displayName: 'bob', | ||
createdTime: new Date() + 50 | ||
}, | ||
{ | ||
displayName: 'bob', | ||
createdTime: new Date() | ||
}, | ||
'users/123' | ||
), | ||
params: { | ||
userId: '123ABC' | ||
} | ||
} | ||
// Invoke webhook with our fake request and response objects. This will cause the | ||
// assertions in the response object to be evaluated. | ||
const res = await myFunctions.indexUsers(fakeEvent) | ||
expect(res).to.be.null | ||
}) | ||
}) |
Oops, something went wrong.