Skip to content

Commit

Permalink
test: getAggregateFromServer()
Browse files Browse the repository at this point in the history
  • Loading branch information
russellwheatley committed Nov 6, 2024
1 parent 7f01f41 commit 8203f96
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 2 deletions.
161 changes: 161 additions & 0 deletions packages/firestore/e2e/Aggregate/AggregateQuery.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright (c) 2022-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
const COLLECTION = 'firestore';
const { wipe } = require('../helpers');
describe('getAggregateFromServer()', function () {
before(function () {
return wipe();
});

it('throws if incorrect `query` argument', function () {
const { getAggregateFromServer, count } = firestoreModular;
const aggregateSpec = {
count: count(),
};
try {
getAggregateFromServer(null, aggregateSpec);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'getAggregateFromServer(*, aggregateSpec)` `query` muse be an instance of `FirestoreQuery`',
);
}

try {
getAggregateFromServer(undefined, aggregateSpec);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'getAggregateFromServer(*, aggregateSpec)` `query` muse be an instance of `FirestoreQuery`',
);
}

try {
getAggregateFromServer('some-string', aggregateSpec);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'getAggregateFromServer(*, aggregateSpec)` `query` muse be an instance of `FirestoreQuery`',
);
}
return Promise.resolve();
});

it('throws if incorrect `aggregateSpec` argument', function () {
const { getAggregateFromServer, collection, getFirestore, count } = firestoreModular;

const colRef = collection(getFirestore(), `firestore`);

try {
getAggregateFromServer(colRef, 'not an object');
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'`getAggregateFromServer(query, *)` `aggregateSpec` muse be an object',
);
}

const aggregateSpec = {
count: "doesn't contain an aggregate field",
};

try {
getAggregateFromServer(colRef, aggregateSpec);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'`getAggregateFromServer(query, *)` `aggregateSpec` must contain at least one `AggregateField`',
);
}

try {
getAggregateFromServer(colRef, aggregateSpec);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql(
'getAggregateFromServer(*, aggregateSpec)` `query` muse be an instance of `FirestoreQuery`',
);
}
const aggField = count();
aggField.aggregateType = 'change underlying type';

const aggregateSpec2 = {
count: aggField,
};

try {
getAggregateFromServer(colRef, aggregateSpec2);
return Promise.reject(new Error('Did not throw an Error.'));
} catch (error) {
error.message.should.containEql("'AggregateField' has an an unknown 'AggregateType'");
}
return Promise.resolve();
});

it('count(), average() & sum()', async function () {
const { getAggregateFromServer, doc, setDoc, collection, getFirestore, count, average, sum } =
firestoreModular;
const firestore = getFirestore();

const colRef = collection(firestore, `${COLLECTION}/aggregate-count/collection`);

await Promise.all([
setDoc(doc(colRef, 'one'), { bar: 5, baz: 4 }),
setDoc(doc(colRef, 'two'), { bar: 5, baz: 4 }),
setDoc(doc(colRef, 'three'), { bar: 5, baz: 4 }),
]);

const aggregateSpec = {
ignoreThisProperty: 'not aggregate field',
countCollection: count(),
averageBar: average('bar'),
sumBaz: sum('baz'),
averageNonExisting: average('not-a-property'),
sumNotExisting: sum('not-a-property'),
};

const result = await getAggregateFromServer(colRef, aggregateSpec);

const data = result.data();

data.countCollection.should.eql(3);
data.averageBar.should.eql(5);
data.sumBaz.should.eql(12);
// should only return the aggregate field requests
data.should.not.have.property('ignoreThisProperty');
// average returns null on non-property
data.averageNonExisting.should.eql(null);
// sum returns 0 on non-property
data.sumNotExisting.should.eql(0);

const colRefNoDocs = collection(firestore, `${COLLECTION}/aggregate-count/no-docs`);

const aggregateSpecNoDocuments = {
countCollection: count(),
averageBar: average('bar'),
sumBaz: sum('baz'),
};

const resultNoDocs = await getAggregateFromServer(colRefNoDocs, aggregateSpecNoDocuments);

const dataNoDocs = resultNoDocs.data();

dataNoDocs.countCollection.should.eql(0);
dataNoDocs.averageBar.should.eql(null);
dataNoDocs.sumBaz.should.eql(0);
});
});
25 changes: 23 additions & 2 deletions packages/firestore/lib/modular/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
*/

import { firebase } from '../index';
import { isObject } from '@react-native-firebase/app/lib/common';
import {
FirestoreAggregateQuerySnapshot,
AggregateField,
AggregateType,
fieldPathFromArgument,
} from '../FirestoreAggregate';
import FirestoreQuery from '../FirestoreQuery';

/**
* @param {FirebaseApp?} app
Expand Down Expand Up @@ -199,11 +201,30 @@ export function getCountFromServer(query) {
}

export async function getAggregateFromServer(query, aggregateSpec) {

Check warning on line 203 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L203

Added line #L203 was not covered by tests
if (!(query instanceof FirestoreQuery)) {
throw new Error(

Check warning on line 205 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L205

Added line #L205 was not covered by tests
'`getAggregateFromServer(*, aggregateSpec)` `query` muse be an instance of `FirestoreQuery`',
);
}

if (!isObject(aggregateSpec)) {
throw new Error('`getAggregateFromServer(query, *)` `aggregateSpec` muse be an object');
} else {
const containsOneAggregateField = Object.values(aggregateSpec).find(
value => value instanceof AggregateField,

Check warning on line 214 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L211-L214

Added lines #L211 - L214 were not covered by tests
);

if (!containsOneAggregateField) {
throw new Error(

Check warning on line 218 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L218

Added line #L218 was not covered by tests
'`getAggregateFromServer(query, *)` `aggregateSpec` must contain at least one `AggregateField`',
);
}
}
const aggregateQueries = [];
for (const key in aggregateSpec) {

Check warning on line 224 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L223-L224

Added lines #L223 - L224 were not covered by tests
if (aggregateSpec.hasOwnProperty(key)) {
const aggregateField = aggregateSpec[key];

Check warning on line 226 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L226

Added line #L226 was not covered by tests

// we ignore any fields that are not `AggregateField`
if (aggregateField instanceof AggregateField) {
switch (aggregateField.aggregateType) {
case AggregateType.AVG:
Expand All @@ -218,7 +239,7 @@ export async function getAggregateFromServer(query, aggregateSpec) {
break;
default:
throw new Error(

Check warning on line 241 in packages/firestore/lib/modular/index.js

View check run for this annotation

Codecov / codecov/patch

packages/firestore/lib/modular/index.js#L238-L241

Added lines #L238 - L241 were not covered by tests
`"AggregateField" has an an unknown "AggregateType" : ${aggregateField.aggregateType}`,
`'AggregateField' has an an unknown 'AggregateType' : ${aggregateField.aggregateType}`,
);
}
}
Expand Down

0 comments on commit 8203f96

Please sign in to comment.