Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(9586): implement freetext search in cht datasource #9625

Open
wants to merge 73 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
ac0ab67
Initial setup
sugat009 Nov 6, 2024
cd11adc
add /api/v1/contacts/:uuid endpoint
sugat009 Nov 7, 2024
b7c5d1f
add /api/v1/contact/:uuid?with_lineage=<option> endpoint
sugat009 Nov 7, 2024
f91e393
add missing files
sugat009 Nov 7, 2024
52ac11b
add missing files
sugat009 Nov 7, 2024
c1b68cf
add endpoint /api/v1/report
sugat009 Nov 8, 2024
45c0ccf
add additional checks for report validity
sugat009 Nov 11, 2024
acf903a
add /api/contact/id endpoint (not tested yet)
sugat009 Nov 12, 2024
89927b1
add endpoint /api/v1/report/id --untested
sugat009 Nov 13, 2024
45abf58
implement search feature in /api/contact/id endpoint
sugat009 Nov 15, 2024
6f5c326
add search functionality to /api/report/id endpoint
sugat009 Nov 15, 2024
192af16
add async API Contact.v1.getIdsAll
sugat009 Nov 15, 2024
bb98dcf
add async API Report.v1.getIds
sugat009 Nov 15, 2024
43efbef
add JSDocs for functions
sugat009 Nov 18, 2024
ede85fd
Merge remote-tracking branch 'origin/master' into 9586-implement-free…
sugat009 Nov 18, 2024
2b33c07
add unit tests for index.ts, qualifier.ts and contact.ts
sugat009 Nov 20, 2024
3bfcace
add unit tests for report.ts
sugat009 Nov 20, 2024
074b0c1
add tests for local/contact.js
sugat009 Nov 25, 2024
1907907
add some additional tests in local/contact.spec.ts
sugat009 Nov 25, 2024
a629116
add tests for local/report.ts
sugat009 Nov 25, 2024
c45cee8
add unit tests for remote/contact.ts
sugat009 Nov 25, 2024
5400736
add unit tests for remote/report.ts
sugat009 Nov 25, 2024
bf46e4a
add unit tests for contact-types.ts
sugat009 Nov 25, 2024
b1cf669
remove unused variables
sugat009 Nov 25, 2024
98fd4e2
add unit tests for api/src/controllers/contact.js
sugat009 Nov 26, 2024
ee32262
add tests for api/src/controllers/report.js
sugat009 Nov 26, 2024
b5bc6e6
Merge remote-tracking branch 'origin/master' into 9586-implement-free…
sugat009 Nov 27, 2024
4a18fc8
Merge remote-tracking branch 'origin/master' into 9586-implement-free…
sugat009 Nov 27, 2024
eba1b61
add integration test for api/src/controller/contact.js
sugat009 Nov 29, 2024
9157059
add integration tests for api/src/controllers/report.js
sugat009 Nov 29, 2024
d5fed9c
fix eslint issues
sugat009 Nov 29, 2024
30d058e
changes missed during copy-paste
sugat009 Dec 2, 2024
662598c
change title of tests
sugat009 Dec 2, 2024
89eb816
fix indentation
sugat009 Dec 2, 2024
3ea31ef
fix max-line 120 issue
sugat009 Dec 2, 2024
a7a9272
rename getIdsAll functions to getIds
sugat009 Dec 3, 2024
ef8b93f
add tests in controller unit tests for when limit is undefined or null
sugat009 Dec 3, 2024
43c3896
add page limits and end of alphabet marker to separate constants file
sugat009 Dec 4, 2024
f97f928
add function in qualifier.ts to check for key-value based freetext qu…
sugat009 Dec 4, 2024
2065125
separate out the endpoints integration tests and cht-datasource integ…
sugat009 Dec 5, 2024
f8087b9
remove unused variables
sugat009 Dec 5, 2024
e6aea4f
move src/constants.ts to src/libs/constants.ts
sugat009 Dec 5, 2024
c21e52a
change limit to number and stringified number in cht-datasource
sugat009 Dec 6, 2024
c487a7e
Update shared-libs/cht-datasource/src/qualifier.ts
sugat009 Dec 23, 2024
ce1013a
Update shared-libs/cht-datasource/test/contact.spec.ts
sugat009 Dec 23, 2024
19143b4
Update shared-libs/cht-datasource/src/remote/contact.ts
sugat009 Dec 24, 2024
8dc7de3
addressing PR review comments
sugat009 Dec 24, 2024
91a0125
Merge branch '9586-implement-freetext-search-in-cht-datasource' of gi…
sugat009 Dec 24, 2024
49553b7
address most of the comments
sugat009 Dec 30, 2024
22da4b9
fix integration tests
sugat009 Dec 30, 2024
4a0d2bb
fix api unit tests
sugat009 Dec 31, 2024
bfa0a57
refactor getWithLineage contacts logic
sugat009 Jan 3, 2025
eab5877
listen to eslint
sugat009 Jan 3, 2025
1cca39c
complete a round of feedbacks
sugat009 Jan 7, 2025
abff459
remove assertions in afterEach
sugat009 Jan 8, 2025
9673d78
almost done
sugat009 Jan 9, 2025
6f1280a
implement getDocUUids functions
sugat009 Jan 10, 2025
a79d93f
Merge remote-tracking branch 'origin/master' into 9586-implement-free…
sugat009 Jan 10, 2025
be48c13
fix some stuff
sugat009 Jan 10, 2025
e523a25
add temp auth setters in cht-datasource specific integration tests
sugat009 Jan 17, 2025
d4bc934
feat: refactor contact code to remove contact-types.ts (#9753)
jkuester Jan 27, 2025
783d9d6
Update shared-libs/cht-datasource/src/contact.ts
sugat009 Jan 27, 2025
d7f8ca1
Update shared-libs/cht-datasource/src/contact.ts
sugat009 Jan 27, 2025
9fc41d9
Update shared-libs/cht-datasource/src/qualifier.ts
sugat009 Jan 28, 2025
423ee0a
Update shared-libs/cht-datasource/src/qualifier.ts
sugat009 Jan 28, 2025
2641477
qualifier.ts changes
sugat009 Jan 28, 2025
faac438
Merge branch '9586-implement-freetext-search-in-cht-datasource' of gi…
sugat009 Jan 28, 2025
6878952
Update shared-libs/cht-datasource/src/local/libs/doc.ts
sugat009 Jan 29, 2025
70e0db5
Update shared-libs/cht-datasource/src/local/libs/doc.ts
sugat009 Jan 29, 2025
f8c7be5
Update shared-libs/cht-datasource/src/local/libs/doc.ts
sugat009 Jan 29, 2025
760e916
feedback implementation
sugat009 Jan 29, 2025
91ef121
Merge branch '9586-implement-freetext-search-in-cht-datasource' of gi…
sugat009 Jan 29, 2025
bac5e2c
remove unused imports
sugat009 Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/src/controllers/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const ctx = require('../services/data-context');
const serverUtils = require('../server-utils');

const getContact = ({ with_lineage }) => ctx.bind(with_lineage === 'true' ? Contact.v1.getWithLineage : Contact.v1.get);
const getContactIds = () => ctx.bind(Contact.v1.getIdsPage);
const getContactIds = () => ctx.bind(Contact.v1.getUuidsPage);

const checkUserPermissions = async (req) => {
const userCtx = await auth.getUserCtx(req);
Expand All @@ -26,7 +26,7 @@ module.exports = {

return res.json(contact);
}),
getIds: serverUtils.doOrError(async (req, res) => {
getUuids: serverUtils.doOrError(async (req, res) => {
await checkUserPermissions(req);

if (!req.query.freetext && !req.query.type) {
Expand Down
4 changes: 2 additions & 2 deletions api/src/controllers/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const serverUtils = require('../server-utils');
const { Report, Qualifier } = require('@medic/cht-datasource');

const getReport = () => ctx.bind(Report.v1.get);
const getReportIds = () => ctx.bind(Report.v1.getIdsPage);
const getReportIds = () => ctx.bind(Report.v1.getUuidsPage);

const checkUserPermissions = async (req) => {
const userCtx = await auth.getUserCtx(req);
Expand All @@ -26,7 +26,7 @@ module.exports = {

return res.json(report);
}),
getIds: serverUtils.doOrError(async (req, res) => {
getUuids: serverUtils.doOrError(async (req, res) => {
await checkUserPermissions(req);

const qualifier = Qualifier.byFreetext(req.query.freetext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So ... this endpoint .. if it doesn't get neither a freetext query param or a limit query param, it will end up returning ALL reports?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope. it returns a 400 - Bad request error because freetext is required whereas limit is set to a default of 10000.
image

Expand Down
4 changes: 2 additions & 2 deletions api/src/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,10 +494,10 @@ app.postJson('/api/v1/people', function(req, res) {
app.get('/api/v1/person', person.v1.getAll);
app.get('/api/v1/person/:uuid', person.v1.get);

app.get('/api/v1/contact/id', contact.v1.getIds);
app.get('/api/v1/contact/uuid', contact.v1.getUuids);
app.get('/api/v1/contact/:uuid', contact.v1.get);

app.get('/api/v1/report/id', report.v1.getIds);
app.get('/api/v1/report/uuid', report.v1.getUuids);
app.get('/api/v1/report/:uuid', report.v1.get);

app.postJson('/api/v1/bulk-delete', bulkDocs.bulkDelete);
Expand Down
130 changes: 77 additions & 53 deletions api/tests/mocha/controllers/contact.spec.js

Large diffs are not rendered by default.

32 changes: 22 additions & 10 deletions api/tests/mocha/controllers/person.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ describe('Person Controller', () => {
.returns(personGetWithLineage);
});

afterEach(() => {
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a person', async () => {
isOnlineOnly.returns(true);
hasAllPermissions.returns(true);
Expand All @@ -70,6 +65,8 @@ describe('Person Controller', () => {
expect(personGetWithLineage.notCalled).to.be.true;
expect(res.json.calledOnceWithExactly(person)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a person with lineage when the query parameter is set to "true"', async () => {
Expand All @@ -87,6 +84,8 @@ describe('Person Controller', () => {
expect(personGetWithLineage.calledOnceWithExactly(Qualifier.byUuid(req.params.uuid))).to.be.true;
expect(res.json.calledOnceWithExactly(person)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a person without lineage when the query parameter is set something else', async () => {
Expand All @@ -104,6 +103,8 @@ describe('Person Controller', () => {
expect(personGetWithLineage.notCalled).to.be.true;
expect(res.json.calledOnceWithExactly(person)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a 404 error if person is not found', async () => {
Expand All @@ -123,6 +124,8 @@ describe('Person Controller', () => {
req,
res
)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if user does not have can_view_contacts permission', async () => {
Expand All @@ -138,6 +141,8 @@ describe('Person Controller', () => {
expect(personGetWithLineage.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if not an online user', async () => {
Expand All @@ -152,6 +157,8 @@ describe('Person Controller', () => {
expect(personGetWithLineage.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});
});

Expand Down Expand Up @@ -180,11 +187,6 @@ describe('Person Controller', () => {
qualifierByContactType.returns(personTypeQualifier);
});

afterEach(() => {
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a page of people with correct query params', async () => {
isOnlineOnly.returns(true);
hasAllPermissions.returns(true);
Expand All @@ -198,6 +200,8 @@ describe('Person Controller', () => {
expect(personGetPageByType.calledOnceWithExactly(personTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.calledOnceWithExactly(people)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if user does not have can_view_contacts permission', async () => {
Expand All @@ -213,6 +217,8 @@ describe('Person Controller', () => {
expect(personGetPageByType.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if not an online user', async () => {
Expand All @@ -227,6 +233,8 @@ describe('Person Controller', () => {
expect(personGetPageByType.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns 400 error when personType is invalid', async () => {
Expand All @@ -243,6 +251,8 @@ describe('Person Controller', () => {
expect(personGetPageByType.calledOnceWithExactly(personTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(err, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('rethrows error in case of other errors', async () => {
Expand All @@ -259,6 +269,8 @@ describe('Person Controller', () => {
expect(personGetPageByType.calledOnceWithExactly(personTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(err, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});
});
});
Expand Down
32 changes: 22 additions & 10 deletions api/tests/mocha/controllers/place.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ describe('Place Controller', () => {
.returns(placeGetWithLineage);
});

afterEach(() => {
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a place', async () => {
isOnlineOnly.returns(true);
hasAllPermissions.returns(true);
Expand All @@ -70,6 +65,8 @@ describe('Place Controller', () => {
expect(placeGetWithLineage.notCalled).to.be.true;
expect(res.json.calledOnceWithExactly(place)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a place with lineage when the query parameter is set to "true"', async () => {
Expand All @@ -87,6 +84,8 @@ describe('Place Controller', () => {
expect(placeGetWithLineage.calledOnceWithExactly(Qualifier.byUuid(req.params.uuid))).to.be.true;
expect(res.json.calledOnceWithExactly(place)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a place without lineage when the query parameter is set something else', async () => {
Expand All @@ -104,6 +103,8 @@ describe('Place Controller', () => {
expect(placeGetWithLineage.notCalled).to.be.true;
expect(res.json.calledOnceWithExactly(place)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a 404 error if place is not found', async () => {
Expand All @@ -123,6 +124,8 @@ describe('Place Controller', () => {
req,
res
)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if user does not have can_view_contacts permission', async () => {
Expand All @@ -138,6 +141,8 @@ describe('Place Controller', () => {
expect(placeGetWithLineage.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if not an online user', async () => {
Expand All @@ -152,6 +157,8 @@ describe('Place Controller', () => {
expect(placeGetWithLineage.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});
});

Expand Down Expand Up @@ -180,11 +187,6 @@ describe('Place Controller', () => {
qualifierByContactType.returns(placeTypeQualifier);
});

afterEach(() => {
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns a page of places with correct query params', async () => {
isOnlineOnly.returns(true);
hasAllPermissions.returns(true);
Expand All @@ -198,6 +200,8 @@ describe('Place Controller', () => {
expect(placeGetPageByType.calledOnceWithExactly(placeTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.calledOnceWithExactly(places)).to.be.true;
expect(serverUtilsError.notCalled).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if user does not have can_view_contacts permission', async () => {
Expand All @@ -213,6 +217,8 @@ describe('Place Controller', () => {
expect(placeGetPageByType.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns error if not an online user', async () => {
Expand All @@ -227,6 +233,8 @@ describe('Place Controller', () => {
expect(placeGetPageByType.notCalled).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(error, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('returns 400 error when placeType is invalid', async () => {
Expand All @@ -243,6 +251,8 @@ describe('Place Controller', () => {
expect(placeGetPageByType.calledOnceWithExactly(placeTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(err, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});

it('rethrows error in case of other errors', async () => {
Expand All @@ -259,6 +269,8 @@ describe('Place Controller', () => {
expect(placeGetPageByType.calledOnceWithExactly(placeTypeQualifier, cursor, limit)).to.be.true;
expect(res.json.notCalled).to.be.true;
expect(serverUtilsError.calledOnceWithExactly(err, req, res)).to.be.true;
expect(getUserCtx.calledOnceWithExactly(req)).to.be.true;
expect(isOnlineOnly.calledOnceWithExactly(userCtx)).to.be.true;
});
});
});
Expand Down
Loading
Loading