From 97d382352542c4774e7c55b6fdfa29c3bc848d79 Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Mon, 22 Mar 2021 17:47:57 -0700 Subject: [PATCH] Add emulator-based integration tests. (#1155) * Add emulator-based integration tests. * Move emulator stuff out of package.json. * Update CONTRIBUTING.md too. * Add npx. * Skip new unsupported tests. * Inline commands in ci.yml. --- .github/workflows/ci.yml | 13 ++++++++++--- CONTRIBUTING.md | 23 ++++++++++++++++++++++- test/integration/auth.spec.ts | 10 ++++++++-- test/integration/database.spec.ts | 22 ++++++++++++++++++---- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5810ed895..244d123dd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,10 +17,17 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: Install, build and test + - name: Install and build run: | npm ci npm run build npm run build:tests - npm test - npm run api-extractor + - name: Lint and run unit tests + run: npm test + - name: Run api-extractor + run: npm run api-extractor + - name: Run emulator-based integration tests + run: | + npm install -g firebase-tools + firebase emulators:exec --project fake-project-id --only auth,database,firestore \ + 'npx mocha \"test/integration/{auth,database,firestore}.spec.ts\" --slow 5000 --timeout 20000 --require ts-node/register' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbb374fa14..7ac6a71cb1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -123,6 +123,8 @@ There are two test suites: unit and integration. The unit test suite is intended development, and the integration test suite is intended to be run before packaging up release candidates. +#### Unit Tests + To run the unit test suite: ```bash @@ -135,7 +137,26 @@ If you wish to skip the linter, and only run the unit tests: $ npm run test:unit ``` -The integration tests run against an actual Firebase project. Create a new +#### Integration Tests with Emulator Suite + +Some of the integration tests work with the Emulator Suite and you can run them +without an actual Firebase project. + +First, make sure to [install Firebase CLI](https://firebase.google.com/docs/cli#install_the_firebase_cli). +And then: + +```bash + firebase emulators:exec --project fake-project-id --only auth,database,firestore \ + 'npx mocha \"test/integration/{auth,database,firestore}.spec.ts\" --slow 5000 --timeout 20000 --require ts-node/register' +``` + +Currently, only the Auth, Database, and Firestore test suites work. Some test +cases will be automatically skipped due to lack of emulator support. The section +below covers how to run the full test suite against an actual Firebase project. + +#### Integration Tests with an actual Firebase project + +Other integration tests require an actual Firebase project. Create a new project in the [Firebase Console](https://console.firebase.google.com), if you do not already have one suitable for running the tests against. Then obtain the following credentials from the project: diff --git a/test/integration/auth.spec.ts b/test/integration/auth.spec.ts index bf9f7f134d..29060b4cdd 100644 --- a/test/integration/auth.spec.ts +++ b/test/integration/auth.spec.ts @@ -683,7 +683,10 @@ describe('admin.auth', () => { }); }); - it('can link/unlink with a federated provider', async () => { + it('can link/unlink with a federated provider', async function () { + if (authEmulatorHost) { + return this.skip(); // Not yet supported in Auth Emulator. + } const googleFederatedUid = 'google_uid_' + generateRandomString(10); let userRecord = await admin.auth().updateUser(updateUser.uid, { providerToLink: { @@ -707,7 +710,10 @@ describe('admin.auth', () => { expect(providerIds).to.not.deep.include('google.com'); }); - it('can unlink multiple providers at once, incl a non-federated provider', async () => { + it('can unlink multiple providers at once, incl a non-federated provider', async function () { + if (authEmulatorHost) { + return this.skip(); // Not yet supported in Auth Emulator. + } await deletePhoneNumberUser('+15555550001'); const googleFederatedUid = 'google_uid_' + generateRandomString(10); diff --git a/test/integration/database.spec.ts b/test/integration/database.spec.ts index 708c3a153a..77204a1839 100644 --- a/test/integration/database.spec.ts +++ b/test/integration/database.spec.ts @@ -17,7 +17,7 @@ import * as admin from '../../lib/index'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; -import { defaultApp, nullApp, nonNullApp, cmdArgs, databaseUrl } from './setup'; +import { defaultApp, nullApp, nonNullApp, cmdArgs, databaseUrl, isEmulator } from './setup'; // eslint-disable-next-line @typescript-eslint/no-var-requires const chalk = require('chalk'); @@ -64,7 +64,13 @@ describe('admin.database', () => { .should.eventually.be.fulfilled; }); - it('App with null auth overrides is blocked by security rules', () => { + it('App with null auth overrides is blocked by security rules', function () { + if (isEmulator) { + // RTDB emulator has open security rules by default and won't block this. + // TODO(https://github.com/firebase/firebase-admin-node/issues/1149): + // remove this once updating security rules through admin is in place. + return this.skip(); + } return nullApp.database().ref('blocked').set(admin.database.ServerValue.TIMESTAMP) .should.eventually.be.rejectedWith('PERMISSION_DENIED: Permission denied'); }); @@ -157,13 +163,21 @@ describe('admin.database', () => { }); }); - it('admin.database().getRules() returns currently defined rules as a string', () => { + it('admin.database().getRules() returns currently defined rules as a string', function () { + if (isEmulator) { + // https://github.com/firebase/firebase-admin-node/issues/1149 + return this.skip(); + } return admin.database().getRules().then((result) => { return expect(result).to.be.not.empty; }); }); - it('admin.database().getRulesJSON() returns currently defined rules as an object', () => { + it('admin.database().getRulesJSON() returns currently defined rules as an object', function () { + if (isEmulator) { + // https://github.com/firebase/firebase-admin-node/issues/1149 + return this.skip(); + } return admin.database().getRulesJSON().then((result) => { return expect(result).to.be.not.undefined; });