Skip to content

Commit

Permalink
Merge pull request #1015 from US-Trustee-Program/CAMS-442-test-coverage
Browse files Browse the repository at this point in the history
CAMS-442 test coverage
  • Loading branch information
btposey authored Nov 8, 2024
2 parents ff59b5d + 0ce6dcb commit e4353a0
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 86 deletions.
47 changes: 47 additions & 0 deletions backend/functions/azure/functions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { azureToCamsHttpRequest, toAzureSuccess } from './functions';
import { HttpRequest, HttpResponseInit } from '@azure/functions';
import { CamsHttpRequest } from '../lib/adapters/types/http';
import { CamsHttpResponseInit } from '../lib/adapters/utils/http-response';

describe('functions test', () => {
test('should return properly formatted CamsHttpRequest from malformed headers and query', async () => {
const request = {
method: 'GET',
url: '/test',
query: 'bar',
params: { arg1: 'hello' },
} as unknown as HttpRequest;

const expected: CamsHttpRequest = {
method: 'GET',
url: '/test',
headers: {},
query: {},
params: { arg1: 'hello' },
body: undefined,
};

const response = await azureToCamsHttpRequest(request);
expect(response).toEqual(expected);
});

test('should return empty Azure response init', () => {
const responseInit = toAzureSuccess();
expect(responseInit).toEqual({});
});

test('should return Azure response init', () => {
const camsResponseInit: CamsHttpResponseInit<{ prop1: boolean }> = {
headers: { foo: 'bar' },
statusCode: 200,
body: { data: { prop1: true } },
};
const expected: HttpResponseInit = {
headers: { foo: 'bar' },
status: 200,
jsonBody: { data: { prop1: true } },
};
const responseInit = toAzureSuccess(camsResponseInit);
expect(responseInit).toEqual(expected);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ describe('offices repo', () => {
...session.user,
ttl,
});

const insertOneSpy = jest
.spyOn(MongoCollectionAdapter.prototype, 'insertOne')
const replaceOneSpy = jest
.spyOn(MongoCollectionAdapter.prototype, 'replaceOne')
.mockResolvedValue('inserted-id');

await repo.putOfficeStaff(officeCode, session.user);
expect(insertOneSpy).toHaveBeenCalledWith({ ...staff, updatedOn: expect.anything() });
expect(replaceOneSpy).toHaveBeenCalledWith(expect.anything(), staff, true);
});

describe('error handling', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ export class OfficesMongoRepository extends BaseMongoRepository implements Offic
...user,
ttl,
});
const query = QueryBuilder.build(
and(equals<string>('id', staff.id), equals<string>('officeCode', officeCode)),
);
try {
await this.getAdapter<OfficeStaff>().insertOne(staff);
await this.getAdapter<OfficeStaff>().replaceOne(query, staff, true);
} catch (originalError) {
throw getCamsError(originalError, MODULE_NAME);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
TransferOrderAction,
} from '../../../../../../common/src/cams/orders';
import { ApplicationContext } from '../../types/basic';
import { NotFoundError } from '../../../common-errors/not-found-error';
import { OrdersRepository } from '../../../use-cases/gateways.types';
import QueryBuilder, { ConditionOrConjunction } from '../../../query/query-builder';
import { getCamsError } from '../../../common-errors/error-utilities';
Expand Down Expand Up @@ -51,9 +50,6 @@ export class OrdersMongoRepository extends BaseMongoRepository implements Orders
const adapter = this.getAdapter<TransferOrder>();
const { docketSuggestedCaseNumber: _docketSuggestedCaseNumber, ...existingOrder } =
(await adapter.findOne(query)) as TransferOrder;
if (!existingOrder) {
throw new NotFoundError(MODULE_NAME, { message: `Order not found with id ${data.id}` });
}
const { id: _id, orderType: _orderType, caseId: _caseId, ...mutableProperties } = data;
const updatedOrder = {
...existingOrder,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { CamsError } from '../../../../common-errors/cams-error';
import { NotFoundError } from '../../../../common-errors/not-found-error';
import { UnknownError } from '../../../../common-errors/unknown-error';
import { CollectionHumble } from '../../../../humble-objects/mongo-humble';
import { CollectionHumble, DocumentClient } from '../../../../humble-objects/mongo-humble';
import QueryBuilder from '../../../../query/query-builder';
import { MongoCollectionAdapter } from './mongo-adapter';
import { MongoCollectionAdapter, removeIds } from './mongo-adapter';

const { and, orderBy } = QueryBuilder;

Expand All @@ -29,7 +29,11 @@ const spies = {
countDocuments,
};

type TestType = object;
type TestType = {
_id?: unknown;
id?: string;
foo?: string;
};

describe('Mongo adapter', () => {
const testQuery = QueryBuilder.build(and());
Expand All @@ -40,13 +44,37 @@ describe('Mongo adapter', () => {
jest.resetAllMocks();
});

test('should return an instance of the adapter from newAdapter', () => {
const mockClient: DocumentClient = {
database: () => {
return {
collection: <_t>() => {},
};
},
} as unknown as DocumentClient;
const adapter = MongoCollectionAdapter.newAdapter<TestType>(
'module',
'collection',
'database',
mockClient,
);
expect(adapter).toBeInstanceOf(MongoCollectionAdapter);
});

test('should return items from a getAll', async () => {
find.mockResolvedValue([{}, {}, {}]);
const item = await adapter.getAll();
expect(item).toEqual([{}, {}, {}]);
expect(find).toHaveBeenCalled();
});

// TODO: maybe remove this?
test('should remove Ids from an item', async () => {
const expectedItem = { arbitraryValue: 'arbitrary-value' };
const item = { _id: 'some_id', id: 'someId', ...expectedItem };
expect(removeIds(item)).toEqual(expectedItem);
});

test('should return a sorted list of items from a getAll', async () => {
function* generator() {
yield Promise.resolve({});
Expand Down Expand Up @@ -101,24 +129,77 @@ describe('Mongo adapter', () => {
);
});

test('should return a single Id from a replaceOne', async () => {
const id = '123456';
replaceOne.mockResolvedValue({ acknowdledged: true, upsertedId: id });
const result = await adapter.replaceOne(testQuery, {});
expect(result).toEqual(id);
test('should return a single Id from replaceOne', async () => {
const testObject: TestType = { id: '12345', foo: 'bar' };
const _id = 'mongoGeneratedId';
replaceOne.mockResolvedValue({
acknowledged: true,
matchedCount: 1,
modifiedCount: 1,
upsertedId: _id,
});
const result = await adapter.replaceOne(testQuery, testObject);
expect(result).not.toEqual(_id);
expect(result).toEqual(testObject.id);
});

test('should throw an error calling replaceOne for a nonexistant record and upsert=false', async () => {
const testObject: TestType = { id: '12345', foo: 'bar' };
replaceOne.mockResolvedValue({
acknowledged: false,
matchedCount: 0,
modifiedCount: 0,
upsertedId: null,
});
await expect(adapter.replaceOne(testQuery, testObject)).rejects.toThrow(
'No matching item found.',
);
});

test('should return a single Id from replaceOne when upsert = true', async () => {
const testObject: TestType = { id: '12345', foo: 'bar' };
const _id = 'mongoGeneratedId';

replaceOne.mockResolvedValue({
acknowledged: true,
matchedCount: 0,
modifiedCount: 1,
upsertedId: _id,
});
const result = await adapter.replaceOne(testQuery, testObject, true);
expect(result).toEqual(testObject.id);
expect(result).not.toEqual(_id);
});

test('should throw an error if replaceOne does not match.', async () => {
const testObject: TestType = { id: '12345', foo: 'bar' };
replaceOne.mockResolvedValue({
acknowledged: false,
matchedCount: 0,
modifiedCount: 0,
upsertedId: null,
});
await expect(adapter.replaceOne(testQuery, testObject, true)).rejects.toThrow(
'Failed to insert document into database.',
);
});

test('should return a single Id from insertOne', async () => {
const id = '123456';
insertOne.mockResolvedValue({ acknowdledged: true, insertedId: id });
insertOne.mockResolvedValue({ acknowledged: true, insertedId: id });
const result = await adapter.insertOne({});
expect(result.split('-').length).toEqual(5);
});

test('should throw an error if insertOne does not insert.', async () => {
insertOne.mockResolvedValue({ acknowledged: false });
await expect(adapter.insertOne({})).rejects.toThrow('Failed to insert document into database.');
});

test('should return a list of Ids from insertMany', async () => {
const ids = ['0', '1', '2', '3', '4'];
insertMany.mockResolvedValue({
acknowdledged: true,
acknowledged: true,
insertedIds: ids,
insertedCount: ids.length,
});
Expand All @@ -127,7 +208,7 @@ describe('Mongo adapter', () => {
});

test('should return a count of 1 for 1 item deleted', async () => {
deleteOne.mockResolvedValue({ acknowdledged: true, deletedCount: 1 });
deleteOne.mockResolvedValue({ acknowledged: true, deletedCount: 1 });
const result = await adapter.deleteOne(testQuery);
expect(result).toEqual(1);
});
Expand All @@ -140,7 +221,7 @@ describe('Mongo adapter', () => {
});

test('should return a count of 5 for 5 items deleted', async () => {
deleteMany.mockResolvedValue({ acknowdledged: true, deletedCount: 5 });
deleteMany.mockResolvedValue({ acknowledged: true, deletedCount: 5 });
const result = await adapter.deleteMany(testQuery);
expect(result).toEqual(5);
});
Expand All @@ -158,8 +239,15 @@ describe('Mongo adapter', () => {
expect(result).toEqual(5);
});

test('should return a count of 6 when countAllDocuments is called and there are 6 documents', async () => {
countDocuments.mockResolvedValue(6);
const result = await adapter.countAllDocuments();
expect(result).toEqual(6);
});

test('should throw CamsError when some but not all items are inserted', async () => {
insertMany.mockResolvedValue({
acknowledged: true,
insertedIds: {
one: 'one',
two: 'two',
Expand All @@ -176,22 +264,6 @@ describe('Mongo adapter', () => {
expect(async () => await adapter.insertMany([{}, {}, {}, {}])).rejects.toThrow(error);
});

test('should handle acknowledged == false', async () => {
const response = { acknowledged: false };
const error = new UnknownError(MODULE_NAME, {
message: 'Operation returned Not Acknowledged.',
});
Object.values(spies).forEach((spy) => {
spy.mockResolvedValue(response);
});

await expect(adapter.replaceOne(testQuery, {})).rejects.toThrow(error);
await expect(adapter.insertOne({})).rejects.toThrow(error);
await expect(adapter.insertMany([{}])).rejects.toThrow(error);
await expect(adapter.deleteOne(testQuery)).rejects.toThrow(error);
await expect(adapter.deleteMany(testQuery)).rejects.toThrow(error);
});

test('should handle errors', async () => {
const originalError = new Error('Test Exception');
const expectedError = new UnknownError(MODULE_NAME, { originalError });
Expand All @@ -206,6 +278,8 @@ describe('Mongo adapter', () => {
await expect(adapter.deleteMany(testQuery)).rejects.toThrow(expectedError);
await expect(adapter.find(testQuery)).rejects.toThrow(expectedError);
await expect(adapter.countDocuments(testQuery)).rejects.toThrow(expectedError);
await expect(adapter.countAllDocuments()).rejects.toThrow(expectedError);
await expect(adapter.findOne(testQuery)).rejects.toThrow(expectedError);
await expect(adapter.getAll()).rejects.toThrow(expectedError);
});
});
Loading

0 comments on commit e4353a0

Please sign in to comment.