Skip to content

Commit

Permalink
Add missing unit tests for aggregations
Browse files Browse the repository at this point in the history
  • Loading branch information
latonv committed Jan 27, 2023
1 parent 303da79 commit 4431177
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 7 deletions.
39 changes: 32 additions & 7 deletions src/models/aggregation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export enum AggregationSortType {
* Sort ascending alphabetically by key
*/
ALPHABETICAL,
/**
* Sort descending numerically by key
*/
NUMERIC,
}

export interface AggregationOptions {
Expand Down Expand Up @@ -67,30 +71,51 @@ export class Aggregation {
* returned as-is.
*
* @param sortType What to sort the buckets on.
* Accepted values are `AggregationSortType.COUNT` (descending order) and
* `AggregationSortType.ALPHABETICAL` (ascending order).
* Accepted values are:
* - `AggregationSortType.COUNT` (descending order)
* - `AggregationSortType.ALPHABETICAL` (ascending order)
* - `AggregationSortType.NUMERIC` (descending order)
*/
@Memoize()
getSortedBuckets(sortType?: AggregationSortType): Bucket[] | number[] {
// Don't apply sorts to numeric buckets.
const copiedBuckets = [...this.buckets] as Bucket[] | number[];

// Don't apply sorts to number[] aggregations (like year_histogram).
// Note this _doesn't_ apply to ordinary year aggregations, which have
// keyed buckets just like most other facet types.
// Assumption here is that all the buckets have the same type as the
// first bucket (which should be true in principle).
if (typeof this.buckets[0] === 'number') {
return [...(this.buckets as number[])];
if (this.isRawNumberBuckets(copiedBuckets)) {
return copiedBuckets;
}

// Default locale & collation options
const collator = new Intl.Collator();

switch (sortType) {
case AggregationSortType.ALPHABETICAL:
return [...(this.buckets as Bucket[])].sort((a, b) => {
return copiedBuckets.sort((a, b) => {
return collator.compare(a.key.toString(), b.key.toString());
});
case AggregationSortType.NUMERIC:
return copiedBuckets.sort((a, b) => {
return Number(b.key) - Number(a.key);
});
case AggregationSortType.COUNT:
default:
// Sorted by count by default
return [...(this.buckets as Bucket[])];
return copiedBuckets;
}
}

/**
* Type guard for number[] buckets, since the buckets provided by the PPS
* may be either keyed objects or just an array of numbers. Currently only
* `year_histogram` facets are of the latter type.
*/
private isRawNumberBuckets(
buckets: Bucket[] | number[]
): buckets is number[] {
return typeof this.buckets[0] === 'number';
}
}
1 change: 1 addition & 0 deletions src/responses/search-request-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export interface SearchRequestParams {
sort?: string[];
aggregations?: string[];
aggregations_size?: number;
uid?: string;
}
101 changes: 101 additions & 0 deletions test/models/aggregation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { expect } from '@open-wc/testing';
import {
Aggregation,
AggregationSortType,
Bucket,
} from '../../src/models/aggregation';

describe('Aggregation model', () => {
it('constructs with options', () => {
const buckets = [1, 2, 3, 4];
const doc_count_error_upper_bound = 10;
const sum_other_doc_count = 20;
const first_bucket_key = 0;
const last_bucket_key = 3;
const number_buckets = 4;
const interval = 1;

const agg = new Aggregation({
buckets,
doc_count_error_upper_bound,
sum_other_doc_count,
first_bucket_key,
last_bucket_key,
number_buckets,
interval,
});

expect(agg.buckets).to.equal(buckets);
expect(agg.doc_count_error_upper_bound).to.equal(
doc_count_error_upper_bound
);
expect(agg.sum_other_doc_count).to.equal(sum_other_doc_count);
expect(agg.first_bucket_key).to.equal(first_bucket_key);
expect(agg.last_bucket_key).to.equal(last_bucket_key);
expect(agg.number_buckets).to.equal(number_buckets);
expect(agg.interval).to.equal(interval);
});

it('expects default sorted buckets by count', async () => {
const buckets: Bucket[] = [
{ key: 'a', doc_count: 5 },
{ key: 'e', doc_count: 4 },
{ key: 'b', doc_count: 3 },
{ key: 'c', doc_count: 2 },
{ key: 'd', doc_count: 1 },
];
const agg = new Aggregation({ buckets });

expect(agg.getSortedBuckets(AggregationSortType.COUNT)).to.deep.equal(
buckets
);
});

it('sorts buckets alphabetically', async () => {
const buckets: Bucket[] = [
{ key: 'e', doc_count: 4 },
{ key: 'c', doc_count: 2 },
{ key: 'b', doc_count: 3 },
{ key: 'd', doc_count: 1 },
{ key: 'a', doc_count: 5 },
];
const agg = new Aggregation({ buckets });

expect(
agg.getSortedBuckets(AggregationSortType.ALPHABETICAL)
).to.deep.equal([
{ key: 'a', doc_count: 5 },
{ key: 'b', doc_count: 3 },
{ key: 'c', doc_count: 2 },
{ key: 'd', doc_count: 1 },
{ key: 'e', doc_count: 4 },
]);
});

it('sorts buckets numerically', async () => {
const buckets: Bucket[] = [
{ key: 400, doc_count: 4 },
{ key: 1999, doc_count: 2 },
{ key: 1001, doc_count: 3 },
{ key: 1900, doc_count: 1 },
{ key: 2005, doc_count: 5 },
];
const agg = new Aggregation({ buckets });

expect(agg.getSortedBuckets(AggregationSortType.NUMERIC)).to.deep.equal([
{ key: 2005, doc_count: 5 },
{ key: 1999, doc_count: 2 },
{ key: 1900, doc_count: 1 },
{ key: 1001, doc_count: 3 },
{ key: 400, doc_count: 4 },
]);
});

it('does not sort raw number buckets', async () => {
const buckets: number[] = [3, 5, 2, 4, 1];
const agg = new Aggregation({ buckets });
expect(agg.getSortedBuckets(AggregationSortType.COUNT)).to.deep.equal(
buckets
);
});
});

0 comments on commit 4431177

Please sign in to comment.