From 75c782b0c548ce756e3d33cd43387d5094b8551b Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 15:52:02 +0200 Subject: [PATCH 1/9] Reproduce problem --- test/collateral/harness.defaults.json | 6 ++++++ ...ct-summary.js => contact-summary.templated.js} | 1 + test/contact-summary.spec.js | 15 +++++++++++++++ 3 files changed, 22 insertions(+) rename test/collateral/project-with-source/{contact-summary.js => contact-summary.templated.js} (89%) diff --git a/test/collateral/harness.defaults.json b/test/collateral/harness.defaults.json index 3c801c0..38b3458 100644 --- a/test/collateral/harness.defaults.json +++ b/test/collateral/harness.defaults.json @@ -88,6 +88,12 @@ } }, + { + "_id": "supervisor_area_id", + "name": "Supervisor", + "type": "district_hospital" + }, + { "_id": "family_head_id", "name": "CHP Area 001 Contact", diff --git a/test/collateral/project-with-source/contact-summary.js b/test/collateral/project-with-source/contact-summary.templated.js similarity index 89% rename from test/collateral/project-with-source/contact-summary.js rename to test/collateral/project-with-source/contact-summary.templated.js index 7c2467e..a622325 100644 --- a/test/collateral/project-with-source/contact-summary.js +++ b/test/collateral/project-with-source/contact-summary.templated.js @@ -2,6 +2,7 @@ const context = { hasPermissions: cht.v1.hasPermissions('chw_permission'), hasAnyPermission: cht.v1.hasAnyPermission([['chw_permission']]), chtApiAnalyticsTargets: cht.v1.analytics && cht.v1.analytics.getTargetDocs(), + reportCount: reports?.length, }; module.exports = { diff --git a/test/contact-summary.spec.js b/test/contact-summary.spec.js index f049f9e..04bee40 100644 --- a/test/contact-summary.spec.js +++ b/test/contact-summary.spec.js @@ -184,5 +184,20 @@ describe('cht.v1 in contact summary ', () => { const targetFromDocs = contactSummary.context.chtApiAnalyticsTargets.map(t => t.targets[0]); expect(targetFromDocs).to.deep.eq(targets); }); + + it('#272 - reports of places children should not appear when child is also a place', async () => { + harness.pushMockedDoc({ + type: 'data_record', + form: 'abc', + reported_date: 1000, + fields: { + place_id: 'chw_area_id', + sp_count: '15' + } + }); + + const cs = await harness.getContactSummary('supervisor_area_id'); + expect(cs.context.reportCount).to.deep.eq(0); + }); }); From 0478cc125d9c911da8fc0cca106998f324f9f75a Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 16:01:14 +0200 Subject: [PATCH 2/9] Fix --- src/core-adapter.js | 6 +++++- test/contact-summary.spec.js | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core-adapter.js b/src/core-adapter.js index 1231a34..2a88b75 100644 --- a/src/core-adapter.js +++ b/src/core-adapter.js @@ -78,7 +78,11 @@ class CoreAdapter { } const contactDocs = [contact, ...state.contacts]; - const relevantContactDocs = contactDocs.filter(contact => contact?._id === contactId || contact?.parent?._id === contactId); + const relevantContactDocs = contactDocs.filter(contact => { + const isSelf = contact?._id === contactId; + const isChild = contact?.parent?._id === contactId; + return isSelf || (isChild && this.core.ContactTypesUtils.isPerson(this.appSettings, contact)); + }); const subjectIds = _.flatten(relevantContactDocs.map(contact => this.core.RegistrationUtils.getSubjectIds(contact))); const reportHasMatchingSubject = report => subjectIds.includes(this.core.RegistrationUtils.getSubjectId(report)); diff --git a/test/contact-summary.spec.js b/test/contact-summary.spec.js index 04bee40..e8e7158 100644 --- a/test/contact-summary.spec.js +++ b/test/contact-summary.spec.js @@ -192,12 +192,11 @@ describe('cht.v1 in contact summary ', () => { reported_date: 1000, fields: { place_id: 'chw_area_id', - sp_count: '15' } }); - const cs = await harness.getContactSummary('supervisor_area_id'); - expect(cs.context.reportCount).to.deep.eq(0); + const contactSummary = await harness.getContactSummary('supervisor_area_id'); + expect(contactSummary.context.reportCount).to.eq(0); }); }); From f6f38b7b3cf44b72437e62547822f6e9359729a6 Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 16:02:04 +0200 Subject: [PATCH 3/9] Bump --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 28ff81b..1cc6c19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cht-conf-test-harness", - "version": "5.0.2", + "version": "5.0.3", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index e6e1170..4be6196 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cht-conf-test-harness", - "version": "5.0.2", + "version": "5.0.3", "description": "Test Framework for CHT Projects", "repository": { "type": "git", From 4efe30a32595406e826eff4d8ec6bdd5b355f1e0 Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 16:04:18 +0200 Subject: [PATCH 4/9] Fix lint failure --- test/collateral/project-with-source/.eslintrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/collateral/project-with-source/.eslintrc b/test/collateral/project-with-source/.eslintrc index fdc1778..ba0392d 100644 --- a/test/collateral/project-with-source/.eslintrc +++ b/test/collateral/project-with-source/.eslintrc @@ -9,6 +9,7 @@ "globals": { "cht": true, "Utils": true, - "user": true + "user": true, + "reports": true } } \ No newline at end of file From 8c9ba4cd1b3042988f20b05dc8dd71f326d17dab Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 16:11:08 +0200 Subject: [PATCH 5/9] Tests passing --- test/collateral/project-with-source/app_settings.json | 2 +- .../project-with-source/contact-summary.templated.js | 2 +- test/contact-summary.spec.js | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/collateral/project-with-source/app_settings.json b/test/collateral/project-with-source/app_settings.json index 1389b0f..7ab9830 100644 --- a/test/collateral/project-with-source/app_settings.json +++ b/test/collateral/project-with-source/app_settings.json @@ -4,7 +4,7 @@ "chw_role" ] }, - "contact_summary": "var ContactSummary = {}; !function(e,t){if('object'==typeof exports&&'object'==typeof module)module.exports=t();else if('function'==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)('object'==typeof exports?exports:e)[r]=n[r]}}(ContactSummary,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&'object'==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,'default',{enumerable:!0,value:e}),2&t&&'string'!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,'a',t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p='',n(n.s=0)}([function(e,t){const n={hasPermissions:cht.v1.hasPermissions('chw_permission'),hasAnyPermission:cht.v1.hasAnyPermission([['chw_permission']]),chtApiAnalyticsTargets:cht.v1.analytics&&cht.v1.analytics.getTargetDocs()};e.exports={context:n}}])})); return ContactSummary;", + "contact_summary": "var ContactSummary = {}; !function(e,t){if('object'==typeof exports&&'object'==typeof module)module.exports=t();else if('function'==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)('object'==typeof exports?exports:e)[r]=n[r]}}(ContactSummary,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&'object'==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,'default',{enumerable:!0,value:e}),2&t&&'string'!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,'a',t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p='',n(n.s=0)}([function(e,t,n){var r=n(1),o=n(2);e.exports=o(r,contact,reports)},function(e,t){const n={hasPermissions:cht.v1.hasPermissions('chw_permission'),hasAnyPermission:cht.v1.hasAnyPermission([['chw_permission']]),chtApiAnalyticsTargets:cht.v1.analytics&&cht.v1.analytics.getTargetDocs(),reportCount:reports.length};e.exports={context:n}},function(e,t){function n(e){return e?Array.isArray(e)?e:[e]:[]}function r(e,t){switch(typeof e){case'undefined':return!0;case'function':return e(t);default:return e}}function o(e,t,n){if(r(e.appliesIf,n)){var o='function'==typeof e.fields?e.fields(n):e.fields.filter((function(e){return r(e.appliesIf,n)})).map((function(e){var t={};return i(e,t,'label'),i(e,t,'value'),i(e,t,'translate'),i(e,t,'filter'),i(e,t,'width'),i(e,t,'icon'),e.context&&(t.context={},i(e.context,t.context,'count'),i(e.context,t.context,'total')),t}));return e.modifyContext&&e.modifyContext(t,n),{label:e.label,fields:o}}function i(e,t,r){switch(typeof e[r]){case'undefined':return;case'function':t[r]=e[r](n);break;default:t[r]=e[r]}}}e.exports=function(e,t,r){var i=e.fields||[],c=e.context||{},u=e.cards||[],f=t&&('contact'===t.type?t.contact_type:t.type),s={cards:[],fields:i.filter((function(e){var t=n(e.appliesToType),r=t.filter((function(e){return e&&'!'===e.charAt(0)}));if((0===t.length||t.includes(f)||r.length>0&&!r.includes('!'+f))&&(!e.appliesIf||e.appliesIf()))return delete e.appliesToType,delete e.appliesIf,!0}))};return u.forEach((function(e){var t,i,u,a,l=n(e.appliesToType);if(l.includes('report')&&l.length>1)throw new Error('You cannot set appliesToType to an array which includes the type \\'report\\' and another type.');if(l.includes('report'))for(t=0;t0)return;(u=o(e,c))&&s.cards.push(u)}})),s.context=c,s}}])})); return ContactSummary;", "tasks": { "rules": "!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&'object'==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,'default',{enumerable:!0,value:e}),2&t&&'string'!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,'a',t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p='',n(n.s=1)}([function(e,t){e.exports=function(e){var t={};!function e(t,n){var o=Object.keys(t);for(var r in o){var a=o[r];switch(typeof t[a]){case'object':e(t[a],n);break;case'function':t[a]=t[a].bind(n)}}}(e,t),t.definition=function e(t){var n=Object.assign({},t),o=Object.keys(n);for(var r in o){var a=o[r];if(Array.isArray(n[a])){n[a]=n[a].slice(0);for(var i=0;i({name:'cht.api.'+e,title:'cht.api.'+e,appliesTo:'contacts',appliesIf:()=>'undefined'!=typeof cht?cht.v1.hasPermissions(e):void 0,actions:[{form:'assessment'}],events:[{dueDate:()=>Utils.now(),start:1,end:1}]});e.exports=[n('chw_permission'),n('permission_dne')]},function(e,t){e.exports=[{id:'cht.api',type:'count',goal:-1,appliesTo:'contacts',appliesToType:['health_center'],appliesIf:()=>'undefined'!=typeof cht?cht.v1.hasPermissions('chw_permission'):void 0,date:'now'}]},function(e,t,n){var o=n(0),r=n(5);function a(e,t,n,o,r,a){var i;if(e.appliesToType){var c;if('contacts'===e.appliesTo){if(!r.contact)return;c='contact'===r.contact.type?r.contact.contact_type:r.contact.type}else{if(!a)return;c=a.form}if(-1===e.appliesToType.indexOf(c))return}if('scheduled_tasks'===e.appliesTo||!e.appliesIf||e.appliesIf(r,a))if('scheduled_tasks'===e.appliesTo){if(a&&e.appliesIf){if(!a.scheduled_tasks)return;for(i=0;i { expect(args[2][1]).to.deep.contain({ _id: 'chw_area_id', }); - expect(args[2][2]).to.be.undefined; + expect(args[2][2]).to.deep.contain({ + _id: 'supervisor_area_id', + }); + expect(args[2][3]).to.be.undefined; })); it('#240 - contact summary includes reports of the selected contacts children', withFunctionStub(async () => { From 8d53edd3119770c6d3977c9abc288b71e5b2f82f Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 23:04:14 +0200 Subject: [PATCH 6/9] Fix? --- .github/workflows/run-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-build.yml b/.github/workflows/run-build.yml index 92f5125..99b2855 100644 --- a/.github/workflows/run-build.yml +++ b/.github/workflows/run-build.yml @@ -8,7 +8,7 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 defaults: run: From 8a270f9a3745b13afddc7292ecbbd42c4e41f5c7 Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 23:08:23 +0200 Subject: [PATCH 7/9] Fix? --- .github/workflows/run-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-build.yml b/.github/workflows/run-build.yml index 99b2855..cb180f4 100644 --- a/.github/workflows/run-build.yml +++ b/.github/workflows/run-build.yml @@ -8,7 +8,7 @@ on: jobs: test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest defaults: run: @@ -25,4 +25,5 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: npm ci --legacy-peer-deps + - run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - run: ./build.sh --force From eb842d43dafad9068e521dba64940f8f7fcb8119 Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 23:26:25 +0200 Subject: [PATCH 8/9] Fix? --- .github/workflows/run-build.yml | 1 - .github/workflows/run-ci-scripts.yml | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-build.yml b/.github/workflows/run-build.yml index cb180f4..92f5125 100644 --- a/.github/workflows/run-build.yml +++ b/.github/workflows/run-build.yml @@ -25,5 +25,4 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: npm ci --legacy-peer-deps - - run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - run: ./build.sh --force diff --git a/.github/workflows/run-ci-scripts.yml b/.github/workflows/run-ci-scripts.yml index 0c3a889..f6eb683 100644 --- a/.github/workflows/run-ci-scripts.yml +++ b/.github/workflows/run-ci-scripts.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [20.x] steps: - uses: actions/checkout@v2 @@ -26,4 +26,5 @@ jobs: node-version: ${{ matrix.node-version }} - run: sudo apt install -y xsltproc - run: npm ci --legacy-peer-deps + - run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - run: npm run git-ci From 010ba6f4d27095e5e5fb222d6557ed07d31fe6ab Mon Sep 17 00:00:00 2001 From: kennsippell Date: Tue, 18 Feb 2025 23:35:18 +0200 Subject: [PATCH 9/9] 2nd test --- test/collateral/harness.defaults.json | 11 ++++++++++- test/contact-summary.spec.js | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/test/collateral/harness.defaults.json b/test/collateral/harness.defaults.json index 38b3458..669b991 100644 --- a/test/collateral/harness.defaults.json +++ b/test/collateral/harness.defaults.json @@ -90,10 +90,19 @@ { "_id": "supervisor_area_id", - "name": "Supervisor", + "name": "Supervisor Area", "type": "district_hospital" }, + { + "_id": "supervisor_id", + "name": "Supervisor", + "type": "person", + "parent": { + "_id": "supervisor_area_id" + } + }, + { "_id": "family_head_id", "name": "CHP Area 001 Contact", diff --git a/test/contact-summary.spec.js b/test/contact-summary.spec.js index 9d4d322..247f820 100644 --- a/test/contact-summary.spec.js +++ b/test/contact-summary.spec.js @@ -136,7 +136,7 @@ describe('getContactSummary', () => { }); }); -describe('cht.v1 in contact summary ', () => { +describe('using project-with-source', () => { const harness = new Harness({ directory: path.join(__dirname, 'collateral', 'project-with-source'), harnessDataPath: path.join(__dirname, 'collateral', 'harness.defaults.json'), @@ -188,7 +188,7 @@ describe('cht.v1 in contact summary ', () => { expect(targetFromDocs).to.deep.eq(targets); }); - it('#272 - reports of places children should not appear when child is also a place', async () => { + it('#272 - reports of a place with place-child not visible', async () => { harness.pushMockedDoc({ type: 'data_record', form: 'abc', @@ -201,5 +201,19 @@ describe('cht.v1 in contact summary ', () => { const contactSummary = await harness.getContactSummary('supervisor_area_id'); expect(contactSummary.context.reportCount).to.eq(0); }); + + it('#272 - reports of a place with person-child is visible', async () => { + harness.pushMockedDoc({ + type: 'data_record', + form: 'abc', + reported_date: 1000, + fields: { + patient_uuid: 'supervisor_id', + } + }); + + const contactSummary = await harness.getContactSummary('supervisor_area_id'); + expect(contactSummary.context.reportCount).to.eq(1); + }); });