Skip to content

Commit

Permalink
test(REPLICATE_ATTRIBUTES): Add test for REPLICATE_ATTRIBUTES
Browse files Browse the repository at this point in the history
  • Loading branch information
anishkny committed Nov 30, 2020
1 parent 64672c6 commit 95732ca
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 29 deletions.
10 changes: 4 additions & 6 deletions .gitignore
@@ -1,8 +1,6 @@
node_modules
lib
test/service-account-key.json
test/functions/integrify.js
.nyc_output
coverage
.vscode
firestore-debug.log
*-debug.log
coverage
lib
node_modules
1 change: 1 addition & 0 deletions src/rules/replicateAttributes.ts
Expand Up @@ -68,6 +68,7 @@ export function integrifyReplicateAttributes(

// Call "pre" hook if defined
const promises = [];
// istanbul ignore else
if (rule.hooks && rule.hooks.pre) {
promises.push(rule.hooks.pre(change, context));
console.log(`integrify: Running pre-hook: ${rule.hooks.pre}`);
Expand Down
13 changes: 8 additions & 5 deletions test/functions/index.js
@@ -1,5 +1,4 @@
const { integrify } = require('../../lib');
const { setState } = require('./stateMachine');

const functions = require('firebase-functions');
const admin = require('firebase-admin');
Expand Down Expand Up @@ -34,8 +33,10 @@ module.exports.replicateMasterToDetail = integrify({
},
],
hooks: {
pre: (change, context) => {
setState({ change, context });
pre: async (change, context) => {
await db.collection('prehooks').add({
message: '[788a32e05504] REPLICATE_ATTRIBUTES prehook was called!',
});
},
},
});
Expand All @@ -57,8 +58,10 @@ module.exports.deleteReferencesToMaster = integrify({
},
],
hooks: {
pre: (snap, context) => {
setState({ snap, context });
pre: async (snap, context) => {
await db.collection('prehooks').add({
message: '[6a8f4f8f090c] DELETE_REFERENCES prehook was called!',
});
},
},
});
Expand Down
16 changes: 8 additions & 8 deletions test/functions/integrify.rules.js
Expand Up @@ -3,19 +3,19 @@ module.exports = [
rule: 'REPLICATE_ATTRIBUTES',
name: 'replicateMasterToDetailFromFile',
source: {
collection: 'master',
collection: 'rules-file-master',
},
targets: [
{
collection: 'detail1',
collection: 'rules-file-detail1',
foreignKey: 'masterId',
attributeMapping: {
masterField1: 'detail1Field1',
masterField2: 'detail1Field2',
},
},
{
collection: 'detail2',
collection: 'rules-file-detail2',
foreignKey: 'masterId',
attributeMapping: {
masterField1: 'detail2Field1',
Expand All @@ -29,15 +29,15 @@ module.exports = [
rule: 'DELETE_REFERENCES',
name: 'deleteReferencesToMasterFromFile',
source: {
collection: 'master',
collection: 'rules-file-master',
},
targets: [
{
collection: 'detail1',
collection: 'rules-file-detail1',
foreignKey: 'masterId',
},
{
collection: 'detail2',
collection: 'rules-file-detail2',
foreignKey: 'masterId',
isCollectionGroup: true,
},
Expand All @@ -47,11 +47,11 @@ module.exports = [
rule: 'MAINTAIN_COUNT',
name: 'maintainFavoritesCountFromFile',
source: {
collection: 'favorites',
collection: 'rules-file-favorites',
foreignKey: 'articleId',
},
target: {
collection: 'articles',
collection: 'rules-file-articles',
attribute: 'favoritesCount',
},
},
Expand Down
4 changes: 0 additions & 4 deletions test/functions/stateMachine.js

This file was deleted.

89 changes: 86 additions & 3 deletions test/main.test.js
Expand Up @@ -2,23 +2,106 @@ const assert = require('chai').assert;

const { integrify } = require('../lib');

const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();

describe('Error conditions', () => {
it('should error on bad rule', function () {
it('should error on bad rule', () => {
assert.throws(
() => integrify({ rule: 'BAD_RULE_ea8e3a2a2d3e' }),
/Unknown rule/i
);
assert.throws(() => require('./functions-bad-rules-file'), /Unknown rule/i);
});

it('should error on no rule or config', function () {
it('should error on no rule or config', () => {
assert.throws(() => integrify(42), /Input must be rule or config/i);
});

it('should error on absent config file', function () {
it('should error on absent config file', () => {
assert.throws(
() => require('./functions-absent-rules-file'),
/Rules file not found/i
);
});
});

describe('REPLICATE_ATTRIBUTES', () => {
it('should replicate attributes', async () => {
// Create master document to replicate from
const masterRef = await db
.collection('master')
.add({ random: Math.random() });
const masterId = masterRef.id;

// Create couple of detail docs to replicate to
await db.collection('detail1').add({ masterId });
await db.collection('detail2').add({ masterId });

// Update master doc
const masterField1 = randstr();
const masterField2 = randstr();
await masterRef.update({ masterField1, masterField2 });

// Ensure update is reflected in detail docs
await assertQuerySizeEventually(
db
.collection('detail1')
.where('masterId', '==', masterId)
.where('detail1Field1', '==', masterField1),
1
);
await assertQuerySizeEventually(
db
.collection('detail2')
.where('masterId', '==', masterId)
.where('detail2Field1', '==', masterField1),
1
);

// Make an irrelevant update
await masterRef.set({ someOtherField: randstr() });

// Ensure prehook is called twice (once for each update)
await assertQuerySizeEventually(
db
.collection('prehooks')
.where(
'message',
'==',
'[788a32e05504] REPLICATE_ATTRIBUTES prehook was called!'
),
2
);
});
});

// Helper functions
function randstr() {
return Math.random().toString(36).substr(2);
}

function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

async function assertQuerySizeEventually(
query,
expectedResultSize,
log = console.log
) {
log(`Asserting query result to have [${expectedResultSize}] entries ... `);
await sleep(1000);
const docs = await new Promise((res) => {
unsubscribe = query.onSnapshot((snap) => {
log(`Current result size: [${snap.size}]`);
if (snap.size === expectedResultSize) {
log('Matched!');
unsubscribe();
res(snap.docs);
}
});
});
return docs;
}
8 changes: 5 additions & 3 deletions test/run-tests.sh
Expand Up @@ -9,6 +9,8 @@ rm -rf ../.nyc_output ../coverage

export GCLOUD_PROJECT=dummy-project
export FIRESTORE_EMULATOR_HOST='localhost:8080'
npx nyc -r html -r text -r lcov firebase emulators:exec \
'mocha --bail --exit --jobs 1 --timeout 30s *.test.js'

: ${MOCHA_TIMEOUT:=30000}
npx \
nyc -r html -r text -r lcov \
firebase emulators:exec --ui \
"mocha --bail --exit --jobs 1 --timeout $MOCHA_TIMEOUT *.test.js"

0 comments on commit 95732ca

Please sign in to comment.