-
-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix(callFirestore): handle a case where data function is undefined in firestore get * feat(tests): add testing against emulators (#107)
- Loading branch information
1 parent
f527ebb
commit b481d7a
Showing
11 changed files
with
3,986 additions
and
246 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,12 +44,37 @@ jobs: | |
CI: true | ||
run: yarn lint | ||
|
||
- name: Expose Test Environment Variables | ||
env: | ||
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }} | ||
GITHUB_HEAD_REF: ${{ github.head_ref }} | ||
GITHUB_REF: ${{ github.ref }} | ||
# Generate Service Account file required to prevent credential error (jq used to format) | ||
run: | | ||
echo "Generating Service Account File..." | ||
echo "$(echo $SERVICE_ACCOUNT | jq .)" > $HOME/serviceAccount.json | ||
echo "::set-env name=GOOGLE_APPLICATION_CREDENTIALS::$HOME/serviceAccount.json" | ||
- name: Run Unit Tests + Coverage | ||
env: | ||
CI: true | ||
CODE_CLIMATE: ${{ secrets.CODE_CLIMATE }} | ||
run: yarn test:cov && yarn codecov | ||
|
||
- name: Run Build | ||
run: yarn build | ||
|
||
# Skipped since yarn isn't supported | ||
# - name: Size Check | ||
# uses: andresz1/[email protected] | ||
# env: | ||
# CI_JOB_NUMBER: 1 | ||
# with: | ||
# github_token: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Size Check | ||
run: yarn size | ||
|
||
- name: Publish | ||
env: | ||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
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 |
---|---|---|
|
@@ -33,18 +33,38 @@ jobs: | |
CI: true | ||
run: yarn install --frozen-lockfile | ||
|
||
- name: Run Build | ||
run: yarn build | ||
|
||
- name: Check For Lint | ||
env: | ||
CI: true | ||
run: yarn lint | ||
|
||
- name: Expose Test Environment Variables | ||
env: | ||
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }} | ||
GITHUB_HEAD_REF: ${{ github.head_ref }} | ||
GITHUB_REF: ${{ github.ref }} | ||
# Generate Service Account file required to prevent credential error (jq used to format) | ||
run: | | ||
echo "Generating Service Account File..." | ||
echo "$(echo $SERVICE_ACCOUNT | jq .)" > $HOME/serviceAccount.json | ||
echo "::set-env name=GOOGLE_APPLICATION_CREDENTIALS::$HOME/serviceAccount.json" | ||
- name: Run Unit Tests + Coverage | ||
if: success() | ||
run: yarn test:cov | ||
|
||
- name: Run Build | ||
run: yarn build | ||
|
||
# Skipped since yarn isn't supported | ||
# - name: Size Check | ||
# uses: andresz1/[email protected] | ||
# env: | ||
# CI_JOB_NUMBER: 1 | ||
# with: | ||
# github_token: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Size Check | ||
run: yarn size | ||
|
||
- name: Upload Coverage | ||
if: success() | ||
env: | ||
|
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
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,13 +1,34 @@ | ||
/* eslint-disable no-unused-vars */ | ||
import chai from 'chai'; | ||
import sinon from 'sinon'; | ||
import sinonChai from 'sinon-chai'; | ||
import * as admin from 'firebase-admin'; | ||
|
||
const projectId = 'test-project'; | ||
const databaseEmulatorPort = 9000; | ||
const firstoreEmulatorPort = 8080; | ||
const databaseURL = `http://localhost:${databaseEmulatorPort}?ns=${projectId}`; | ||
|
||
// Set environment variables | ||
process.env.NODE_ENV = 'test'; | ||
process.env.GCLOUD_PROJECT = projectId; | ||
process.env.FIREBASE_DATABASE_EMULATOR_HOST = `localhost:${databaseEmulatorPort}`; | ||
process.env.FIRESTORE_EMULATOR_HOST = `localhost:${firstoreEmulatorPort}`; | ||
|
||
chai.use(sinonChai); | ||
|
||
// globals | ||
(global as any).expect = chai.expect; | ||
(global as any).sinon = sinon; | ||
(global as any).chai = chai; | ||
// Set global variables | ||
(global as any).projectId = projectId; | ||
(global as any).databaseURL = databaseURL; | ||
|
||
// Initialize admin SDK with emulator settings for RTDB | ||
admin.initializeApp({ | ||
projectId, | ||
databaseURL, | ||
// credential: admin.credential.applicationDefault(), | ||
}); | ||
|
||
// Initialize Firestore with emulator settings | ||
admin.firestore().settings({ | ||
servicePath: 'localhost', | ||
port: firstoreEmulatorPort, | ||
}); |
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,131 @@ | ||
import { expect } from 'chai'; | ||
import sinon from 'sinon'; | ||
import * as tasks from '../../src/tasks'; | ||
|
||
let adminInstance: any; | ||
let collectionSpy: any; | ||
let rtdbRefSpy: any; | ||
let rtdbVal: any; | ||
let rtdbRemoveSpy: any; | ||
let docSpy: any; | ||
let rtdbValSpy: any; | ||
let getSpy: any; | ||
const firestoreData: any = {}; | ||
|
||
describe('tasks with mocks/spies', () => { | ||
beforeEach(() => { | ||
const createCustomTokenSpy = sinon.spy(() => Promise.resolve('someToken')); | ||
const authSpy = sinon.spy(() => ({ | ||
createCustomToken: createCustomTokenSpy, | ||
})); | ||
getSpy = sinon.spy( | ||
(): Promise<any> => Promise.resolve({ data: () => firestoreData }), | ||
); | ||
docSpy = sinon.spy(() => ({ | ||
get: getSpy, | ||
})); | ||
collectionSpy = sinon.spy(() => ({ doc: docSpy, get: getSpy })); | ||
const firestoreSpy = sinon.spy(() => ({ | ||
collection: collectionSpy, | ||
doc: docSpy, | ||
})); | ||
const rtdbOnSpy = sinon.spy(); | ||
rtdbVal = { some: 'value' }; | ||
rtdbValSpy = sinon.spy(() => rtdbVal); | ||
const onceSpy = sinon.spy( | ||
(): Promise<any> => Promise.resolve({ val: rtdbValSpy }), | ||
); | ||
rtdbRemoveSpy = sinon.spy((): Promise<any> => Promise.resolve()); | ||
rtdbRefSpy = sinon.spy(() => ({ | ||
once: onceSpy, | ||
remove: rtdbRemoveSpy, | ||
on: rtdbOnSpy, | ||
})); | ||
const rtdbSpy = sinon.spy(() => ({ | ||
ref: rtdbRefSpy, | ||
})); | ||
adminInstance = { | ||
auth: authSpy, | ||
firestore: firestoreSpy, | ||
database: rtdbSpy, | ||
}; | ||
}); | ||
|
||
describe('callFirestore', () => { | ||
it('is exported', () => { | ||
expect(tasks).to.have.property('callFirestore'); | ||
expect(tasks.callFirestore).to.be.a('function'); | ||
}); | ||
it('returns a promise', () => { | ||
expect( | ||
tasks.callFirestore(adminInstance, 'get', 'some/path').then, | ||
).to.be.a('function'); | ||
}); | ||
describe('get action', () => { | ||
it('gets collections', async () => { | ||
const result = await tasks.callFirestore(adminInstance, 'get', 'some'); | ||
expect(collectionSpy).to.be.calledOnceWith('some'); | ||
expect(getSpy).to.be.calledOnce; | ||
expect(result).to.be.equal(firestoreData); | ||
}); | ||
|
||
it('gets documents', async () => { | ||
const result = await tasks.callFirestore( | ||
adminInstance, | ||
'get', | ||
'some/path', | ||
); | ||
expect(docSpy).to.be.calledOnceWith('some/path'); | ||
expect(getSpy).to.be.calledOnce; | ||
expect(result).to.be.equal(firestoreData); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('callRtdb', () => { | ||
it('is exported', () => { | ||
expect(tasks).to.have.property('callRtdb'); | ||
expect(tasks.callRtdb).to.be.a('function'); | ||
}); | ||
|
||
it('returns a promise', () => { | ||
expect(tasks.callRtdb(adminInstance, 'get', 'some/path').then).to.be.a( | ||
'function', | ||
); | ||
}); | ||
|
||
describe('get action', () => { | ||
it('gets data', async () => { | ||
const result = await tasks.callRtdb(adminInstance, 'get', 'some/path'); | ||
expect(rtdbRefSpy).to.have.been.calledOnceWith('some/path'); | ||
expect(result).to.equal(rtdbVal); | ||
}); | ||
}); | ||
|
||
describe('remove action', () => { | ||
it('removes data', async () => { | ||
await tasks.callRtdb(adminInstance, 'remove', 'some/path'); | ||
expect(rtdbRefSpy).to.have.been.calledOnceWith('some/path'); | ||
expect(rtdbRemoveSpy).to.have.been.calledOnce; | ||
}); | ||
|
||
it('supports "delete" action alias', async () => { | ||
await tasks.callRtdb(adminInstance, 'delete', 'some/path'); | ||
expect(rtdbRefSpy).to.have.been.calledOnceWith('some/path'); | ||
expect(rtdbRemoveSpy).to.have.been.calledOnce; | ||
}); | ||
}); | ||
}); | ||
|
||
describe('createCustomToken', () => { | ||
it('is exported', () => { | ||
expect(tasks).to.have.property('createCustomToken'); | ||
expect(tasks.createCustomToken).to.be.a('function'); | ||
}); | ||
it('returns a promise', () => { | ||
expect(tasks.createCustomToken(adminInstance, 'someuid').then).to.be.a( | ||
'function', | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.