From c9a7dc657c76a6c05bbb2927f182c229686382b1 Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 1 Oct 2024 17:51:23 +0100 Subject: [PATCH 1/6] Add unit test for stock out --- src/add-feature.js | 10 ++- src/features/stock-out.js | 34 ++++++++- test/mocks/mocks.js | 44 ++++++++++++ test/stock-out.spec.js | 147 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 test/stock-out.spec.js diff --git a/src/add-feature.js b/src/add-feature.js index 8819ffc..cbbfeae 100644 --- a/src/add-feature.js +++ b/src/add-feature.js @@ -44,7 +44,15 @@ async function selectFeature(configs) { choices: remainingFeatures.map((ft) => ({ name: FEATURES[ft], value: ft, - })) + })), + when: function (answers){ + const argv = process.argv; + if (!argv[4]){ + return true; + } + answers.name = argv[4]; + return false; + } } ]); diff --git a/src/features/stock-out.js b/src/features/stock-out.js index 88ec7a4..477d9d1 100644 --- a/src/features/stock-out.js +++ b/src/features/stock-out.js @@ -263,7 +263,15 @@ async function getStockOutConfigs({ type: 'input', name: 'form_name', message: 'Enter stock out form ID', - default: 'stock_out' + default: 'stock_out', + when: function (answers){ + const argv = process.argv; + if (!argv[5]){ + return true; + } + answers.form_name = argv[5]; + return false; + } }, { type: 'list', @@ -279,12 +287,34 @@ async function getStockOutConfigs({ value: 'weekly_qty' } ], + when: function (answers){ + const argv = process.argv; + if (!argv[6]){ + return true; + } + answers.formular = argv[6]; + return false; + } }, ...languages.map((language) => ({ type: 'input', name: `title.${language}`, message: `Enter stock out form title in ${language}`, - default: 'Stock Out' + default: 'Stock Out', + when: function (answers){ + const argv = process.argv; + if (!argv[7]){ + return true; + } + const answer = { + title:{ + 'en': argv[7].split(',')[0], + 'fr': argv[7].split(',')[1] + } + }; + Object.assign(answers, answer); + return false; + } })) ]); return configs; diff --git a/test/mocks/mocks.js b/test/mocks/mocks.js index e1c41e6..df4ad7b 100644 --- a/test/mocks/mocks.js +++ b/test/mocks/mocks.js @@ -41,6 +41,50 @@ module.exports = { 'paracetamol___count' ] + }, + + stockOutScenario: { + initScenario: [ + 'init', + '2_levels', + 'c62_chw', + 'chw', + 'c52_supervisor', + 'supervisor', + 'Y', + 'stock_count', + '[{contact_type: \'c62_chw\', role: \'chw\', place_type: \'c60_chw_site\' },{contact_type: \'c52_supervisor\',role: \'supervisor\',place_type: \'c50_supervision_area\'}]', + 'action', + 'end_of_week', + ['Stock count', 'Stock count'], + 'patient_assessment_under_5', + 'Y', + 'now()', + 'malaria', + ['Category', 'Categorie'], + ['Category', 'Categorie'], + 'paracetamol', + ['Paracetamol', 'Paracetamole'], + 'Y', + ['Box of 8', 'Boite de 8'], + 8, + ['Tablet', 'Comprimes'], + 20, + 15, + 15, + 'by_user', + 0, + ], + addStockOutFeatureScenario: [ + 'add', 'feature', 'stock_out', 'stock_out', 'item_danger_qty', ['Stock Out', 'Stock Out'] + ], + productsScenario: [ + 'paracetamol_at_hand___set', + 'paracetamol_at_hand___unit', + 'paracetamol_required___set', + 'paracetamol_required___unit' + ] + } }; diff --git a/test/stock-out.spec.js b/test/stock-out.spec.js new file mode 100644 index 0000000..cac2d2d --- /dev/null +++ b/test/stock-out.spec.js @@ -0,0 +1,147 @@ +const { spawnSync } = require('child_process'); +const path = require('path'); +const fs = require('fs-extra'); +//const { once } = require('events'); +const ExcelJS = require('exceljs'); + +const { stockOutScenario, stockCountScenario } = require('./mocks/mocks'); +const { + setDirToprojectConfig, + revertBackToProjectHome +} = require('./test-utils'); + + +describe('Stock out', () => { + const workingDir = process.cwd(); + + beforeEach(() => { + revertBackToProjectHome(workingDir); + setDirToprojectConfig(); + }); + + afterEach(async() => { + revertBackToProjectHome(workingDir); + }); + + it('Add stock out summaries test', async() => { + const processDir = process.cwd(); + const workbook = new ExcelJS.Workbook(); + const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); + + if(childProcess.status === 0) { + // Check that stock monitoring is initialized and stock count and stock out xform and properties files are generated + //const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); + + const formFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); + for(const formFile of formFiles){ + if(formFile.toString().includes('stock_count') || formFile.toString().includes('stock_out')){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); + } + } + + expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); + + // Check that the products are available in stock count xform + const productCategoryList = stockCountScenario.productCategoryScenario; + const productsList = stockCountScenario.productsScenario; + await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_count.xlsx`)); + const surveyWorkSheet = workbook.getWorksheet('survey'); + const nameCol = surveyWorkSheet.getColumn('B'); + const cellProductCategoriesList = []; + const cellProductsList = []; + let productIndex = 0; + let productCatIndex =0; + nameCol.eachCell(function(cell){ + + if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ + cellProductCategoriesList.push(cell.value); + productCatIndex ++; + productIndex = 0; + } + + if(cell.value === productsList[productIndex] && productIndex < productsList.length){ + cellProductsList.push(cell.value); + productIndex ++; + } + + }); + + expect(productsList.length).toBe(cellProductsList.length); + expect(productsList.entries).toStrictEqual(cellProductsList.entries); + + expect(productCategoryList.length).toBe(cellProductCategoriesList.length); + expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); + + // Add stock out feature test + const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); + if(stockOutChildProcess.status === 0){ + const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); + for(const formFile of stockOutFormFiles){ + if(formFile.toString().includes('stock_out')){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); + } + } + + // Check that the products are available in stock out xform + const stockOutProductsList = stockOutScenario.productsScenario; + await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_out.xlsx`)); + const surveyWorkSheet = workbook.getWorksheet('survey'); + const nameCol = surveyWorkSheet.getColumn('B'); + const stockOutCellProductsList = []; + productIndex = 0; + nameCol.eachCell(function(cell){ + if(cell.value === stockOutProductsList[productIndex] && productIndex < stockOutProductsList.length){ + stockOutCellProductsList.push(cell.value); + productIndex ++; + } + }); + + expect(stockOutProductsList.length).toBe(stockOutCellProductsList.length); + expect(stockOutProductsList.entries).toStrictEqual(stockOutCellProductsList.entries); + + } + + const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); + + for(const formFile of stockOutFormFiles){ + if(formFile.toString().includes('stock_out') || formFile.toString().includes('stock_count')){ + expect(fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile))).toBe(undefined); + } + } + + // Removing the stock monitoring init file and stock count file + const stockMonitoringInitPath = path.join(processDir, 'stock-monitoring.config.json'); + //const stockMonitoringInitFile = fs.stat + fs.stat(stockMonitoringInitPath, (error) => { + if (error) { + //console.log(error); + } + else { + expect(fs.unlinkSync(stockMonitoringInitPath)).toBe(undefined); + //console.log(stats); + } + }); + + const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); + for(const translationFile of translationFiles){ + + const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); + expect(messageFileContent).not.toBe(''); + const newMessageContent = messageFileContent.split('\n').map(message => { + if(!message.toString().includes('cht-stock-monitoring-workflow') && message.toString()!==''){ + return `${message.toString()}\n`; + } + }); + + expect(newMessageContent.includes('cht-stock-monitoring-workflow')).toBe(false); + fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); + fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); + } + + } + + }); + +}); + + From 69f6cb96ec8368f616db4044b4d84a3635270fad Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 22 Oct 2024 01:40:32 +0100 Subject: [PATCH 2/6] fix: review feedback and added unit test stock out --- package.json | 2 +- test/mocks/mocks.js | 88 ++++ .../translations/messages-en.properties | 339 +------------ .../translations/messages-fr.properties | 474 +----------------- test/stock-out-feature.spec.js | 84 ++++ ....spec.js => stock-out-integration.spec.js} | 71 +-- test/test-utils.js | 36 +- 7 files changed, 239 insertions(+), 855 deletions(-) create mode 100644 test/stock-out-feature.spec.js rename test/{stock-out.spec.js => stock-out-integration.spec.js} (57%) diff --git a/package.json b/package.json index 0ffb483..2c61c67 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "scripts": { "cz": "cz", - "test": "jest", + "test": "jest --testTimeout=25000", "semantic-release": "semantic-release", "prepare": "husky" }, diff --git a/test/mocks/mocks.js b/test/mocks/mocks.js index df4ad7b..2cb7183 100644 --- a/test/mocks/mocks.js +++ b/test/mocks/mocks.js @@ -1,4 +1,92 @@ module.exports = { + mockConfigs: { + features: { + stock_count: { + form_name: 'stock_count', + contact_types: [ + { + contact_type: 'c62_chw', + role: 'chw', + place_type: 'c60_chw_site' + }, + { + contact_type: 'c52_supervisor', + role: 'supervisor', + place_type: 'c50_supervision_area' + } + ], + type: 'action', + title: { + en: 'Stock count', + fr: 'Stock count' + } + }, + stock_out: { + form_name: 'stock_out', + formular: 'item_danger_qty', + title: { + en: 'Stock Out Title', + fr: 'Titre du Stock' + }, + }, + }, + levels: { + 1: { + contact_type: 'c62_chw', + role: 'chw', + place_type: 'c62_chw_site' + }, + 2: { + contact_type: 'c52_supervisor', + role: 'supervisor', + place_type: 'c50_supervision_area' + }, + }, + languages: ['en', 'fr'], + items: { + paracetamol: { + name: 'paracetamol', + label: { + en: 'Paracetamol', + fr: 'Paracetamole' + }, + isInSet: 'Y', + set: { + label: { + en: 'Box of 8', + fr: 'Boite de 8' + }, + count: '8' + }, + unit: { + label: { + en: 'Tablet', + fr: 'Comprimes' + } + }, + warning_total: '20', + danger_total: '15', + max_total: '15', + category: 'malaria' + } + }, + categories: { + malaria: { + name: 'malaria', + label: { + fr: 'Categorie' + }, + description: { + fr: 'Categorie' + } + } + }, + useItemCategory: true, + defaultLanguage: 'fr', + version: '1.1.3', + last_update_date: '2024-10-21T11:09:33.013Z' + }, + stockCountScenario: { initScenario: [ 'init', diff --git a/test/project-config/translations/messages-en.properties b/test/project-config/translations/messages-en.properties index 5479131..7dbbdf2 100644 --- a/test/project-config/translations/messages-en.properties +++ b/test/project-config/translations/messages-en.properties @@ -1,332 +1,7 @@ -contact.type.c10_central = Central level -contact.type.c10_central.plural = Central levels -contact.type.c10_central.new = New central level -contact.type.c10_central.edit = Edit central level -contact.type.c20_region = Region -contact.type.c20_region.plural = Regions -contact.type.c20_region.new = New region -contact.type.c20_region.edit = Edit region -contact.type.c30_district = District -contact.type.c30_district.plural = Districts -contact.type.c30_district.new = New district -contact.type.c30_district.edit = Edit district -contact.type.c40_health_area = Health Area -contact.type.c40_health_area.plural = Health Area -contact.type.c40_health_area.new = New Health Area -contact.type.c40_health_area.edit = Edit Health Area -contact.type.c50_supervision_area = Supervision area -contact.type.c50_supervision_area.edit = Edit supervision area -contact.type.c50_supervision_area.new = New supervision area -contact.type.c50_supervision_area.plural = Supervision area -contact.type.c60_chw_site = CHW Site -contact.type.c60_chw_site.edit = Edit CHW site -contact.type.c60_chw_site.new = New CHW site -contact.type.c60_chw_site.plural = CHW Sites -contact.type.c70_village = Village -contact.type.c70_village.edit = Edit village -contact.type.c70_village.new = New village -contact.type.c70_village.plural = Villages -contact.type.c80_concession = Concession -contact.type.c80_concession.edit = Edit concessions -contact.type.c80_concession.new = New concession -contact.type.c80_concession.plural = Concessions -contact.type.c90_household = Household -contact.type.c90_household.plural = Household -contact.type.c90_household.new = New household -contact.type.c90_household.edit = Edit household -contact.type.person = Person -contact.type.person.edit = Edit person -contact.type.person.new = New person -contact.type.person.plural = Persons -contact.type.c12_central = Person -contact.type.c12_central.edit = Edit person -contact.type.c12_central.new = New person -contact.type.c12_central.plural = Persons -contact.type.c22_region = Person -contact.type.c22_region.edit = Edit person -contact.type.c22_region.new = New person -contact.type.c22_region.plural = Persons -contact.type.c32_district = Person -contact.type.c32_district.edit = Edit person -contact.type.c32_district.new = New person -contact.type.c32_district.plural = Persons -contact.type.c42_health_area = Person -contact.type.c42_health_area.edit = Edit person -contact.type.c42_health_area.new = New person -contact.type.c42_health_area.plural = Persons -contact.type.c52_supervisor = Person -contact.type.c52_supervisor.edit = Edit person -contact.type.c52_supervisor.new = New person -contact.type.c52_supervisor.plural = Persons -contact.type.c62_chw = Person -contact.type.c62_chw.edit = Edit person -contact.type.c62_chw.new = New person -contact.type.c62_chw.plural = Persons -contact.type.c72_village = Person -contact.type.c72_village.edit = Edit person -contact.type.c72_village.new = New person -contact.type.c72_village.plural = Persons -contact.type.c82_concession = Person -contact.type.c82_concession.edit = Edit person -contact.type.c82_concession.new = New person -contact.type.c82_concession.plural = Persons -contact.type.c92_household = Person -contact.type.c92_household.edit = Edit person -contact.type.c92_household.new = New person -contact.type.c92_household.plural = Household members -contact.type.c74_community_actor = New Community Actor -contact.type.c74_community_actor.edit = Edit Community Actor -contact.type.c74_community_actor.new = New Community Actor -contact.type.c74_community_actor.plural = New Community Actors -contact.sex.male = Male -contact.sex.female = Female -contact.sex. = Undefined -person.field.telephone = phone -contact.pregnancy.lmp = Day of last menstruations -contact.pregnancy.estimated_delivery = Estimated delivery -contact.pregnancy.type = Type of pregnancy -contact.pregnancy.high_risk = High risque -contact.pregnancy.not_high_risk = No risque -contact-prgnancy-activity = Pregnacy Active -task.pregnancy_confirmation = Pregnancy Confirmation -task.child_longitudinal_followup_1_24 = Child Longitudinal Followup 1 to 24 month -task.child_longitudinal_followup_2_5 = Child Longitudinal Followup 2 to 5 years -task.child_longitudinal_followup_6_12 = Child Longitudinal Followup 6 to 12 years -task.child_longitudinal_followup_13_19 = Child Longitudinal Followup 13 to 19 years -task.newborn_registration = Newborn Registration -task.mother_referral_followup = Mother Referral Followup -task.cpon_realisation = Home birth reference -task.postnatal_followup = Postnatal Followup -task.treatment_followup_under_5 = Treatment Followup less than 5 years -task.referral_followup_under_5 = Referral Followup less than 5 years -task.treatment_referral_followup_under_5 = Follow-up Treatment after Referral less than 5 years -task.mas_followup_under_5 = MAS less than 5 years -task.mam_followup_under_5 = MAM less than 5 years -task.vaccine_followup_under_5 = Vaccine Followup less than 5 years -task.treatment_followup_multiple = Multiple Treatment Followup -task.treatment_followup_under_5.diarrhea = Diarrhea Treatment Followup -task.treatment_followup_under_5.pneumonia = Pneumonia Treatment Followup -task.treatment_followup_under_5.malaria = Malaria Treatment Followup -contact.delivery.number_pregnancy_confirmed = Pregnancy Confirmed -contact.delivery.number_of_children = Number of Newborn -contact.delivery.delivery_date = Delivery Date -contact.delivery.general = Delivery Details -contact.fp.general = Family Planning -contact.fp.recent_fp_method = Recent FP Method -contact.fp.state = Status -contact.fp.stop = Stop -contact.fp.in_progress = In Progress -task.pregnancy_followup = Pregnancy Followup -task.priority.high = High -enketo.geopicker.latitude = Latitude -enketo.geopicker.longitude = Longitude -enketo.geopicker.altitude = Altitude -enketo.geopicker.accuracy = Accuracy -enketo.geopicker.searchPlaceholder = Search for a place -enketo.selectpicker.noneselected = None -usertype.central_admin = Central Admin -usertype.national_admin = National Admin -usertype.district_admin = District Admin -usertype.dtc = DTC -usertype.supervisor = Supervisor -usertype.chw = CHW -usertype.oca = Other Community Actor -usertype.oca_supervisor = ADC(OCA Coach) -usertype.cvs = CVS -usertype.wash_comity = Wash Comity -usertype.savings = Savings Manager -usertype.manager_stock= Stock Warehouse Manager -vaccine.title = Vaccinations -contact.birth.certificate = Birth Certificate -contact.birth.certificate_number = Birth Certificate Number -contact.birth.certificate_date = Birth Certificate Date -task.overdue = Past due -task.overdue.days = {DAYS plural =0{Due today} =1{Due yesterday} other{Due \# days ago}} -task.days.left = {DAYS plural =1{1 day left} other{# days left}} -task.pregnancy_referral_followup = Pregnancy Referral Followup -task.anc_followup = ANC Visit Realization -task.fp_reference_followup = FP Reference {{contact.name}} -task.fp_renewal_followup = FP Followup -task.treatment_followup_over_5 = Treatment Followup -task.referral_followup_over_5 = Referral Followup over 5 -task.tb_treatment_followup = Weekly Treatment Follow-up TB -sms.token.login.help = Hi ready to start? You will need data and a good connection. Go to https://play.google.com/store/apps/details?id=org.medicmobile.webapp.mobile.moh_mali_chw&hl=en_US to install the app. After the installation click the next link to log in. -task.referral_followup=Referral -task.treatment.malaria=Malaria followup -task.treatment.diarrhea=Diarrhea followup -task.treatment.ari=Pneumonia followup -task.treatment.multiple=Treatment followup -task.treatment.malnutrition=Malnutrition -task.pnc_followup=Postnatal realization -task.anc_supervision_followup=Antenatal realization -task.newborn_followup=Newborn followup -task.prenatal_followup=Prenatal followup -task.supervision_visit_realization=Supervision visit -task.supervision_with_chw_confirmation=Visit with CHW -task.supervision_without_chw_confirmation=Visit without CHW -task.individual_feedback_confirmation=Individual feedback -task.oca_individual_feedback_confirmation = Individual Meeting Realization -task.oca_supervision_visit_realization=Coaching Visit Realization (PC) -task.oca_supervision_visit_scheduling=Coaching visit scheduling (PC) -task.meeting_with_authorities_realization=Meeting with authorities after coaching -task.visit_with_pc_realization=Visit Realization with the PC -task.visit_realisation_without_pc= Visit Realization to households without the PC -task.sebac_alert_sort = Alert sorting -task.sebac_alert_sort_not_done = Alert sorting not done -task.sebac_alert_sort_2 = Alert sorting 2 -task.sebac_alert_verification=Alert Verification -task.sebac_verification_notification=Alert Verification Notification -task.sebac_verification_result=Alert Verification Result -task.sebac_test_result_reminder=Test Result Reminder -task.sebac_result_notification=Test Result Notification -task.sebac_alert_dtc_notification=Alert Notification -target.home_visits=# Home visit -target.2-home-visits-per-fam=% households who received ≥2 VAD -target.chv-receive-supervision-visit=% of CHVs who received a 360 degree supervision visit -target.patient_assessment-24h=% of children <5 years who received care within 24 hours of the onset of illness -target.patient_assessment_over_5-24h=% of children> = 5 years who received care within 24 hours of the beginning of their illness -target.preg-first-trimester=% of pregnancies diagnosed in the first trimester -target.protocol-error-percentage=% of the evaluations without protocol errors -target.protocol-error-count=# total protocol errors -target.danger-signs-without-accompany=Sign(s) of danger without reference or accompaniment to the CSCOM -target.symptoms-of-malaria-without-tdr=Malaria sign TDR malaria not realized -target.fever-without-tdr=Presence of fever RDT malaria not achieved -target.tdr-without-malaria=CTA given by the ASC TDR negative malaria -target.incorrect-dosage-of-act-based-combination=CTA dose given by incorrect ASC -target.diarrhea-without-zinc=Diarrhea without zinc administration -target.incorrect-dosage-of-zinc=Zinc dose given by incorrect ASC -target.pneumonia-without-amoxicillin=Pneumonia without amoxicillin -target.amoxicillin-without-pneumonia=Amoxicillin without pneumonia -target.incorrect-dosage-of-amoxicillin=Amoxicillin dose given by the incorrect ASC -target.muac-yellow-incomplete-drugs=Shakir band in yellow without complete treatment on the first day -target.incorrect-dosage-of-vitamin-a=Vitamin A dose given by the incorrect ASC -target.incorrect-dosage-of-albendazole=Albendazol dose given by incorrect ASC -target.incorrect-dosage-of-paracetamol=Paracetamol dose given by the incorrect ASC -target.no-24h-follow-up=No 24h follow-up -target.no-48h-follow-up=No 48h follow-up -target.no-72h-follow-up=No 72h follow-up -target.no-120h-follow-up=No follow-up of 5th d ay (For IRA or Diarrhea) -target.aggrevated-no-accompany=Aggravated condition at 24H or 48H or 72H or day 5 without reference / accompaniment at the CSCOM -target.unchanged-no-accompany=No change at 48H or 72H or 5th day without reference / accompaniment at the CSCOM -target.not-improved-3d-no-accompany=Not improved or not cured at 72H without reference / accompaniment at the CSCOM -target.not-improved-5d-no-accompany=Not improved or not cured the 5th without reference / accompaniment to the CSCOM -target.chw_observed_during_assessment.title= % of CHW observed by dedicated supervisor during the care of a patient -target.chw_rdts_correctly_carried_out.title= Number of Malaria RDTs correctly carried out by the CHW during supervision -target.chw_rdts_carrying_out_malaria.title= Number CHW observed by the SD for carrying out the Malaria RDT -contact.profile.death.date = Date of death -contact.profile.death.place = Place of death -contact.profile.death.title = Death -contact.profile.value.unknown = Unknown -contact.profile.death.places.village = At the village -contact.profile.death.places.home = At home -contact.profile.death.places.other = Other -contact.profile.death.places.undefined = Unknown -target.childcare_by_chw.title = Number of new curative consultations for children under 5 by CHW -target.childcare_by_chw.fever.title = Number of RDTs performed in children under 5 years old with fever -target.childcare_by_chw.diarrhea.title = Number of children under 5 years old with diarrhea treated with zinc and SRO by CHW -target.childcare_by_chw.pneumonia.title = Number of children under 5 years old with pneumonia treated with Amoxicillin by CHW -target.childcare_by_chw.cough_cold_ari.title = Number of children under 5 years old with Cough/Cold treated by CHW -target.child_uncomplicated_malaria.title = Number of children under 5 years old with uncomplicated malaria confirmed by RDT and treated by CTA by the CHW -target.childcare_by_chw.malnourished.title = Children detected malnourished -target.childcare_by_chw.moderate_acute_malnutrition.title = Number of children under 5 years old with moderate acute malnutrition treated by CHW -target.childcare_by_chw.uncomplicated_severe_malnutrition.title = Number of children under 5 years old with severe acute malnutrition without complications treated with plumpy nut by CHWs -target.uncomplicated_malaria_5_plus.title = Number of children over 5 years old with uncomplicated malaria confirmed by RDT and treated by CTA by CHW -target.pregnant_with_uncomplicated_malaria_rdt_cta.title = Proportion of pregnant women with uncomplicated malaria confirmed by RDT and treated with CTA by CHWs. -target.newborns_followed_first_7_days = Newborns followed within the first 7 days of life -target.newborns_followed_declared = Newborns declared to the civil registry -target.new_fp_user = New FP users in CHW site -target.proportion_with_danger_case = Proportion of cases with a danger or alert sign referred by the CHW -target.proportion_children_fully_vaccinated = Proportion of children from 0 to 23 months fully vaccinated -target.new_patient_followed_by_community_agent = New patients in treatment followed -target.presumptive_tb_followed_by_community_agent = Presumptive TB cases referred -target.home_visit_chw = Total of Home visits -target.chw_talks = Talks made -target.tb_cases_lost = Cases TB of loss of sight -target.household_with_hand_washing = Proportion of households with a hand washing device (functional with water and soap) -target.household_with_improved_latrine = Proportion (Percentage) of households using an improved latrine -target.cvss.household_as_member.title = Number of households joining the CVSS -target.cvss.individual_as_member.title = Number of individual CVSS memberships -target.village_motivation_mecanism.title = Number of CVSS villages with a CHW motivation mechanism -target.village_promotional_activities.title = Number of CVSS villages having supported other health promotion activities -target.cvss.nutritional_demonstration.title = Number of CVSS having supported nutritional demonstrations -target.cvss_total_expense_transportation.title = Amount of expenses on transport (pregnant women and children under five) -target.cvss_total_expense_nd.title = Amount of expenses on nutrition demonstrations -target.cvss_member_total_expense.title = Amount of expenses recorded by CVSS members -target.village_transportation_mecanism.title = Number of villages with transport mechanism -target.fonctional_transportation.title = Number of villages with a functioning transport mechanism -target.cvss.individual_leaving_cvss.title = Number of people who left CVSS fund -target.cvss.household_leaving_cvss.title = Number of households that left CVSS fund -target.cvss_under_5_transported_title = Number of children under 5 transported by the transport mechanism -target.cvss_pregnant_woman_transported_title = Number of pregnant women transported by the transport mechanism -target.cvss_postpartum_woman_transported_title = Number of Postpartum women transported by the transport mechanism -target.cvss_average_contribution.title = Average contribution of health solidarity funds for the period -target.cvss.cvss_total_contribution.title = Total Contribution -target.cvss.cvss_donation_diaspora.title = Amount mobilized from the diaspora -target.cvss.cvss_donation_private_sector.title = Amount mobilized from the private sector -target.chw_helped_in_nature_by_community.title = Number of CHWs having received in nature support -target.chw_financially_helpedby_community.title = Number of CHWs having received motivation from CVSS -target.rdts_carried_out_5_plus_with_fever.title = Number of RDTs performed in those over 5 years old with fever -target.number_of_traitments_followup_carried_out.title = Number of follow-up treatment carried out PEC of cases by CHW -target.chw_site_visited_in_community_without_chw.title = % CHW site visited in community without CHW -target.chw_having_had_an_individual_meeting_with_the_supervisor.title = % Of CHWs having had an individual meeting with the supervisor -target.percentage_chw_received_visit_sd.title = % of CHWs having received a dedicated supervision visit with all steps -target.number_of_children_zero_doses.title = Number of children (0 to 23 months) with 0 doses -target.number_of_children_vaccination_not_up_to_date.title = Number of children (0 to 23 months) with vaccination not up to date -contact.savings.title = CVSS Group Contact Card -contact.savings.manager.name = CVSS Manager's name -contact.savings.cvss_balance = Available Balance -contact.savings.manager.phone = Manager Phone number -contact.savings.total_members = Total number of CVSS members -contact.savings.total_amount_contributed = Total amount contributed -contact.savings.total_loan_disbursed = Loan disbursed -contact.savings.total_loan_paid = Loan Imbursed -contact.savings.loan_balance = Loan balance -contact.savings.total_expenses = Total expenses -contact.savings.total_disbursement = Total Amount Disbursed -contact.savings.beneficiary.title = Beneficiary Contact Card -contact.savings.beneficiary.total_contribution = Total contribution Record -contact.savings.beneficiary.total_expense = Total Expense Record -contact.savings.total_loan = Total Loan -contact.savings.beneficiary.loan_balance = Total Loan Balance -task.savings.loan_reminder = Loan Reminder -task.savings.confirmation_of_expenditure = Confirmation of expenditure -task.savings.loan_reimbursement = Loan Reimbursement -target.home_visit_gsan = Proportion of home visits made -target.gsan_affected_men = Men affected -target.gsan_affected_women = Women affected -target.gsan_affected_men_chat = Men reached during educational talks -target.gsan_affected_women_chat = Women reached during educational talks -target.gsan_chat_proportion = Proportion of talks carried out -target.gsan_affected_men_genre = Men sensitized on the gender approach -target.gsan_affected_women_genre = Women sensitized on the gender approach -target.chw_promo_pregnancy = Home visits made for promotional activities + follow-up of the pregnant woman -target.curative_home_visits = Home visits made for curative activities -vaccine.status.no_dose = Zero Dose -vaccine.status.full_dose = Complet -vaccine.status.partial_dose = Incomplet -child.civil_status = Civil status -child.civil_status.declared = Declared child -child.civil_status.not_declared = Not declared child -child.schooling = Schooling -child.schooling.not_schooled = Not schooled -child.schooling.schooled = Schooled -child.schooling.waiting = Waiting -reports.sidebar.filter.title = Filter -reports.sidebar.filter.form_type = Form Type -reports.sidebar.filter.place = Place -reports.sidebar.filter.date = Date -reports.sidebar.filter.status = Status -search_bar.filter.label = Filter -fast_action_button.title = New -contact.child.mother.indicator.title = Child and mother's indicators -contact.child.mother.indicator.pregnant_from_15_49 = Number of pregnant women from 15-49 years old -contact.child.mother.indicator.health_facility.delivery = Number of pregnant women who gave birth in a health facility -contact.child.mother.indicator.exclusive.breastfeeding = Number of children under 6 months exclusively breastfed -contact.child.mother.indicator.no.vaccine = Number of children who have not received any vaccine -contact.child.mother.indicator.fully.immunized = Number of children fully immunized -contact.child.mother.indicator.early.learning = Number of children aged 2-5 years who have benefited from early learning -contact.child.mother.indicator.improved.latrine = Number of households with improved latrine -contact.child.mother.indicator.potable.water = Number of households with access to drinking water -contact.child.mother.indicator.cash.transfert = Number of households that have benefited from cash transfers -contact.child.mother.indicator.sexual.mutilation = Number of children with sexual mutilations -contact.child.mother.indicator.malnutrition = Number of children aged 6-59 months having been screened for malnutrition in a household +cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamol +cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock out +cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock at hand: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock required: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.summary_header = Summary +cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} has low stock of the following items +cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock out diff --git a/test/project-config/translations/messages-fr.properties b/test/project-config/translations/messages-fr.properties index 7031adb..8fe99db 100644 --- a/test/project-config/translations/messages-fr.properties +++ b/test/project-config/translations/messages-fr.properties @@ -1,467 +1,7 @@ -contact.type.c10_central = Niveau Central -contact.type.c10_central.plural = Niveaux Centraux -contact.type.c10_central.new = Ajouter niveau central -contact.type.c10_central.edit = Modifier niveau central -contact.type.c20_region = Région -contact.type.c20_region.plural = Régions -contact.type.c20_region.new = Ajouter région -contact.type.c20_region.edit = Modifier région -contact.type.c30_district = District -contact.type.c30_district.plural = Districts -contact.type.c30_district.new = Ajouter district -contact.type.c30_district.edit = Modifier district -contact.type.c40_health_area = Aire de santé -contact.type.c40_health_area.plural = Aires de santé -contact.type.c40_health_area.new = Ajouter Aire de santé -contact.type.c40_health_area.edit = Modifier Aire de santé -contact.type.c50_supervision_area = Zone de Supervision -contact.type.c50_supervision_area.edit = Modifier zone de supervision -contact.type.c50_supervision_area.new = Nouvelle zone du supervision -contact.type.c50_supervision_area.plural = Zones de Supervision -contact.type.c60_chw_site = Site ASC -contact.type.c60_chw_site.edit = Modifier site ASC -contact.type.c60_chw_site.new = Nouveau site ASC -contact.type.c60_chw_site.plural = Sites ASC -contact.type.c70_village = Village -contact.type.c70_village.edit = Modifier Village -contact.type.c70_village.new = Nouveau Village -contact.type.c70_village.plural = Villages -contact.type.c80_concession = Concession -contact.type.c80_concession.edit = Modifier Concession -contact.type.c80_concession.new = Nouvelle Concession -contact.type.c80_concession.plural = Concession -contact.type.c90_household = Ménage -contact.type.c90_household.plural = Ménages -contact.type.c90_household.new = Ajouter ménage -contact.type.c90_household.edit = Modifier ménage -contact.type.person = Personne -contact.type.person.edit = Modifier personne -contact.type.person.new = Nouvelle personne -contact.type.person.plural = Personnes -contact.type.c12_central = Personne -contact.type.c12_central.edit = Modifier personne -contact.type.c12_central.new = Nouvelle personne -contact.type.c12_central.plural = Personnes -contact.type.c22_region = Personne -contact.type.c22_region.edit = Modifier personne -contact.type.c22_region.new = Nouvelle personne -contact.type.c22_region.plural = Personnes -contact.type.c32_district = Personne -contact.type.c32_district.edit = Modifier personne -contact.type.c32_district.new = Nouvelle personne -contact.type.c32_district.plural = Personnes -contact.type.c42_health_area = Personne -contact.type.c42_health_area.edit = Modifier personne -contact.type.c42_health_area.new = Nouvelle personne -contact.type.c42_health_area.plural = Personnes -contact.type.c52_supervisor = Personne -contact.type.c52_supervisor.edit = Modifier personne -contact.type.c52_supervisor.new = Nouvelle personne -contact.type.c52_supervisor.plural = Personnes -contact.type.c62_chw = Personne -contact.type.c62_chw.edit = Modifier personne -contact.type.c62_chw.new = Nouvelle personne -contact.type.c62_chw.plural = Personnes -contact.type.c72_village = Personne -contact.type.c72_village.edit = Modifier personne -contact.type.c72_village.new = Nouvelle personne -contact.type.c72_village.plural = Personnes -contact.type.c82_concession = Personne -contact.type.c82_concession.edit = Modifier personne -contact.type.c82_concession.new = Nouvelle personne -contact.type.c82_concession.plural = Personnes -contact.type.c92_household = Personne -contact.type.c92_household.edit = Modifier personne -contact.type.c92_household.new = Nouvelle personne -contact.type.c92_household.plural = Membre du ménage -contact.type.c74_community_actor = Nouveau Acteur Communautaire -contact.type.c74_community_actor.edit = Modifier Acteur Communautaire -contact.type.c74_community_actor.new = Nouveau Acteur Communautaire -contact.type.c74_community_actor.plural = Nouveaux Acteurs Communautaires -contact.sex.male = Homme -contact.sex.female = Femme -contact.sex. = Non Definis -person.field.telephone = Téléphone -contact.pregnancy.lmp = Date des dernières règles -contact.pregnancy.estimated_delivery = Date estimative de l''accouchement -contact.pregnancy.type = Type de grossesse -contact.pregnancy.high_risk = Haut risque -contact.pregnancy.not_high_risk = Aucun risque -contact-prgnancy-active = Grossesse Active -task.child_longitudinal_followup_1_24 = Suivi longitudinal de l'enfant 1 à 24 mois -task.child_longitudinal_followup_2_5 = Suivi longitudinal de l'enfant 2 à 5 ans -task.child_longitudinal_followup_6_12 = Suivi longitudinal de l'enfant 6 à 12 ans -task.child_longitudinal_followup_13_19 = Suivi longitudinal de l'enfant 13 à 19 ans -task.newborn_registration = Création Profil enfant -task.mother_referral_followup = Suivi Référence Mère -task.cpon_realisation = Référence naissance à domicile -task.postnatal_followup = Suivi Après Naissance -task.treatment_followup_under_5 = Suivi traitement moins de 5 ans -task.referral_followup_under_5 = Suivi référence moins de 5 ans -task.treatment_referral_followup_under_5 = Suivi traitement après Référence moins de 5 ans -task.mas_followup_under_5 = Suivi malnutrition (MAS Sans Complication) moins de 5 ans -task.mam_followup_under_5 = Suivi MAM moins de 5 ans -task.vaccine_followup_under_5 = Suivi vaccinal moins de 5 ans -task.treatment_followup_multiple = Suivi Traitement Multiple -task.treatment_followup_under_5.diarrhea = Suivi Traitement Diarrhée -task.treatment_followup_under_5.pneumonia = Suivi Traitement Pneumonie -task.treatment_followup_under_5.malaria = Suivi Traitement Paludisme -contact.delivery.number_pregnancy_confirmed = Grossesses Confirmées -contact.delivery.number_of_children = Nombre de nouveaux nés -contact.delivery.delivery_date = Date d'accouchement -contact.delivery.general = Informations accouchements -task.pregnancy_followup = Suivi Grossesse -task.priority.high = Elévé -enketo.geopicker.latitude = Latitude -enketo.geopicker.longitude = Longitude -enketo.geopicker.altitude = Altitude -enketo.geopicker.accuracy = Précision -enketo.geopicker.searchPlaceholder = Rechercher un lieu -enketo.selectpicker.noneselected = Non Sélectionner -usertype.central_admin = Central Admin -usertype.national_admin = National Admin -usertype.district_admin = District Admin -usertype.dtc = DTC -usertype.supervisor = Supervisor -usertype.chw = ASC -usertype.oca = Autre acteur communautaire -usertype.oca_supervisor = ADC(OCA Coach) -usertype.cvs = CVS -usertype.wash_comity = Comité WASH -usertype.savings = Manager CVSS -usertype.manager_stock = Responsable Approvisionnement -task.pregnancy_confirmation = Confirmation de la grossesse -contact.birth.certificate = Acte de naissance -contact.birth.certificate_number = Numero de l''acte de naissance -contact.birth.certificate_date = Date de délivrance -contact.fp.general = Planning Familial -contact.fp.recent_fp_method = Méthode de PF Récente -contact.fp.state = Status -contact.fp.stop = Arrêt -contact.fp.in_progress = En cours -task.overdue = Aujourd’hui -task.overdue.days = {DAYS plural =0{Aujourd''hui} =1{Retard d''1 jour} other{Retard de \# jours}} -task.days.left = {DAYS plural =1{1 jour restant} other{# jours restant}} -task.pregnancy_referral_followup = Suivi Référence Femme enceinte -task.anc_followup = Réalisation Visite CPN -task.fp_reference_followup = Référence FP {{contact.name}} -task.fp_renewal_followup = Suivi PF -task.treatment_followup_over_5 = Suivi traitement -task.referral_followup_over_5 = Suivi référence +5 ans -task.tb_treatment_followup = Suivi Traitement Hebdomadaire TB -admin.display = Affichage -admin.display.datetime = Date et heure -admin.targets.description = Si désactivé l'onglet cible sera masqué pour tous les utilisateurs. Un objectif de -1 montrera une cible sans objectif. -app.name = Application -branding.favicon.field = Petite icône -branding.logo.field = Logo -branding.title.field = Titre -branding.title.field.help = Affichera les installations PWA. Devrait être au moins 144 pixels carrés. -configuration.sms = SMS -configuration.sms.forms = Formes SMS -configuration.sms.forms.title = Vous devez choisir à la fois un fichier XML et un fichier META avant de cliquer sur le bouton Télécharger. Vous ne pouvez télécharger qu'un seul fichier de formulaire d'application à la fois et tous les formulaires existants seront écrasés. -configuration.sms.settings = Paramètres de base -configuration.sms.test.description = Utilisez cette page pour envoyer un message de test à l'application de production sans passer par la passerelle SMS. Assurez-vous d'utiliser un numéro de téléphone enregistré dans le profil d'un ASC pour imiter un rapport venant de lui sur un patient particulier. -configuration.sms.test.from.number = À partir du numéro de téléphone -configuration.sms.test.message.description = Limite de 144 caractères -configuration.sms.test.number.validation.description = Veuillez saisir un numéro de téléphone valide sans tirets ni ponctuation. -configuration.sms.test.title = Message d'essai -display.language.accordion.title = Les langages activés seront disponibles pour les utilisateurs en option lorsqu'ils sélectionnent leur langue principale. Nous vous recommandons de choisir 1 à 3 langues prises en charge et de désactiver le reste. Parmi les langues prises en charge activées il devrait y avoir 0 traduction manquante. -display.privacy.policies.current = Politique actuelle -display.privacy.policies.select = Sélectionnez le fichier HTML -display.privacy.policies.title = Les politiques de confidentialité -display.privacy.policies.update = Mettre à jour la politique -display.privacy.policies.upload = Soumettre pour télécharger des modifications. -display.translation.description = Veuillez noter que toutes les modifications ou ajouts que vous apportez ici aux traductions ne sont pas actuellement enregistrés ou suivis ailleurs. -edit.name = Modifier le nom -export.dhis.dataset.description = Sélectionnez parmi les intégrations DHIS2 disponibles. -export.dhis.dataset.label = Ensemble de données DHIS2 -export.dhis.description = Téléchargez un fichier contenant un DHIS2 DataValueNeset pour intégrer avec DHIS2. -export.dhis.period.description = Sélectionnez parmi les intervalles de temps mensuels disponibles. -export.dhis.period.label = Filtre par période -export.dhis.place.all = Tous les lieux -export.dhis.place.description = Filtrez des données exportées pour inclure des données associées aux contacts sous cet endroit dans la hiérarchie. -export.dhis.place.label = Filtre par lieu -export.feedback.description = Téléchargez un journal des erreurs détectées et des commentaires des utilisateurs soumis via la fonction «Bug de rapport» au format CSV. Le tableau ci-dessous montre les rapports les plus récemment soumis. -export.messages.description = Téléchargez tous les messages qui ont jamais été envoyés ou reçus au format CSV. -export.people.description = Téléchargez tous les contacts enregistrés dans le système au format JSON. -export.reports.description = Le lancement d'Android Apps n'est pas disponible sur cet appareil. -icon.library = Bibliothèque d'icônes CHT -images.header.tabs.icons = Icônes des onglets d'en-tête -images.header.tabs.icons.default = Icône par défaut -images.header.tabs.icons.description = Configurer les icônes d'onglet d'en-tête. Vous pouvez choisir entre les icônes d'application au format .svg et les icônes Fontawesome. -images.header.tabs.icons.fa.icon = Icône Fontawesome -images.header.tabs.icons.fontawesome.link = En savoir plus sur Fontawesome. -images.header.tabs.icons.resource.icon = Icône de ressources -images.header.tabs.icons.tab = Languette -images.icons.description = Les images téléchargées ici sont utilisées dans l'application à divers endroits comme spécifié dans le code d'application. Par exemple l'image qui apparaît pour un widget particulier dans la page cible est spécifiée dans le code cible. Vous pouvez télécharger des images un à la fois et si vous téléchargez une image avec le même nom qu'une image existante elle sera écrasée avec le nouveau fichier. Il est recommandé que les images soient au format .svg ou .png et aient une taille inférieure à 500 Ko. Des ressources sont disponibles dans le -images.partners.description = Tous les logos partenaires qui sont ajoutés ici seront affichés sur la page "À propos" de l'application. -partner.logo.field = Logo partenaire -partner.logo.upload = Télécharger le logo du partenaire -partner.name.field = Nom de partenaire -partner.tab.partners = Les partenaires -permission.description.can_access_gateway_api = Autorisé à accéder aux API pour agir comme une passerelle SMS. -permission.description.can_aggregate_targets = Page des agrégats cibles autorisés -permission.description.can_bulk_delete_reports = Autorisé à utiliser des fonctions de suppression en vrac pour supprimer plusieurs rapports. -permission.description.can_configure = Autorisé à configurer toutes les configurations d'application. -permission.description.can_create_people = Autorisé à créer de nouvelles personnes. -permission.description.can_create_places = Autorisé à créer de nouveaux lieux. -permission.description.can_create_records = Autorisé à accéder aux API pour créer des rapports. -permission.description.can_create_users = Autorisé à créer des utilisateurs. -permission.description.can_delete_contacts = Autorisé à supprimer des personnes et des lieux. -permission.description.can_delete_messages = Autorisé à supprimer les messages. -permission.description.can_delete_reports = Autorisé à supprimer les rapports. -permission.description.can_delete_users = Autorisé à supprimer les utilisateurs. -permission.description.can_edit = Autorisé à créer et à modifier des documents dans la base de données. -permission.description.can_edit_profile = Autorisé à modifier leurs propres paramètres utilisateur. -permission.description.can_edit_verification = Autorisé à mettre à jour les statuts de vérification des rapports. -permission.description.can_export_all = Autorisé à exporter toutes les données même s'ils n'auraient généralement pas la permission de les visualiser. -permission.description.can_export_contacts = Autorisé à exporter tous les contacts. -permission.description.can_export_feedback = Autorisé à exporter tous les commentaires de l'utilisateur. -permission.description.can_export_messages = Autorisé à exporter tous les rapports et messages. -permission.description.can_log_out_on_android = Autorisé à déconnecter de l'application Android. -permission.description.can_update_places = Autorisé à mettre à jour les documents de lieu existants. -permission.description.can_update_reports = Autorisé à mettre à jour les documents de rapport existants. -permission.description.can_update_users = Autorisé à mettre à jour les utilisateurs existants. -permission.description.can_verify_reports = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_analytics = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_analytics_tab = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_call_action = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_contacts = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_contacts_tab = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_last_visited_date = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_message_action = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_messages = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_messages_tab = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_outgoing_messages = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_reports = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_reports_tab = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_tasks = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_tasks_tab = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_unallocated_data_records = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_view_users = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -permission.description.can_write_wealth_quintiles = Autorisé à mettre à niveau la version CHT Core Framework via l'interface API ou Admin. -submit.icon = Icône de téléchargement -unique.id = Identifiant unique -upload = Télécharger -upload.sms.forms = Télécharger les formulaires SMS -admin.app.name = Configuration de l’application -Cancel = Annuler -Import\ from\ file = Importer à partir d’un fichier -Add\ User = Ajouter un utilisateur -To\ add\ multiple\ users\ please\ upload\ the\ appropriate\ spreadsheet. = Pour ajouter plusieurs utilisateurs veuillez charger le fichier approprié. -Only\ .csv\ file\ are\ accepted. = Seuls les fichiers .csv sont acceptés. -Upload\ .csv = Charger le .csv -Are\ you\ sure\ you\ want\ to\ upload = Voulez-vous vraiment charger le fichier? -Yes\ upload = Oui charger -Processing\ users = Traitement des utilisateurs en cours -This\ process\ can\ take\ a\ long\ time\ if\ you''re\ uploading\ a\ lot\ of\ users\ please\ be\ patient. = Le traitement peut prendre un peu de temps si vous importez un grand nombre d’utilisateurs s’il vous plait soyez patient. -Currently\ unavailable = Actuellement indisponible -Someone\ else\ in\ the\ system\ is\ currently\ in\ the\ process\ of\ adding\ multiple\ users. = Quelqu’un d’autre dans le système est actuellement en train d’importer des utilisateurs. -users\ added = utilisateurs ajoutés -previously\ imported = déjà importés -contained\ errors = contenant des erreurs -Click = Cliquez -here = ici -to\ download\ your\ status\ file. = pour télécharger le rapport de traitement -To\ resubmit\ the\ users\ containing\ errors\ \: = Pour corriger les erreurs et soumettre à nouveau : -1.\ Open\ the\ downloaded\ status\ file = 1. Ouvrir le rapport de traitement téléchargé -2.\ Cross-reference\ the\ errors\ against\ your\ formatted\ spreadsheet = 2. Comparer et croiser les erreurs avec le fichier formatté -3.\ Correct\ rows\ with\ errors\ and\ export\ to\ .csv = 3. Corriger les lignes contenant les erreurs et exporter le fichier au format csv -4.\ Reupload\ updated\ spreadsheet = 4. Charger de nouveau le fichier -Back\ to\ user\ list = Retour à la liste des utilisateurs -upgrade.description = Pour mettre à niveau votre application vers une version une bêta ou une branche spécifique il est recommandé d'effectuer une première étape en cliquant sur "Staging". Cela permet d'effectuer un travail de fond pour préparer l'installation sans interrompre les utilisateurs. Une fois la mise en scène terminée cliquez sur Installer pour procéder à la mise à niveau. Cette action ne peut pas être annulée alors assurez-vous que vos données ont été sauvegardées et que vos utilisateurs sont informés de l'interruption de service. -instance.upgrade.date = Date de mise à jour -users.manage.add_single_user = Ajouter un utilisateur -users.manage.back = Retour à la liste des utilisateurs -users.manage.import_users = Importer à partir d'un fichier -login.unsupported_browser = Pour une meilleure experience avec l'application veuillez contacter l'administrator ou votre superviseur. -login.unsupported_browser.outdated_cht_android = Demander leur de mettre à niveau cht-android. -login.unsupported_browser.outdated_webview_apk = Demander leur de mettre à niveau l'apk webview. -login.unsupported_browser.outdated_browser = Demander leur de mettre à niveau leur navigateur. -task.referral_followup=Suivi référence -task.treatment.malaria=Suivi traitement malaria -task.treatment.diarrhea=Suivi traitement diarhée -task.treatment.ari=Suivi traitement pneumonie -task.treatment.multiple=Suivi traitement multiple -task.treatment.malnutrition=Suivi traitement malnutrition -task.pnc_followup=Suivi réalisation CPON -task.anc_supervision_followup=Suivi réalisation CPN -task.newborn_followup=Suivi Nouveau-né -task.prenatal_followup=Suivi CPN -task.supervision_visit_realization=Réalisation de la visite de Supervision -task.supervision_with_chw_confirmation=Visite du site d''ASC -task.supervision_without_chw_confirmation=Visite dans la communauté sans l''ASC -task.individual_feedback_confirmation=Rencontre Individuelle -task.oca_supervision_visit_realization=Réalisation de la visite de coaching de la PC -task.oca_supervision_visit_scheduling=Planification de la visite de coaching (PC) -task.meeting_with_authorities_realization=Réalisation de la réunion avec les autorités -task.visit_with_pc_realization=Réalisation Visite Avec la PC -task.visit_realisation_without_pc=Réalisation Visite des Ménages sans PC -task.oca_individual_feedback_confirmation = Réalisation Rencontre individuelle -task.sebac_alert_sort = Tri de l'alerte -task.sebac_alert_sort_not_done = Tri de l'alerte non réalisé -task.sebac_alert_sort_2 = Tri de l'alerte 2 -task.sebac_alert_verification=Vérification d'Alerte -task.sebac_verification_notification=Notification Vérification d'Alerte -task.sebac_verification_result=Résultat Vérification d'Alerte -task.sebac_test_result_reminder=Rappel des Résultat des Tests -task.sebac_result_notification=Notification Résultat Tests -task.sebac_alert_dtc_notification=Notification d'Alerte -target.home_visits=Visite à domicile -target.2-home-visits-per-fam=% de ménages ayant reçu ≥2 VAD -target.chv-receive-supervision-visit=% des ASC ayant reçu de visite de supervision 360 degré -target.patient_assessment-24h=% <5 ans ayant reçu de soins dans les 24H du début de la maladie -target.patient_assessment_over_5-24h=% >5 ans ayant reçu de soins dans les 24H du début de la maladie -target.preg-first-trimester=% des grossesses diagnostiquées dans le premier trimestre -target.protocol-error-percentage=% des évaluations sans erreur de protocole -target.protocol-error-count=# Total des erreurs de protocole -target.danger-signs-without-accompany=Signe (s) de danger sans référence ou accompagnement au CSCOM -target.symptoms-of-malaria-without-tdr=Signe de paludisme TDR paludisme pas réalisé -target.fever-without-tdr=Présence de fièvre TDR paludisme pas réalisé -target.tdr-without-malaria=CTA donnée par l''ASC TDR paludisme négatif -target.incorrect-dosage-of-act-based-combination=Dose de CTA donnée par l''ASC incorrecte -target.diarrhea-without-zinc=Diarrhée sans administration de zinc -target.incorrect-dosage-of-zinc=Dose de Zinc donnée par l''ASC incorrecte -target.pneumonia-without-amoxicillin=Pneumonie sans amoxicilline -target.amoxicillin-without-pneumonia=Amoxicilline sans pneumonie -target.incorrect-dosage-of-amoxicillin=Dose d''amoxicilline donnée par l''ASC incorrecte -target.muac-yellow-incomplete-drugs=Bande de Shakir au jaune sans traitement au complet le premier jour -target.incorrect-dosage-of-vitamin-a=Dose de vitamine A donnée par l''ASC incorrecte -target.incorrect-dosage-of-albendazole=Dose d''Albendazol donnée par l''ASC incorrecte -target.incorrect-dosage-of-paracetamol=Dose de paracetamol donnée par l''ASC incorrecte -target.no-24h-follow-up=Pas de suivi de 24H -target.no-48h-follow-up=Pas de suivi de 48H -target.no-72h-follow-up=Pas de suivi de 72H -target.no-120h-follow-up=Pas de suivi de 5eme jour (Pour IRA ou Diarrhée) -target.aggrevated-no-accompany=Etat aggravé à 24H ou 48H ou 72H ou 5eme jour sans référence/accompagnement au CSCOM -target.unchanged-no-accompany=Pas de changement à 48H ou 72H ou 5eme jour sans référence/accompagnement au CSCOM -target.not-improved-3d-no-accompany=Pas amélioré ou pas guéri à 72H sans référence/accompagnement au CSCOM -target.not-improved-5d-no-accompany=Pas amélioré ou pas guéri le 5eme sans référence/accompagnement au CSCOM -sms.token.login.help = -contact.profile.death.date = Date de décès -contact.profile.death.place = Lieu du décès -contact.profile.death.title = Décès -contact.profile.value.unknown = Inconnu -contact.profile.death.places.village = Au village -contact.profile.death.places.home = A la maison -contact.profile.death.places.other = Autre -contact.profile.death.places.undefined = Inconnu -sync.now = Rafraîchir -Report\ Bug = Reporter une erreur -target.childcare_by_chw.title = Nombre de nouvelles consultations curatives d’enfants de moins de 5 ans par les ASC -target.childcare_by_chw.fever.title = Nombre de TDR réalisé chez les enfants de moins de 5 ans présentant une fièvre -target.childcare_by_chw.diarrhea.title = Nombre d’enfants de moins de 5 ans présentant une diarrhée traitée avec le zinc et SRO par l'ASC -target.childcare_by_chw.pneumonia.title = Nombre d’enfants de moins de 5 ans présentant une pneumonie traitée avec Amoxicilline par l'ASC -target.childcare_by_chw.cough_cold_ari.title = Nombre d’enfants de moins de 5 ans présentant Toux/Rhume traitée par l'ASC -target.child_uncomplicated_malaria.title = Nombre d’enfants de moins de 5 ans présentant un paludisme simple confirmé par TDR et traité avec CTA par l'ASC -target.childcare_by_chw.malnourished.title = Nombre d’enfants dépistés malnutris -target.childcare_by_chw.moderate_acute_malnutrition.title = Nombre d’enfants de moins de 5 ans présentant une malnutrition aiguë modérée prise en charge par les ASC -target.childcare_by_chw.uncomplicated_severe_malnutrition.title = Nombre d’enfants de moins de 5 ans présentant une malnutrition aiguë sévère sans complication prise en charge avec plumpy nut par l'ASC -target.uncomplicated_malaria_5_plus.title = Nombre d’enfants de plus de 5 ans présentant un paludisme simple confirmé par TDR et traité avec CTA par l'ASC -target.pregnant_with_uncomplicated_malaria_rdt_cta.title = Proportion de femme enceinte présentant un paludisme simple confirmé par TDR et traité avec CTA par les ASC -target.newborns_followed_first_7_days = Nouveau-nés suivis dans le délai les 7 premiers jours de vie -target.newborns_followed_declared = Nouveaux nés déclarés à l’état civil -target.new_fp_user = Nouvelle utilisatrice en PF réalisé par les ASC -target.proportion_with_danger_case = Proportion de cas présentant un signe de danger ou d'alerte référés par l'ASC -target.proportion_children_fully_vaccinated = Proportion d'enfants de 0 à 23 mois entièrement vaccinés -target.new_patient_followed_by_community_agent = Nombre de nouveaux malades TB en traitement suivis -target.presumptive_tb_followed_by_community_agent = Cas présumés de TB référés -target.home_visit_chw = VAD Total -target.chw_talks = Causeries réalisées -target.tb_cases_lost = Nombre de cas de TB perdu de vue -target.household_with_hand_washing = Proportion de ménage disposant d’un dispositif de lavage des mains (fonctionnel avec eau et savon) -target.household_with_improved_latrine = Proportion (Pourcentage) de ménage utilisant une latrine améliorée -target.home_visit_gsan = Proportion de visites à domicile réalisées -target.gsan_affected_men = Nombre d’hommes touchés lors d’une VAD -target.gsan_affected_women = Nombre de femmes touchées lors d’une VAD -target.gsan_affected_men_chat = Nombre d’hommes touchés lors causeries éducatives -target.gsan_affected_women_chat = Nombre de femmes touchées lors des causeries éducatives -target.gsan_chat_proportion = Proportion de causeries réalisées -target.gsan_affected_men_genre = Nombre d’hommes sensibilisés sur l’approche genre -target.cvss.household_as_member.title = Nombre d'adhésion ménages à la CVSS -target.cvss.individual_as_member.title = Nombre d'adhésion individuelle à la CVSS -target.village_motivation_mecanism.title = Nombre de caisses ayant un mecanisme de motivation des ASC -target.village_promotional_activities.title = Nombre de caisses ayant appuyé d’autres activité de promotion de la santé -target.village_transportation_mecanism.title = Nombre de villages ayant un mecanisme de transport -target.fonctional_transportation.title = Nombre de villages avec un mécanisme transport fonctionnel -target.cvss.individual_leaving_cvss.title = Nombre de personne ayant quitté la caisse de solidarité santé -target.cvss.household_leaving_cvss.title = Nombre de ménages ayant quitté la caisse de solidarité santé -target.cvss_under_5_transported_title = Nombre d’enfants de moins de 5ans transportés par le mécanisme de transport -target.cvss_pregnant_woman_transported_title = Nombre de femmes enceintes transportées par le mécanisme de transport -target.cvss_postpartum_woman_transported_title = Nombre de femmes en suite de couche transportées par le mécanisme de transport -target.cvss.nutritional_demonstration.title = Nombre de caisses ayant appuyées les démonstrations nutritionnelles -target.cvss_average_contribution.title = Contribution moyenne des caisses de solidarité santé pour la période -target.cvss_total_expense_transportation.title = Montant dépensé pour le transport( femmes enceintes et les enfants de moins de cinq ans) -target.cvss_total_expense_nd.title = Montant dépensé pour les demonstrations nutritionnelles -target.cvss_member_total_expense.title = Montant de dépenses enregistrées par les membre CVSS -target.chw_helped_in_nature_by_community.title = Nombre d'ASC ayant reçu un appui en nature -target.chw_financially_helpedby_community.title = Nombre d'ASC ayant recu une motivation financiere de la CVSS -target.rdts_carried_out_5_plus_with_fever.title = Nombre de TDR réalisé chez les plus de 5 ans présentant une fièvre -target.number_of_traitments_followup_carried_out.title = Nombre de suivi traitement réalisé (PEC des cas) par l'ASC -target.chw_site_visited_in_community_without_chw.title = % Site ASC ayant fait l'objet d'une visite dans la communauté sans ASC -target.chw_having_been_directly_observed_by_the_supervisor.title = % d'ASC ayant été observé directement par le superviseur -target.chw_having_had_an_individual_meeting_with_the_supervisor.title = % d'ASC ayant fait une rencontre individuelle avec le superviseur -target.pourcentage_de_satisfaction.title = % d'ASC ayant dun niveau de compétence acceptable ≥ 80% -target.pourcentage_geolocalise.title = Pourcentage de sites geolocalisé -target.supervision_visit_realization = Pourcentage de vistes de supervision réalisées -target.percentage_chw_received_visit_sd.title = % d'ASC ayant reçu une visite de supervision dédiée avec toutes les étapes -target.chw_observed_during_assessment.title= % d'ASC observé par superviseur dédié pendant la prise en charge d'un malade -target.chw_rdts_correctly_carried_out.title= Nombre de TDR Paludisme correctement réalisé par l’ASC pendant la supervision -target.chw_rdts_carrying_out_malaria.title= Nombre ASCs observés par le SD pour la réalisation du TDR Paludisme -target.number_of_children_zero_doses.title = Nombre d'enfants de 0 à 23 mois avec zéro dose -target.number_of_children_vaccination_not_up_to_date.title = Nombre d'enfants de 0 à 23 mois partiellement vaccinés -contact.savings.title = Fiche de contact du groupe CVSS -contact.savings.manager.name = Nom manager CVSS -contact.savings.cvss_balance = Solde total -contact.savings.manager.phone = Numéro de téléphone du gestionnaire -contact.savings.total_members = Nombre total de membres CVSS -contact.savings.total_amount_contributed = Montant total cotisé -contact.savings.total_loan_disbursed = Prêt décaissé -contact.savings.loan_balance = Solde du prêt -contact.savings.total_expenses = Dépenses totales -contact.savings.total_disbursement = Montant total décaissé -contact.savings.total_loan_paid = Prêt Remboursé -contact.savings.total_loan = Prêt Total -contact.savings.beneficiary.title = Fiche Contact Bénéficiaire -contact.savings.beneficiary.total_contribution = Cotisation totale Record -contact.savings.beneficiary.total_expense = Total des depense enregistré -contact.savings.beneficiary.total_loan = Prêt Total -contact.savings.beneficiary.loan_balance = Solde total du prêt -task.savings.loan_reminder = Rappel de prêt -task.savings.confirmation_of_expenditure = Confirmation des dépenses -task.savings.loan_reimbursement = Remboursement de prêt -sms.token.login.help = Salut prêt à commencer ? Vous aurez besoin de données et d’une bonne connexion. Accédez à https://play.google.com/store/apps/details?id=org.medicmobile.webapp.mobile.moh_mali_chw&hl=en_US pour installer l'application. Après l'installation cliquez sur le lien suivant pour vous connecter. -target.gsan_affected_women_genre = Femmes sensibilisées sur l’approche genre -target.chw_promo_pregnancy = Visites à domicile réalisées pour les activités promotionnelles + suivi de la femme enceinte -target.curative_home_visits = Visite à domicile réalisés pour les activités curatives -vaccine.status.no_dose = Zero Dose -vaccine.status.full_dose = Complet -vaccine.status.partial_dose = Incomplet -vaccine.title = Vaccination -child.civil_status = Etat civil -child.civil_status.declared = Enfant déclaré -child.civil_status.not_declared = Enfant non déclaré -child.schooling = Scolarité -child.schooling.not_schooled = Non scolarisé -child.schooling.schooled = Scolarisé -child.schooling.waiting = En attente -reports.sidebar.filter.title = Filtre -reports.sidebar.filter.form_type = Type de Formulaire -reports.sidebar.filter.place = Lieu -reports.sidebar.filter.date = Date -reports.sidebar.filter.status = Status -search_bar.filter.label = Filtre -fast_action_button.title = Nouveau -contact.child.mother.indicator.title = Indicateurs de la mère et de l'enfant -contact.child.mother.indicator.pregnant_from_15_49 = Nombre des femmes enceintes de 15-49 ans -contact.child.mother.indicator.health_facility.delivery = Nombre des femmes enceintes ayant accouché dans une formation sanitaire -contact.child.mother.indicator.exclusive.breastfeeding = Nombre d\'enfant de 0-5 mois sous allaitement maternel exclusif -contact.child.mother.indicator.no.vaccine = Nombre d'enfants n'ayant reçu aucun vaccin dans un ménage -contact.child.mother.indicator.fully.immunized = Nombre d'enfants complètement vaccinés -contact.child.mother.indicator.early.learning = Nombre d'enfant de 2-5 ans qui participe à un type de programme d'apprentissage précoce -contact.child.mother.indicator.improved.latrine = Nombre de ménage disposant de latrine améliorée -contact.child.mother.indicator.potable.water = Nombre de ménage qui a accès à l'eau potable (pompe réseau public) -contact.child.mother.indicator.cash.transfert = Nombre de ménage qui recoit un cash transfert -contact.child.mother.indicator.sexual.mutilation = Nombre d'enfant fille ayant subi une mutilation sexuelle -contact.child.mother.indicator.malnutrition = Nombre d\'enfant de 6-59 mois ayant ete depiste de la malnutrition dans un menage +cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamole +cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock out +cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock at hand: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock required: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.summary_header = Summary +cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} has low stock of the following items +cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock out diff --git a/test/stock-out-feature.spec.js b/test/stock-out-feature.spec.js new file mode 100644 index 0000000..bc50b6b --- /dev/null +++ b/test/stock-out-feature.spec.js @@ -0,0 +1,84 @@ +const ExcelJS = require('exceljs'); +const fs = require('fs'); +const path = require('path'); +const { mockConfigs } = require('./mocks/mocks'); +const { updateStockOut } = require('../src/features/stock-out'); +const { + setDirToprojectConfig, +} = require('./test-utils'); + +describe('updateStockOut', () => { + const workingDir = process.cwd(); + + beforeEach(() => { + setDirToprojectConfig(); + }); + + afterEach(() => { + jest.clearAllMocks(); + process.chdir(workingDir); + }); + + it('should update the stock out form with correct values', async () => { + const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; + const processDir = process.cwd(); + + // Check that stock out xlsx and properties files exist. + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + // Call the function updateStockOut and check that the stock_out files are generated + await updateStockOut(mockConfigs); + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); + } + + // Check that stock out files content are correctly written. + const formPath = path.join(processDir, 'forms', 'app', 'stock_out.xlsx'); + const workbook = new ExcelJS.Workbook(); + await workbook.xlsx.readFile(formPath); + const spy = jest.spyOn(workbook, 'getWorksheet'); + const surveyWorkSheet = workbook.getWorksheet('survey'); + expect(spy).toHaveBeenCalledTimes(1); + const settingWorkSheet = workbook.getWorksheet('settings'); + expect(spy).toHaveBeenCalledTimes(2); + expect(surveyWorkSheet).not.toEqual([]); + expect(settingWorkSheet).not.toEqual([]); + + + const propertiesFileContent = fs.readFileSync( + path.join(processDir, 'forms', 'app', 'stock_out.properties.json'), + {encoding: 'utf-8'} + ); + + expect(JSON.parse(propertiesFileContent)).toEqual({ + 'context': { + 'expression': 'user.parent.contact_type === \'c50_supervision_area\'', + 'person': false, + 'place': false + }, + 'icon': 'icon-healthcare-medicine', + 'title': [ + { + 'content': 'Stock Out Title', + 'locale': 'en' + }, + { + 'content': 'Titre du Stock', + 'locale': 'fr' + } + ] + }); + + // Delete generated stock out files + for(const createdAppFormFile of createdAppFormFiles){ + fs.stat(path.join(processDir, 'forms', 'app', createdAppFormFile), (error) => { + if (!error) { + expect(fs.unlinkSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(undefined); + } + }); + } + + }); +}); diff --git a/test/stock-out.spec.js b/test/stock-out-integration.spec.js similarity index 57% rename from test/stock-out.spec.js rename to test/stock-out-integration.spec.js index cac2d2d..38d75b4 100644 --- a/test/stock-out.spec.js +++ b/test/stock-out-integration.spec.js @@ -1,13 +1,13 @@ const { spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs-extra'); -//const { once } = require('events'); const ExcelJS = require('exceljs'); const { stockOutScenario, stockCountScenario } = require('./mocks/mocks'); const { setDirToprojectConfig, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp } = require('./test-utils'); @@ -20,6 +20,7 @@ describe('Stock out', () => { }); afterEach(async() => { + cleanUp(workingDir); revertBackToProjectHome(workingDir); }); @@ -28,15 +29,15 @@ describe('Stock out', () => { const workbook = new ExcelJS.Workbook(); const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); - if(childProcess.status === 0) { + if (childProcess.error) { + throw childProcess.error; + } + else { // Check that stock monitoring is initialized and stock count and stock out xform and properties files are generated - //const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); + const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx']; - const formFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - for(const formFile of formFiles){ - if(formFile.toString().includes('stock_count') || formFile.toString().includes('stock_out')){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); - } + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); } expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); @@ -74,12 +75,13 @@ describe('Stock out', () => { // Add stock out feature test const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); - if(stockOutChildProcess.status === 0){ - const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - for(const formFile of stockOutFormFiles){ - if(formFile.toString().includes('stock_out')){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); - } + if (stockOutChildProcess.error) { + throw stockOutChildProcess.error; + } + else { + const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); } // Check that the products are available in stock out xform @@ -98,46 +100,7 @@ describe('Stock out', () => { expect(stockOutProductsList.length).toBe(stockOutCellProductsList.length); expect(stockOutProductsList.entries).toStrictEqual(stockOutCellProductsList.entries); - - } - - const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - - for(const formFile of stockOutFormFiles){ - if(formFile.toString().includes('stock_out') || formFile.toString().includes('stock_count')){ - expect(fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile))).toBe(undefined); - } - } - - // Removing the stock monitoring init file and stock count file - const stockMonitoringInitPath = path.join(processDir, 'stock-monitoring.config.json'); - //const stockMonitoringInitFile = fs.stat - fs.stat(stockMonitoringInitPath, (error) => { - if (error) { - //console.log(error); - } - else { - expect(fs.unlinkSync(stockMonitoringInitPath)).toBe(undefined); - //console.log(stats); - } - }); - - const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); - for(const translationFile of translationFiles){ - - const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); - expect(messageFileContent).not.toBe(''); - const newMessageContent = messageFileContent.split('\n').map(message => { - if(!message.toString().includes('cht-stock-monitoring-workflow') && message.toString()!==''){ - return `${message.toString()}\n`; - } - }); - - expect(newMessageContent.includes('cht-stock-monitoring-workflow')).toBe(false); - fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); - fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); } - } }); diff --git a/test/test-utils.js b/test/test-utils.js index a7cf32e..98f6952 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -1,5 +1,6 @@ const process = require('process'); const path = require('path'); +const fs = require('fs-extra'); const currentWorkingDirectory = () =>{ return process.cwd(); @@ -14,10 +15,43 @@ const revertBackToProjectHome = (projectHome) =>{ process.chdir(projectHome); }; +const cleanUp = (workingDir) => { + const processDir = path.join(workingDir,'test/project-config/'); + const stockOutFormFiles = ['stock_out.xlsx', 'stock_count.xlsx', 'stock_count.properties.json', 'stock_out.properties.json']; + for(const formFile of stockOutFormFiles){ + fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile)); + } + + // Removing the stock monitoring init file and stock count file + const stockMonitoringInitPath = path.join(processDir, 'stock-monitoring.config.json'); + fs.stat(stockMonitoringInitPath, (error) => { + if (!error) { + fs.unlinkSync(stockMonitoringInitPath); + } + }); + + const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); + for(const translationFile of translationFiles){ + + const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); + if(messageFileContent !== ''){ + const newMessageContent = messageFileContent.split('\n').map(message => { + if(!message.toString().includes('cht-stock-monitoring-workflow.stock_count') && message.toString()!==''){ + return `${message.toString()}\n`; + } + }); + + fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); + fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); + } + } +}; + module.exports = { setDirToprojectConfig, currentWorkingDirectory, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp, }; From dc96d2dc87f1fe0a63194929e1e52c464907a9eb Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 22 Oct 2024 12:41:51 +0100 Subject: [PATCH 3/6] fix: tests failing --- package.json | 2 +- .../translations/messages-en.properties | 396 ++++++++++++++++- .../translations/messages-fr.properties | 411 +++++++++++++++++- test/stock-count.spec.js | 110 ++--- test/stock-out-feature.spec.js | 4 +- test/stock-out-integration.spec.js | 14 +- test/test-utils.js | 15 - 7 files changed, 859 insertions(+), 93 deletions(-) diff --git a/package.json b/package.json index 2c61c67..1a0fdd2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "scripts": { "cz": "cz", - "test": "jest --testTimeout=25000", + "test": "jest --testTimeout=25000 --runInBand", "semantic-release": "semantic-release", "prepare": "husky" }, diff --git a/test/project-config/translations/messages-en.properties b/test/project-config/translations/messages-en.properties index 7dbbdf2..ae1e430 100644 --- a/test/project-config/translations/messages-en.properties +++ b/test/project-config/translations/messages-en.properties @@ -1,7 +1,401 @@ -cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamol +contact.type.ca10_central = Central Level +contact.type.ca10_central.plural = Central Levels +contact.type.ca10_central.new = Add central level +contact.type.ca10_central.edit = Edit central level +contact.type.ca12_central = Person +contact.type.ca12_central.plural = Persons +contact.type.ca12_central.new = Add person +contact.type.ca12_central.edit = Edit person +contact.type.cb20_region = Region +contact.type.cb20_region.plural = Regions +contact.type.cb20_region.new = Add region +contact.type.cb20_region.edit = Edit region +contact.type.cb22_region = Person +contact.type.cb22_region.plural = Persons +contact.type.cb22_region.new = Add person +contact.type.cb22_region.edit = Edit person +contact.type.cc30_district = District +contact.type.cc30_district.plural = Districts +contact.type.cc30_district.new = Add district +contact.type.cc30_district.edit = Edit district +contact.type.cc32_district = Person +contact.type.cc32_district.plural = Persons +contact.type.cc32_district.new = Add person +contact.type.cc32_district.edit = Edit person +contact.type.cd40_commun = Commune +contact.type.cd40_commun.plural = Communes +contact.type.cd40_commun.new = Add commune +contact.type.cd40_commun.edit = Edit commune +contact.type.cd42_commun = Person +contact.type.cd42_commun.plural = Persons +contact.type.cd42_commun.new = Add person +contact.type.cd42_commun.edit = Edit person +contact.type.ce50_followup = Follow-up Area +contact.type.ce50_followup.plural = Follow-up Areas +contact.type.ce50_followup.new = Add follow-up area +contact.type.ce50_followup.edit = Edit follow-up area +contact.type.ce52_followup = Person +contact.type.ce52_followup.plural = Persons +contact.type.ce52_followup.new = Add person +contact.type.ce52_followup.edit = Edit person +contact.type.cf60_sanitary = Sanitary Training +contact.type.cf60_sanitary.plural = Sanitary Trainings +contact.type.cf60_sanitary.new = Add sanitary training +contact.type.cf60_sanitary.edit = Edit sanitary training +contact.type.cf62_sanitary = Person +contact.type.cf62_sanitary.plural = Persons +contact.type.cf62_sanitary.new = Add person +contact.type.cf62_sanitary.edit = Edit person +contact.type.cg70_supervision = Supervision Area +contact.type.cg70_supervision.plural = Supervision Areas +contact.type.cg70_supervision.new = Add supervision area +contact.type.cg70_supervision.edit = Edit supervision area +contact.type.cg72_supervision = Person +contact.type.cg72_supervision.plural = Persons +contact.type.cg72_supervision.new = Add person +contact.type.cg72_supervision.edit = Edit person +contact.type.ch80_village = Village +contact.type.ch80_village.plural = Villages +contact.type.ch80_village.new = Add village +contact.type.ch80_village.edit = Edit village +contact.type.ch82_village = Person +contact.type.ch82_village.plural = Persons +contact.type.ch82_village.new = Add person +contact.type.ch82_village.edit = Edit person +contact.type.ci90_chw_site = CHW Post +contact.type.ci90_chw_site.plural = CHW Posts +contact.type.ci90_chw_site.new = Add CHW post +contact.type.ci90_chw_site.edit = Edit CHW post +contact.type.ci92_chw_site = Person +contact.type.ci92_chw_site.plural = Persons +contact.type.ci92_chw_site.new = Add person +contact.type.ci92_chw_site.edit = Edit person +contact.type.cj100_household = Household +contact.type.cj100_household.plural = Households +contact.type.cj100_household.new = New Household +contact.type.cj100_household.edit = New Household +contact.type.cj100_household.id_code = Household ID +contact.type.cj100_household.geolocation = Geolocation +contact.type.cj100_household.geolocation_missing = Geolocation missing +contact.type.cj102_household = Person +contact.type.cj102_household.plural = Persons +contact.type.cj102_household.new = Add person +contact.type.cj102_household.edit = Edit person +fast_action_button.title = Actions +contact.sex.undefined = UNKNOWN +contact.sex.male = Male +contact.sex.female = Female +person.field.telephone = Telephone +contact.age = Age +contact.profile.death.date = Date of death +contact.profile.death.place = Place of death +contact.profile.death.title = Death +contact.profile.value.unknown = Unknown +contact.profile.death.places.village = In the village +contact.profile.death.places.home = At home +contact.profile.death.places.other = Other +contact.profile.death.places.undefined = Unknown +admin.app.name = Configuration +admin.display = Display +fast_action_button.send_message = Send Message +search_bar.filter.label = Filter +report.new_report.button = New Report +reports.sidebar.filter.title = Filter +reports.sidebar.filter.form_type = Form Type +reports.sidebar.filter.place = Place +reports.sidebar.filter.date = Date +reports.sidebar.filter.status = Status +task.overdue = Today +task.overdue.days = {DAYS plural =0{Today} =1{1 day overdue} other{# days overdue}} +task.days.left = {DAYS plural =1{1 day left} other{# days left}} +task.treatment_followup_under_5 = Under 5 Treatment Follow-up +task.malnutrition_followup = Malnutrition Follow-up +task.cpn_realization = CPN Realization Follow-up +report.death_report_household.household_id = Household Identifier +report.death_report_household.household_name = Household Name +report.death_report_household.death_report_household = Death Report (Household Level) +report.death_report_household.death_report_household.death_date = Date of death +report.death_report_household.death_report_household.name_of_deceased = Full Name of deceased person +report.death_report_household.death_report_household.duration_in_household = How long has the person been in the household? +report.death_report_household.death_report_household.age = Age(s) +report.death_report_household.death_report_household.sex = Gender +report.death_report_household.death_report_household.death_location = Place of death +report.death_report_household.death_report_household.specify = Specify (Other) +report.death_report_household.death_report_household.cause_death = Cause of death +report.death_report_household.death_report_household.death_notified = Was the death notified? +report.death_report_household.death_report_household.consent = Are you sure you want to submit this form? +report.death_report.death_report = Death Report +report.death_report.death_report.death_date = Date of death +report.death_report.death_report.death_location = Place of death +report.death_report.death_report.specify = Specify (Other) +report.death_report.death_report.cause_death = Cause of death +report.death_report.death_report.death_notified = Was the death notified? +report.death_report.death_report.consent = Are you sure you want to submit this form? +report.home_visit.household_id = Household Identifier +report.home_visit.household_name = Household Name +report.home_visit.realization_date = Date of realization +report.home_visit.realization_date.done_today = Was the activity done today? +report.home_visit.realization_date.done_date = Enter the date when the activity was done +report.home_visit.realization_date.reason_activity_not_done = Why was the activity not done today? +report.home_visit.realization_date.reason_activity_not_done_other = Specify (Other) +report.home_visit.realization_date.start_time = Start time +report.home_visit.theme_group = Theme to address +report.home_visit.theme_group.theme = What is the theme to address? +report.home_visit.prenatal_consultation = PFE on Prenatal Consultation CPN +report.home_visit.prenatal_consultation.is_there_a_pregnant_woman = Is there a pregnant woman in the household? +report.home_visit.prenatal_consultation.required_checkup_received = Has the woman received the required CPN checkups based on pregnancy age? +report.home_visit.birth_registration_fee = PFE on Birth Registration +report.home_visit.birth_registration_fee.are_there_children_in_the_household = Are there child(ren) in the household? +report.home_visit.birth_registration_fee.are_the_children_registered = Have you registered your child(ren) with civil registration? +report.home_visit.vaccination_and_vit_a_supplementation = PFE on Vaccination and Vit A Supplementation +report.home_visit.vaccination_and_vit_a_supplementation.are_children_vaccinated = Are your children vaccinated? +report.home_visit.vaccination_and_vit_a_supplementation.are_children_under_5_vaccinated_up_to_date = Are all children under 5 years old in the household up to date with their vaccinations according to the PEV vaccination schedule? +report.home_visit.affected_persons = Affected Persons +report.home_visit.affected_persons.number_of_affected_females = Number of affected females +report.home_visit.affected_persons.number_of_affected_males = Number of affected males +report.home_visit.affected_persons.total_number_of_affected = Total number of affected persons +report.home_visit.end = End +report.home_visit.end.end_time = End time +report.social_mobilization.realization_activity = Realization of Activity +report.social_mobilization.realization_activity.realization_date = Date of realization +report.social_mobilization.realization_activity.realization_date.done_today = Was the activity done today? +report.social_mobilization.realization_activity.realization_date.done_date = Enter the date when the activity was done +report.social_mobilization.realization_activity.realization_date.reason_activity_not_done = Why was the activity not done today? +report.social_mobilization.realization_activity.realization_date.reason_other = Specify (Other) +report.social_mobilization.realization_activity.realization_date.start_time = Start time +report.social_mobilization.realization_activity.place_of_mobilization = Place of mobilization +report.social_mobilization.realization_activity.place_of_mobilization.location_of_the_mobilization = What is the location of the mobilization? +report.social_mobilization.realization_activity.place_of_mobilization.location_other = Specify (Other) +report.social_mobilization.realization_activity.theme_group = Themes addressed +report.social_mobilization.realization_activity.theme_group.theme = What is the social mobilization topic? +report.social_mobilization.realization_activity.theme_group.theme_other = Specify (Other) +report.social_mobilization.affected_persons = Affected Persons +report.social_mobilization.affected_persons.number_of_affected_females = Number of affected females +report.social_mobilization.affected_persons.number_of_affected_males = Number of affected males +report.social_mobilization.affected_persons.total_number_of_affected = Total number of affected persons +report.social_mobilization.evaluation = Evaluation +report.social_mobilization.evaluation.evaluation_of_social_mobilization = Evaluation of social mobilization +report.social_mobilization.evaluation.evaluation_of_social_mobilization.tools_used = Tools used +report.social_mobilization.evaluation.evaluation_of_social_mobilization.evaluation_other = Specify (Other) +report.social_mobilization.evaluation.evaluation_of_social_mobilization.difficulties_encountered = Difficulties encountered +report.social_mobilization.evaluation.evaluation_of_social_mobilization.proposed_solutions = Proposed solutions +report.social_mobilization.evaluation.evaluation_of_social_mobilization.good_practices_observed = Good practices observed +report.social_mobilization.evaluation.end = End +report.social_mobilization.evaluation.end.end_time = End time +usertype.supervisor = Supervisor +usertype.community_user = Community Relay +usertype.chw = Community Health Worker +usertype.sanitary = Sanitary Health Worker +usertype.followup = Endogenous Animator +usertype.district_admin = District Administrator +usertype.regional_admin = Regional Administrator +usertype.central_admin = Central Administrator +users.manage.add_single_user = Add User +users.manage.import_users = Import from File +sync.now = Refresh +app.name = Application Configuration +task.referral_followup_under_5 = Under 5 Referral Follow-up +task.pregnancy_confirmation = Pregnancy Confirmation +task.overdue = Today +task.overdue.days = {DAYS plural =0{Today} =1{1 day overdue} other{# days overdue}} +task.days.left = {DAYS plural =1{1 day left} other{# days left}} +task.priority.high = High +task.fp_followup = FP Follow-up +enketo.geopicker.longitude = Longitude +enketo.geopicker.latitude = Latitude +enketo.geopicker.altitude = Altitude +enketo.geopicker.accuracy = Accuracy +task.fp_renewal = FP Renewal +task.postnatal_followup = Postnatal CPoN Follow-up +task.cpon_realization = CPoN Realization Follow-up +target.chw_home_visit = Total of Home Visits +cht-stock-monitoring-workflow.stock_count.balance_fill = Use this form to fill in balances on hand for all commodities as of today +cht-stock-monitoring-workflow.stock_count.commodities_note =

Commodities Balance on hand

+cht-stock-monitoring-workflow.stock_count.message.summary_header = Results/Summary page +cht-stock-monitoring-workflow.stock_count.contact_summary.title = Stock count +cht-stock-monitoring-workflow.stock_count.message.submit_note =

Be sure you Submit to complete this action.

+cht-stock-monitoring-workflow.stock_count.message.summary_note = Stock items you currently have. +cht-stock-monitoring-workflow.stock_count.tasks.stock-count = Stock count +cht-stock-monitoring-workflow.stock_count.forms.additional_doc_title = Stock uses +cht-stock-monitoring-workflow.stock_count.forms.item_used_question = Quantity of {{item}} +cht-stock-monitoring-workflow.stock_count.message.set_unit_constraint_message = Should be in the form x/y for x {{set_label}} and y {{unit_label}} +cht-stock-monitoring-workflow.stock_count.message.unit_quantity_hint = Add the quantity: {{quantity}} {{unit_label}} + cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock out cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock at hand: {{qty}} cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock required: {{qty}} cht-stock-monitoring-workflow.stock_out.message.summary_header = Summary cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} has low stock of the following items cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock out + + +cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/project-config/translations/messages-fr.properties b/test/project-config/translations/messages-fr.properties index 8fe99db..a2b3bcd 100644 --- a/test/project-config/translations/messages-fr.properties +++ b/test/project-config/translations/messages-fr.properties @@ -1,7 +1,406 @@ +contact.type.ca10_central=Niveau Central +contact.type.ca10_central.plural = Niveaux Centraux +contact.type.ca10_central.new = Ajouter niveau central +contact.type.ca10_central.edit = Modifier niveau central +contact.type.ca12_central = Personne +contact.type.ca12_central.plural = Personnes +contact.type.ca12_central.new = Ajouter personne +contact.type.ca12_central.edit = Modifier personne +contact.type.cb20_region= Région +contact.type.cb20_region.plural = Régions +contact.type.cb20_region.new = Ajouter région +contact.type.cb20_region.edit = Modifier région +contact.type.cb22_region = Personne +contact.type.cb22_region.plural = Personnes +contact.type.cb22_region.new = Ajouter personne +contact.type.cb22_region.edit = Modifier personne +contact.type.cc30_district = District +contact.type.cc30_district.plural = Districts +contact.type.cc30_district.new = Ajouter district +contact.type.cc30_district.edit = Modifier district +contact.type.cc32_district = Personne +contact.type.cc32_district.plural = Personnes +contact.type.cc32_district.new = Ajouter personne +contact.type.cc32_district.edit = Modifier personne +contact.type.cd40_commun = Commune +contact.type.cd40_commun.plural = Communes +contact.type.cd40_commun.new = Ajouter Commune +contact.type.cd40_commun.edit = Modifier Commune +contact.type.cd42_commun = Personne +contact.type.cd42_commun.plural = Personnes +contact.type.cd42_commun.new = Ajouter personne +contact.type.cd42_commun.edit = Modifier personne +contact.type.ce50_followup = Zone de suivi +contact.type.ce50_followup.plural = Zone de suivi +contact.type.ce50_followup.new = Ajouter Zone de suivi +contact.type.ce50_followup.edit = Modifier Zone de suivi +contact.type.ce52_followup = Personne +contact.type.ce52_followup.plural = Personnes +contact.type.ce52_followup.new = Ajouter personne +contact.type.ce52_followup.edit = Modifier personne +contact.type.cf60_sanitary = Formation Sanitaire +contact.type.cf60_sanitary.plural = Formation Sanitaire +contact.type.cf60_sanitary.new = Ajouter Formation Sanitaire +contact.type.cf60_sanitary.edit = Modifier Formation Sanitaire +contact.type.cf62_sanitary = Personne +contact.type.cf62_sanitary.plural = Personnes +contact.type.cf62_sanitary.new = Ajouter personne +contact.type.cf62_sanitary.edit = Modifier personne +contact.type.cg70_supervision = Zone Supervision +contact.type.cg70_supervision.plural = Zone Supervision +contact.type.cg70_supervision.new = Ajouter Zone Supervision +contact.type.cg70_supervision.edit = Modifier Zone Supervision +contact.type.cg72_supervision = Personne +contact.type.cg72_supervision.plural = Personnes +contact.type.cg72_supervision.new = Ajouter personne +contact.type.cg72_supervision.edit = Modifier personne +contact.type.ch80_village = Village +contact.type.ch80_village.plural = Village +contact.type.ch80_village.new = Ajouter Village +contact.type.ch80_village.edit = Modifier Village +contact.type.ch82_village = Personne +contact.type.ch82_village.plural = Personnes +contact.type.ch82_village.new = Ajouter personne +contact.type.ch82_village.edit = Modifier personne +contact.type.ci90_chw_site = Poste ASC +contact.type.ci90_chw_site.plural = Poste ASC +contact.type.ci90_chw_site.new = Ajouter Poste ASC +contact.type.ci90_chw_site.edit = Modifier Poste ASC +contact.type.ci92_chw_site = Personne +contact.type.ci92_chw_site.plural = Personnes +contact.type.ci92_chw_site.new = Ajouter personne +contact.type.ci92_chw_site.edit = Modifier personne +contact.type.cj100_household = Ménage +contact.type.cj100_household.plural = Ménages +contact.type.cj100_household.new = Nouveau Ménage +contact.type.cj100_household.edit = Nouveau Ménage +contact.type.cj100_household.id_code = ID Ménage +contact.type.cj100_household.geolocation = Geolocalisation +contact.type.cj100_household.geolocation_missing = Aucune géolocalisation défini +contact.type.cj102_household = Personne +contact.type.cj102_household.plural = Personnes +contact.type.cj102_household.new = Ajouter personne +contact.type.cj102_household.edit = Modifier personne +fast_action_button.title = Actions +contact.sex.undefined = INCONNU +contact.sex.male = Homme +contact.sex.female = Femme +person.field.telephone = Téléphone +contact.age = Âge +contact.muted = Mode silencieux activé +contact.profile.death.date = Date de décès +contact.profile.death.place = Lieu du décès +contact.profile.death.title = Décès +contact.profile.value.unknown = Inconnu +contact.profile.death.places.village = Au village +contact.profile.death.places.home = A la maison +contact.profile.death.places.other = Autre +contact.profile.death.places.undefined = Inconnu +admin.app.name = Configuration +admin.display = Affichage +fast_action_button.send_message = Send Message +search_bar.filter.label = Filtre +report.new_report.button = New Report +reports.sidebar.filter.title = Filtre +reports.sidebar.filter.form_type = Form Type +reports.sidebar.filter.place = Place +reports.sidebar.filter.date = Date +reports.sidebar.filter.status = Status +task.overdue = Aujourd’hui +task.overdue.days = {DAYS plural =0{Aujourd''hui} =1{Retard d''1 jour} other{Retard de \# jours}} +task.days.left = {DAYS plural =1{1 jour restant} other{# jours restant}} +task.treatment_followup_under_5 = Suivi Enfant Malade +task.malnutrition_followup = Suivi Malnutrition +task.cpn_realization = Suivi Realization CPN +report.death_report_household.household_id = Identifiant de la Famille +report.death_report_household.household_name = Nom de la Famille +report.death_report_household.death_report_household = Rapport de décès (Niveau Ménage) +report.death_report_household.death_report_household.death_date = Date de décès +report.death_report_household.death_report_household.name_of_deceased = Nom et Prénom de la personne décédée +report.death_report_household.death_report_household.duration_in_household = Depuis quand est-il dans le ménage? +report.death_report_household.death_report_household.age = Age(s) +report.death_report_household.death_report_household.sex = Sexe +report.death_report_household.death_report_household.death_location = Lieu de décès +report.death_report_household.death_report_household.specify = Précisez (Autre) +report.death_report_household.death_report_household.cause_death = Cause du décès +report.death_report_household.death_report_household.death_notified = Est-ce que le décès a été notifié ? +report.death_report_household.death_report_household.consent = Êtes-vous sûr de soumettre ce formulaire? +report.death_report.death_report = Rapport de décès +report.death_report.death_report.death_date = Date de décès +report.death_report.death_report.death_location = Lieu de décès +report.death_report.death_report.specify = Précisez (Autre) +report.death_report.death_report.cause_death = Cause du décès +report.death_report.death_report.death_notified = Est-ce que le décès a été notifié ? +report.death_report.death_report.consent = Êtes-vous sûr de soumettre ce formulaire? +report.home_visit.household_id = Identifiant de la Famille +report.home_visit.household_name = Nom de la Famille +report.home_visit.realization_date = Date de réalisation +report.home_visit.realization_date.done_today = L'activité t-elle été faite aujourd'hui? +report.home_visit.realization_date.done_date = Entrez la date où l'activité a été faite +report.home_visit.realization_date.reason_activity_not_done = Pourquoi l'activité n'a pas été faite aujourd'hui? +report.home_visit.realization_date.reason_activity_not_done_other = Précisez (Autre) +report.home_visit.realization_date.start_time = Heure de démarrage +report.home_visit.theme_group = Thème à aborder +report.home_visit.theme_group.theme = Quel est le thème à aborder? +report.home_visit.prenatal_consultation = PFE sur la Consultation Prénatale CPN) +report.home_visit.prenatal_consultation.is_there_a_pregnant_woman = Il y a t-il une femme enceinte dans le ménage ? +report.home_visit.prenatal_consultation.required_checkup_received = La femme a t-elle réalisé les CPN requis en fonction de l'âge de la grossesse? +report.home_visit.birth_registration_fee = PFE sur l'enregistrement de Naissance +report.home_visit.birth_registration_fee.are_there_children_in_the_household = Il y a t-il un ou des enfants dans le ménage? +report.home_visit.birth_registration_fee.are_the_children_registered = Avez-vous déclaré votre enfant (ou tous les enfants) à l’état civil ? +report.home_visit.vaccination_and_vit_a_supplementation = PFE sur la Vaccination et Supplémentation en Vit A +report.home_visit.vaccination_and_vit_a_supplementation.are_children_vaccinated = Vos enfants sont-ils vaccinés ? +report.home_visit.vaccination_and_vit_a_supplementation.are_children_under_5_vaccinated_up_to_date = Tous les enfants de moins de 5 ans du ménage sont-ils à jour de leur vaccination selon le calendrier vaccinal du PEV +report.home_visit.affected_persons = Personnes touchées +report.home_visit.affected_persons.number_of_affected_females = Nombre femmes touchés +report.home_visit.affected_persons.number_of_affected_males = Nombre d'hommes touchés +report.home_visit.affected_persons.total_number_of_affected = Nombre total de personnes touchées +report.home_visit.end = Fin +report.home_visit.end.end_time = Heure de fin +report.social_mobilization.realization_activity = Réalisation de l'activité +report.social_mobilization.realization_activity.realization_date = Date de réalisation +report.social_mobilization.realization_activity.realization_date.done_today = L'activité t-elle été faite aujourd'hui? +report.social_mobilization.realization_activity.realization_date.done_date = Entrez la date où l'activité a été faite +report.social_mobilization.realization_activity.realization_date.reason_activity_not_done = Pourquoi l'activité n'a pas été faite aujourd'hui? +report.social_mobilization.realization_activity.realization_date.reason_other = Précisez (Autre) +report.social_mobilization.realization_activity.realization_date.start_time = Heure de démarrage +report.social_mobilization.realization_activity.place_of_mobilization = Lieu de la mobilisation +report.social_mobilization.realization_activity.place_of_mobilization.location_of_the_mobilization = Quel est le lieu de la mobilisation ? +report.social_mobilization.realization_activity.place_of_mobilization.location_other = Précisez (Autre) +report.social_mobilization.realization_activity.theme_group = Thèmes abordés +report.social_mobilization.realization_activity.theme_group.theme = Quel est le sujet de la mobilisation sociale? +report.social_mobilization.realization_activity.theme_group.theme_other = Précisez (Autre) +report.social_mobilization.affected_persons = Personnes touchées +report.social_mobilization.affected_persons.number_of_affected_females = Nombre de femmes touchées +report.social_mobilization.affected_persons.number_of_affected_males = Nombre d'hommes touchés +report.social_mobilization.affected_persons.total_number_of_affected = Nombre total de personnes touchées +report.social_mobilization.evaluation = Evaluation +report.social_mobilization.evaluation.evaluation_of_social_mobilization = Evaluation de la mobilisation sociale +report.social_mobilization.evaluation.evaluation_of_social_mobilization.tools_used = Outils utilisés +report.social_mobilization.evaluation.evaluation_of_social_mobilization.evaluation_other = Précisez (Autre) +report.social_mobilization.evaluation.evaluation_of_social_mobilization.difficulties_encountered = Difficultés rencontrées +report.social_mobilization.evaluation.evaluation_of_social_mobilization.proposed_solutions = Solutions proposées +report.social_mobilization.evaluation.evaluation_of_social_mobilization.good_practices_observed = Bonnes pratiques observées +report.social_mobilization.evaluation.end = Fin +report.social_mobilization.evaluation.end.end_time = Heure de fin +usertype.supervisor = Superviseur +usertype.community_user = Relais Communautaire +usertype.chw = ASC +usertype.sanitary = RFS +usertype.followup = Animateur Endogène +usertype.district_admin = Admin District +usertype.regional_admin = Admin Region +usertype.central_admin = Admin Central +users.manage.add_single_user = Ajouter un utilisateur +users.manage.import_users = Importer à partir d'un fichier +sync.now = Rafraîchir +app.name = Configuration de l'application +task.referral_followup_under_5 = Suivi référence moins de 5 ans +task.pregnancy_confirmation = Confirmation de Grossesse +task.overdue = Aujourd’hui +task.overdue.days = {DAYS plural =0{Aujourd''hui} =1{Retard d''1 jour} other{Retard de \# jours}} +task.days.left = {DAYS plural =1{1 jour restant} other{# jours restant}} +task.priority.high = Elévé +task.fp_followup = Suivi PF +enketo.geopicker.longitude = Longitude +enketo.geopicker.latitude = Latitude +enketo.geopicker.altitude = Altitude +enketo.geopicker.accuracy = Accuracy +task.fp_renewal = Renouvellement PF +task.postnatal_followup = Suivi Réalisation CPoN +task.cpon_realization = Suivi Réalisation CPoN +privacy.policy=Politique de confidentialité +privacy.policy.accept = Accepter +target.chw_home_visit = Total VAD + + +cht-stock-monitoring-workflow.stock_count.balance_fill = Utiliser ce formulaire pour enregistrer votre stock actuel +cht-stock-monitoring-workflow.stock_count.commodities_note =

Stock actuel

+cht-stock-monitoring-workflow.stock_count.message.summary_header = Résultats +cht-stock-monitoring-workflow.stock_count.contact_summary.title = Fiche de Stock +cht-stock-monitoring-workflow.stock_count.message.submit_note =

Assurez-vous de soumettre pour complèter cette action.

+cht-stock-monitoring-workflow.stock_count.message.summary_note = Votre stock actuel. +cht-stock-monitoring-workflow.stock_count.tasks.stock-count = Inventaire +cht-stock-monitoring-workflow.stock_count.forms.additional_doc_title = Stock livré +cht-stock-monitoring-workflow.stock_count.forms.item_used_question = Quantité de {{item}} +cht-stock-monitoring-workflow.stock_count.message.set_unit_constraint_message = Doit être sous la forme x/y de x {{set_label}} et y {{unit_label}} +cht-stock-monitoring-workflow.stock_count.message.unit_quantity_hint = Ajouter la quantité: {{quantity}} {{unit_label}} + +cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock épuisé +cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock actuel: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock nécessaire: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.summary_header = Résumé +cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} a épuisé son stock des éléments suivants: +cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock épuisé + + cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamole -cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock out -cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock at hand: {{qty}} -cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock required: {{qty}} -cht-stock-monitoring-workflow.stock_out.message.summary_header = Summary -cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} has low stock of the following items -cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock out + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/stock-count.spec.js b/test/stock-count.spec.js index 839bdf2..74e007f 100644 --- a/test/stock-count.spec.js +++ b/test/stock-count.spec.js @@ -1,7 +1,6 @@ -const { fork } = require('child_process'); +const { spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs-extra'); -const { once } = require('events'); const ExcelJS = require('exceljs'); const { stockCountScenario } = require('./mocks/mocks'); @@ -12,81 +11,68 @@ const { describe('Stock count', () => { + const workingDir = process.cwd(); beforeEach(() => { setDirToprojectConfig(); }); afterEach(() => { - revertBackToProjectHome(process.cwd()); + revertBackToProjectHome(workingDir); }); it('Add stock count summaries test', async() => { const processDir = process.cwd(); - const childProcess = fork('../../main.js', stockCountScenario.initScenario); - await once(childProcess, 'close'); - - const formPath = path.join(processDir, 'forms', 'app', `stock_count.xlsx`); - const formPropertiesPath = path.join(processDir, 'forms', 'app', `stock_count.properties.json`); - const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); - - // Check that stock monitoring is initialized and stock count xform is generated - expect(fs.existsSync(stockMonitoringConfig)).toBe(true); - expect(fs.existsSync(formPropertiesPath)).toBe(true); - expect(fs.existsSync(formPath)).toBe(true); - - // Check that the products are available in stock count xform - const productCategoryList = stockCountScenario.productCategoryScenario; - const productsList = stockCountScenario.productsScenario; - const workbook = new ExcelJS.Workbook(); - await workbook.xlsx.readFile(formPath); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const cellProductCategoriesList = []; - const cellProductsList = []; - let productCatIndex =0; - let productIndex = 0; - nameCol.eachCell(function(cell){ - - if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ - cellProductCategoriesList.push(cell.value); - productCatIndex ++; - productIndex = 0; - } - - if(cell.value === productsList[productIndex] && productIndex < productsList.length){ - cellProductsList.push(cell.value); - productIndex ++; - } - - }); - - expect(productsList.length).toBe(cellProductsList.length); - expect(productsList.entries).toStrictEqual(cellProductsList.entries); - - expect(productCategoryList.length).toBe(cellProductCategoriesList.length); - expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); - - //Removing the stock monitoring init file and stock count file - expect(fs.unlinkSync(stockMonitoringConfig)).toBe(undefined); - expect(fs.unlinkSync(formPath)).toBe(undefined); - expect(fs.unlinkSync(formPropertiesPath)).toBe(undefined); + const childProcess = spawnSync('../../main.js', stockCountScenario.initScenario); + + if (childProcess.error) { + throw childProcess.error; + } else { + const formPath = path.join(processDir, 'forms', 'app', `stock_count.xlsx`); + const formPropertiesPath = path.join(processDir, 'forms', 'app', `stock_count.properties.json`); + const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); + + // Check that stock monitoring is initialized and stock count xform is generated + expect(fs.existsSync(stockMonitoringConfig)).toBe(true); + expect(fs.existsSync(formPropertiesPath)).toBe(true); + expect(fs.existsSync(formPath)).toBe(true); + + // Check that the products are available in stock count xform + const productCategoryList = stockCountScenario.productCategoryScenario; + const productsList = stockCountScenario.productsScenario; + const workbook = new ExcelJS.Workbook(); + await workbook.xlsx.readFile(formPath); + const surveyWorkSheet = workbook.getWorksheet('survey'); + const nameCol = surveyWorkSheet.getColumn('B'); + const cellProductCategoriesList = []; + const cellProductsList = []; + let productCatIndex =0; + let productIndex = 0; + nameCol.eachCell(function(cell){ + + if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ + cellProductCategoriesList.push(cell.value); + productCatIndex ++; + productIndex = 0; + } - const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); - for(const translationFile of translationFiles){ - - const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); - expect(messageFileContent).not.toBe(''); - const newMessageContent = messageFileContent.split('\n').map(message => { - if(!message.toString().includes('cht-stock-monitoring-workflow') && message.toString()!==''){ - return `${message.toString()}\n`; + if(cell.value === productsList[productIndex] && productIndex < productsList.length){ + cellProductsList.push(cell.value); + productIndex ++; } + }); - expect(newMessageContent.includes('cht-stock-monitoring-workflow')).toBe(false); - fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); - fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); + expect(productsList.length).toBe(cellProductsList.length); + expect(productsList.entries).toStrictEqual(cellProductsList.entries); + expect(productCategoryList.length).toBe(cellProductCategoriesList.length); + expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); + + //Removing the stock monitoring init file and stock count file + expect(fs.unlinkSync(stockMonitoringConfig)).toBe(undefined); + expect(fs.unlinkSync(formPath)).toBe(undefined); + expect(fs.unlinkSync(formPropertiesPath)).toBe(undefined); } }); diff --git a/test/stock-out-feature.spec.js b/test/stock-out-feature.spec.js index bc50b6b..11f835b 100644 --- a/test/stock-out-feature.spec.js +++ b/test/stock-out-feature.spec.js @@ -5,6 +5,7 @@ const { mockConfigs } = require('./mocks/mocks'); const { updateStockOut } = require('../src/features/stock-out'); const { setDirToprojectConfig, + revertBackToProjectHome } = require('./test-utils'); describe('updateStockOut', () => { @@ -16,9 +17,10 @@ describe('updateStockOut', () => { afterEach(() => { jest.clearAllMocks(); - process.chdir(workingDir); + revertBackToProjectHome(workingDir); }); + it('should update the stock out form with correct values', async () => { const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; const processDir = process.cwd(); diff --git a/test/stock-out-integration.spec.js b/test/stock-out-integration.spec.js index 38d75b4..b699545 100644 --- a/test/stock-out-integration.spec.js +++ b/test/stock-out-integration.spec.js @@ -11,23 +11,21 @@ const { } = require('./test-utils'); -describe('Stock out', () => { +describe('Stock out integration test', () => { const workingDir = process.cwd(); beforeEach(() => { - revertBackToProjectHome(workingDir); setDirToprojectConfig(); }); afterEach(async() => { - cleanUp(workingDir); revertBackToProjectHome(workingDir); }); - it('Add stock out summaries test', async() => { + it('Add stock out integration test', async() => { const processDir = process.cwd(); const workbook = new ExcelJS.Workbook(); - const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); + const childProcess = await spawnSync('../../main.js', stockOutScenario.initScenario); if (childProcess.error) { throw childProcess.error; @@ -79,8 +77,8 @@ describe('Stock out', () => { throw stockOutChildProcess.error; } else { - const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; - for(const createdAppFormFile of createdAppFormFiles){ + const createdStockOutAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; + for(const createdAppFormFile of createdStockOutAppFormFiles){ expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); } @@ -101,6 +99,8 @@ describe('Stock out', () => { expect(stockOutProductsList.length).toBe(stockOutCellProductsList.length); expect(stockOutProductsList.entries).toStrictEqual(stockOutCellProductsList.entries); } + + cleanUp(workingDir); } }); diff --git a/test/test-utils.js b/test/test-utils.js index 98f6952..790e9db 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -30,21 +30,6 @@ const cleanUp = (workingDir) => { } }); - const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); - for(const translationFile of translationFiles){ - - const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); - if(messageFileContent !== ''){ - const newMessageContent = messageFileContent.split('\n').map(message => { - if(!message.toString().includes('cht-stock-monitoring-workflow.stock_count') && message.toString()!==''){ - return `${message.toString()}\n`; - } - }); - - fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); - fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); - } - } }; module.exports = { From ddeeabee9b6f969785a15eca62dbaa61d0fbf8fe Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 5 Nov 2024 11:48:32 +0100 Subject: [PATCH 4/6] fix: feedback from review and update old test cases --- .eslintrc | 3 + test/stock-count.spec.js | 79 ++++++++------------ test/stock-out-integration.spec.js | 111 ++++++++++------------------- test/test-utils.js | 44 +++++++++++- 4 files changed, 110 insertions(+), 127 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0a019e4..c493cbe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -32,5 +32,8 @@ "SwitchCase": 1 } ] + }, + "globals": { + "jest": true } } \ No newline at end of file diff --git a/test/stock-count.spec.js b/test/stock-count.spec.js index 74e007f..f0c5a53 100644 --- a/test/stock-count.spec.js +++ b/test/stock-count.spec.js @@ -1,79 +1,60 @@ const { spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs-extra'); -const ExcelJS = require('exceljs'); const { stockCountScenario } = require('./mocks/mocks'); const { setDirToprojectConfig, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp, + readDataFromXforms } = require('./test-utils'); describe('Stock count', () => { const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx']; + beforeEach(() => { setDirToprojectConfig(); }); afterEach(() => { + cleanUp(workingDir, createdAppFormFiles); revertBackToProjectHome(workingDir); }); - it('Add stock count summaries test', async() => { + it('Add stock count integration test', async() => { const processDir = process.cwd(); + // Check that stock count xform and properties files does not exist + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + const childProcess = spawnSync('../../main.js', stockCountScenario.initScenario); if (childProcess.error) { throw childProcess.error; - } else { - const formPath = path.join(processDir, 'forms', 'app', `stock_count.xlsx`); - const formPropertiesPath = path.join(processDir, 'forms', 'app', `stock_count.properties.json`); - const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); - - // Check that stock monitoring is initialized and stock count xform is generated - expect(fs.existsSync(stockMonitoringConfig)).toBe(true); - expect(fs.existsSync(formPropertiesPath)).toBe(true); - expect(fs.existsSync(formPath)).toBe(true); - - // Check that the products are available in stock count xform - const productCategoryList = stockCountScenario.productCategoryScenario; - const productsList = stockCountScenario.productsScenario; - const workbook = new ExcelJS.Workbook(); - await workbook.xlsx.readFile(formPath); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const cellProductCategoriesList = []; - const cellProductsList = []; - let productCatIndex =0; - let productIndex = 0; - nameCol.eachCell(function(cell){ - - if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ - cellProductCategoriesList.push(cell.value); - productCatIndex ++; - productIndex = 0; - } - - if(cell.value === productsList[productIndex] && productIndex < productsList.length){ - cellProductsList.push(cell.value); - productIndex ++; - } - - }); - - expect(productsList.length).toBe(cellProductsList.length); - expect(productsList.entries).toStrictEqual(cellProductsList.entries); - - expect(productCategoryList.length).toBe(cellProductCategoriesList.length); - expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); - - //Removing the stock monitoring init file and stock count file - expect(fs.unlinkSync(stockMonitoringConfig)).toBe(undefined); - expect(fs.unlinkSync(formPath)).toBe(undefined); - expect(fs.unlinkSync(formPropertiesPath)).toBe(undefined); } + + const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); + + // Check that stock monitoring is initialized and stock count xform is generated + expect(fs.existsSync(stockMonitoringConfig)).toBe(true); + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); + } + + // Check that the products and categories are available in stock count xform + const { productsList, productCategoryList } = await readDataFromXforms(stockCountScenario.productCategoryScenario, stockCountScenario.productsScenario, 'stock_count.xlsx'); + + expect(productsList.length).toBe(stockCountScenario.productsScenario.length); + expect(productsList.entries).toStrictEqual(stockCountScenario.productsScenario.entries); + expect(productCategoryList.length).toBe(stockCountScenario.productCategoryScenario.length); + expect(productCategoryList.entries).toStrictEqual(stockCountScenario.productCategoryScenario.entries); + }); }); diff --git a/test/stock-out-integration.spec.js b/test/stock-out-integration.spec.js index b699545..0840212 100644 --- a/test/stock-out-integration.spec.js +++ b/test/stock-out-integration.spec.js @@ -1,108 +1,69 @@ const { spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs-extra'); -const ExcelJS = require('exceljs'); const { stockOutScenario, stockCountScenario } = require('./mocks/mocks'); const { setDirToprojectConfig, revertBackToProjectHome, - cleanUp + cleanUp, + readDataFromXforms } = require('./test-utils'); describe('Stock out integration test', () => { const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx', 'stock_out.properties.json', 'stock_out.xlsx']; + beforeEach(() => { setDirToprojectConfig(); }); afterEach(async() => { + cleanUp(workingDir, createdAppFormFiles); revertBackToProjectHome(workingDir); }); it('Add stock out integration test', async() => { const processDir = process.cwd(); - const workbook = new ExcelJS.Workbook(); - const childProcess = await spawnSync('../../main.js', stockOutScenario.initScenario); + + // Check that stock count and stock out xform and properties files does not exist + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + + const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); if (childProcess.error) { throw childProcess.error; } - else { - // Check that stock monitoring is initialized and stock count and stock out xform and properties files are generated - const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx']; - - for(const createdAppFormFile of createdAppFormFiles){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); - } - - expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); - - // Check that the products are available in stock count xform - const productCategoryList = stockCountScenario.productCategoryScenario; - const productsList = stockCountScenario.productsScenario; - await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_count.xlsx`)); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const cellProductCategoriesList = []; - const cellProductsList = []; - let productIndex = 0; - let productCatIndex =0; - nameCol.eachCell(function(cell){ - - if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ - cellProductCategoriesList.push(cell.value); - productCatIndex ++; - productIndex = 0; - } - - if(cell.value === productsList[productIndex] && productIndex < productsList.length){ - cellProductsList.push(cell.value); - productIndex ++; - } - - }); - - expect(productsList.length).toBe(cellProductsList.length); - expect(productsList.entries).toStrictEqual(cellProductsList.entries); - - expect(productCategoryList.length).toBe(cellProductCategoriesList.length); - expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); - - // Add stock out feature test - const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); - if (stockOutChildProcess.error) { - throw stockOutChildProcess.error; - } - else { - const createdStockOutAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; - for(const createdAppFormFile of createdStockOutAppFormFiles){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); - } - - // Check that the products are available in stock out xform - const stockOutProductsList = stockOutScenario.productsScenario; - await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_out.xlsx`)); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const stockOutCellProductsList = []; - productIndex = 0; - nameCol.eachCell(function(cell){ - if(cell.value === stockOutProductsList[productIndex] && productIndex < stockOutProductsList.length){ - stockOutCellProductsList.push(cell.value); - productIndex ++; - } - }); - - expect(stockOutProductsList.length).toBe(stockOutCellProductsList.length); - expect(stockOutProductsList.entries).toStrictEqual(stockOutCellProductsList.entries); - } - - cleanUp(workingDir); + + // Add stock out feature test + const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); + if (stockOutChildProcess.error) { + throw stockOutChildProcess.error; + } + + expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); } + // Check that the products and categories are available in stock count xform + const { productsList, productCategoryList } = await readDataFromXforms(stockCountScenario.productCategoryScenario, stockCountScenario.productsScenario, 'stock_count.xlsx'); + + expect(productsList.length).toBe(stockCountScenario.productsScenario.length); + expect(productsList.entries).toStrictEqual(stockCountScenario.productsScenario.entries); + expect(productCategoryList.length).toBe(stockCountScenario.productCategoryScenario.length); + expect(productCategoryList.entries).toStrictEqual(stockCountScenario.productCategoryScenario.entries); + + // Check that the products are available in stock out xform + const stockOutProducts = await readDataFromXforms([], stockOutScenario.productsScenario, 'stock_out.xlsx'); + expect(stockOutScenario.productsScenario.length).toBe(stockOutProducts.productsList.length); + expect(stockOutScenario.productsScenario.entries).toStrictEqual(stockOutProducts.productsList.entries); + }); }); diff --git a/test/test-utils.js b/test/test-utils.js index 790e9db..0ca5e36 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -1,6 +1,7 @@ const process = require('process'); const path = require('path'); const fs = require('fs-extra'); +const ExcelJS = require('exceljs'); const currentWorkingDirectory = () =>{ return process.cwd(); @@ -15,10 +16,9 @@ const revertBackToProjectHome = (projectHome) =>{ process.chdir(projectHome); }; -const cleanUp = (workingDir) => { +const cleanUp = (workingDir, fileNames) => { const processDir = path.join(workingDir,'test/project-config/'); - const stockOutFormFiles = ['stock_out.xlsx', 'stock_count.xlsx', 'stock_count.properties.json', 'stock_out.properties.json']; - for(const formFile of stockOutFormFiles){ + for(const formFile of fileNames){ fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile)); } @@ -32,11 +32,49 @@ const cleanUp = (workingDir) => { }; +const readDataFromXforms = async (productCategoryScenario, productsScenario, fileName) => { + const projectPath = process.cwd(); + const productCategoryList = []; + const productsList = []; + + const workbook = new ExcelJS.Workbook(); + const xlsx = workbook.xlsx; + await xlsx.readFile(path.join(projectPath, 'forms', 'app', fileName)); + const surveyWorkSheet = workbook.getWorksheet('survey'); + const nameCol = surveyWorkSheet.getColumn('B'); + let productIndex = 0; + let productCatIndex =0; + nameCol.eachCell(function(cell){ + + if(productCategoryScenario !== undefined && productCategoryScenario.length > 0){ + if(cell.value === productCategoryScenario[productCatIndex] && productCatIndex < productCategoryScenario.length){ + productCategoryList.push(cell.value); + productCatIndex ++; + productIndex = 0; + } + } + + if(productsScenario !== undefined && productsScenario.length > 0){ + if(cell.value === productsScenario[productIndex] && productIndex < productsScenario.length){ + productsList.push(cell.value); + productIndex ++; + } + } + }); + + return { + productsList, + productCategoryList + }; + +}; + module.exports = { setDirToprojectConfig, currentWorkingDirectory, revertBackToProjectHome, cleanUp, + readDataFromXforms }; From b34b0709d65d04c2280c082351f0e172d3f97daa Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 5 Nov 2024 16:00:50 +0100 Subject: [PATCH 5/6] fix: better organize test-utils.js --- test/stock-out-feature.spec.js | 16 +++++----------- test/test-utils.js | 7 ++++++- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/test/stock-out-feature.spec.js b/test/stock-out-feature.spec.js index 11f835b..a23ea6e 100644 --- a/test/stock-out-feature.spec.js +++ b/test/stock-out-feature.spec.js @@ -5,24 +5,27 @@ const { mockConfigs } = require('./mocks/mocks'); const { updateStockOut } = require('../src/features/stock-out'); const { setDirToprojectConfig, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp } = require('./test-utils'); describe('updateStockOut', () => { const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; + beforeEach(() => { setDirToprojectConfig(); }); afterEach(() => { + cleanUp(workingDir, createdAppFormFiles); jest.clearAllMocks(); revertBackToProjectHome(workingDir); }); it('should update the stock out form with correct values', async () => { - const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; const processDir = process.cwd(); // Check that stock out xlsx and properties files exist. @@ -73,14 +76,5 @@ describe('updateStockOut', () => { ] }); - // Delete generated stock out files - for(const createdAppFormFile of createdAppFormFiles){ - fs.stat(path.join(processDir, 'forms', 'app', createdAppFormFile), (error) => { - if (!error) { - expect(fs.unlinkSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(undefined); - } - }); - } - }); }); diff --git a/test/test-utils.js b/test/test-utils.js index 0ca5e36..e4c740d 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -19,7 +19,12 @@ const revertBackToProjectHome = (projectHome) =>{ const cleanUp = (workingDir, fileNames) => { const processDir = path.join(workingDir,'test/project-config/'); for(const formFile of fileNames){ - fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile)); + const filePath = path.join(processDir, 'forms', 'app', formFile); + fs.stat(filePath, (error) => { + if (!error) { + fs.unlinkSync(filePath); + } + }); } // Removing the stock monitoring init file and stock count file From 82caf4c6ab5bef2eacd1d98d59005962ec093213 Mon Sep 17 00:00:00 2001 From: Foromo Ernest Teoro Date: Tue, 5 Nov 2024 17:46:46 +0100 Subject: [PATCH 6/6] fix: file content issue --- .eslintrc | 3 + package.json | 2 +- test/mocks/mocks.js | 87 +++++++++++ .../translations/messages-en.properties | 27 ++++ .../translations/messages-fr.properties | 27 ++++ test/stock-count.spec.js | 99 ++++-------- test/stock-out-feature.spec.js | 80 ++++++++++ test/stock-out-integration.spec.js | 71 +++++++++ test/stock-out.spec.js | 147 ------------------ test/test-utils.js | 64 +++++++- 10 files changed, 392 insertions(+), 215 deletions(-) create mode 100644 test/stock-out-feature.spec.js create mode 100644 test/stock-out-integration.spec.js delete mode 100644 test/stock-out.spec.js diff --git a/.eslintrc b/.eslintrc index 0a019e4..c493cbe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -32,5 +32,8 @@ "SwitchCase": 1 } ] + }, + "globals": { + "jest": true } } \ No newline at end of file diff --git a/package.json b/package.json index 0ffb483..1a0fdd2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "scripts": { "cz": "cz", - "test": "jest", + "test": "jest --testTimeout=25000 --runInBand", "semantic-release": "semantic-release", "prepare": "husky" }, diff --git a/test/mocks/mocks.js b/test/mocks/mocks.js index df4ad7b..4e32d0d 100644 --- a/test/mocks/mocks.js +++ b/test/mocks/mocks.js @@ -1,4 +1,91 @@ module.exports = { + stockOutConfigs: { + features: { + stock_count: { + form_name: 'stock_count', + contact_types: [ + { + contact_type: 'c62_chw', + role: 'chw', + place_type: 'c60_chw_site' + }, + { + contact_type: 'c52_supervisor', + role: 'supervisor', + place_type: 'c50_supervision_area' + } + ], + type: 'action', + title: { + en: 'Stock count', + fr: 'Stock count' + } + }, + stock_out: { + form_name: 'stock_out', + formular: 'item_danger_qty', + title: { + en: 'Stock Out Title', + fr: 'Titre du Stock' + }, + }, + }, + levels: { + 1: { + contact_type: 'c62_chw', + role: 'chw', + place_type: 'c62_chw_site' + }, + 2: { + contact_type: 'c52_supervisor', + role: 'supervisor', + place_type: 'c50_supervision_area' + }, + }, + languages: ['en', 'fr'], + items: { + paracetamol: { + name: 'paracetamol', + label: { + en: 'Paracetamol', + fr: 'Paracetamole' + }, + isInSet: 'Y', + set: { + label: { + en: 'Box of 8', + fr: 'Boite de 8' + }, + count: '8' + }, + unit: { + label: { + en: 'Tablet', + fr: 'Comprimes' + } + }, + warning_total: '20', + danger_total: '15', + max_total: '15', + category: 'malaria' + } + }, + categories: { + malaria: { + name: 'malaria', + label: { + fr: 'Categorie' + }, + description: { + fr: 'Categorie' + } + } + }, + useItemCategory: true, + defaultLanguage: 'fr', + version: '1.1.3', + last_update_date: '2024-10-21T11:09:33.013Z' + }, stockCountScenario: { initScenario: [ 'init', diff --git a/test/project-config/translations/messages-en.properties b/test/project-config/translations/messages-en.properties index 5479131..6a619d4 100644 --- a/test/project-config/translations/messages-en.properties +++ b/test/project-config/translations/messages-en.properties @@ -330,3 +330,30 @@ contact.child.mother.indicator.potable.water = Number of households with access contact.child.mother.indicator.cash.transfert = Number of households that have benefited from cash transfers contact.child.mother.indicator.sexual.mutilation = Number of children with sexual mutilations contact.child.mother.indicator.malnutrition = Number of children aged 6-59 months having been screened for malnutrition in a household + +cht-stock-monitoring-workflow.stock_count.balance_fill = Use this form to fill in balances on hand for all commodities as of today +cht-stock-monitoring-workflow.stock_count.commodities_note =

Commodities Balance on hand

+cht-stock-monitoring-workflow.stock_count.message.summary_header = Results/Summary page +cht-stock-monitoring-workflow.stock_count.contact_summary.title = Stock count +cht-stock-monitoring-workflow.stock_count.message.submit_note =

Be sure you Submit to complete this action.

+cht-stock-monitoring-workflow.stock_count.message.summary_note = Stock items you currently have. +cht-stock-monitoring-workflow.stock_count.tasks.stock-count = Stock count +cht-stock-monitoring-workflow.stock_count.forms.additional_doc_title = Stock uses +cht-stock-monitoring-workflow.stock_count.forms.item_used_question = Quantity of {{item}} +cht-stock-monitoring-workflow.stock_count.message.set_unit_constraint_message = Should be in the form x/y for x {{set_label}} and y {{unit_label}} +cht-stock-monitoring-workflow.stock_count.message.unit_quantity_hint = Add the quantity: {{quantity}} {{unit_label}} +cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamol + +cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock out +cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock at hand: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock required: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.summary_header = Summary +cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} has low stock of the following items +cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock out + + + + + + + diff --git a/test/project-config/translations/messages-fr.properties b/test/project-config/translations/messages-fr.properties index 7031adb..c18ee77 100644 --- a/test/project-config/translations/messages-fr.properties +++ b/test/project-config/translations/messages-fr.properties @@ -465,3 +465,30 @@ contact.child.mother.indicator.potable.water = Nombre de ménage qui a accès à contact.child.mother.indicator.cash.transfert = Nombre de ménage qui recoit un cash transfert contact.child.mother.indicator.sexual.mutilation = Nombre d'enfant fille ayant subi une mutilation sexuelle contact.child.mother.indicator.malnutrition = Nombre d\'enfant de 6-59 mois ayant ete depiste de la malnutrition dans un menage + +cht-stock-monitoring-workflow.stock_count.balance_fill = Use this form to fill in balances on hand for all commodities as of today +cht-stock-monitoring-workflow.stock_count.commodities_note =

Commodities Balance on hand

+cht-stock-monitoring-workflow.stock_count.message.summary_header = Results/Summary page +cht-stock-monitoring-workflow.stock_count.contact_summary.title = Stock count +cht-stock-monitoring-workflow.stock_count.message.submit_note =

Be sure you Submit to complete this action.

+cht-stock-monitoring-workflow.stock_count.message.summary_note = Stock items you currently have. +cht-stock-monitoring-workflow.stock_count.tasks.stock-count = Stock count +cht-stock-monitoring-workflow.stock_count.forms.additional_doc_title = Stock uses +cht-stock-monitoring-workflow.stock_count.forms.item_used_question = Quantity of {{item}} +cht-stock-monitoring-workflow.stock_count.message.set_unit_constraint_message = Should be in the form x/y for x {{set_label}} and y {{unit_label}} +cht-stock-monitoring-workflow.stock_count.message.unit_quantity_hint = Add the quantity: {{quantity}} {{unit_label}} +cht-stock-monitoring-workflow.items.paracetamol.label = Paracetamole + +cht-stock-monitoring-workflow.stock_out.tasks.stock_out = Stock épuisé +cht-stock-monitoring-workflow.stock_out.message.stock_at_hand = Stock actuel: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.stock_required = Stock nécessaire: {{qty}} +cht-stock-monitoring-workflow.stock_out.message.summary_header = Résumé +cht-stock-monitoring-workflow.stock_out.message.submit_note = {{name}} a épuisé son stock des éléments suivants: +cht-stock-monitoring-workflow.stock_out.message.summary_note = Stock épuisé + + + + + + + diff --git a/test/stock-count.spec.js b/test/stock-count.spec.js index 839bdf2..f0c5a53 100644 --- a/test/stock-count.spec.js +++ b/test/stock-count.spec.js @@ -1,93 +1,60 @@ -const { fork } = require('child_process'); +const { spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs-extra'); -const { once } = require('events'); -const ExcelJS = require('exceljs'); const { stockCountScenario } = require('./mocks/mocks'); const { setDirToprojectConfig, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp, + readDataFromXforms } = require('./test-utils'); describe('Stock count', () => { + const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx']; + beforeEach(() => { setDirToprojectConfig(); }); afterEach(() => { - revertBackToProjectHome(process.cwd()); + cleanUp(workingDir, createdAppFormFiles); + revertBackToProjectHome(workingDir); }); - it('Add stock count summaries test', async() => { + it('Add stock count integration test', async() => { const processDir = process.cwd(); - const childProcess = fork('../../main.js', stockCountScenario.initScenario); - await once(childProcess, 'close'); - - const formPath = path.join(processDir, 'forms', 'app', `stock_count.xlsx`); - const formPropertiesPath = path.join(processDir, 'forms', 'app', `stock_count.properties.json`); + // Check that stock count xform and properties files does not exist + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + + const childProcess = spawnSync('../../main.js', stockCountScenario.initScenario); + + if (childProcess.error) { + throw childProcess.error; + } + const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); // Check that stock monitoring is initialized and stock count xform is generated expect(fs.existsSync(stockMonitoringConfig)).toBe(true); - expect(fs.existsSync(formPropertiesPath)).toBe(true); - expect(fs.existsSync(formPath)).toBe(true); - - // Check that the products are available in stock count xform - const productCategoryList = stockCountScenario.productCategoryScenario; - const productsList = stockCountScenario.productsScenario; - const workbook = new ExcelJS.Workbook(); - await workbook.xlsx.readFile(formPath); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const cellProductCategoriesList = []; - const cellProductsList = []; - let productCatIndex =0; - let productIndex = 0; - nameCol.eachCell(function(cell){ - - if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ - cellProductCategoriesList.push(cell.value); - productCatIndex ++; - productIndex = 0; - } - - if(cell.value === productsList[productIndex] && productIndex < productsList.length){ - cellProductsList.push(cell.value); - productIndex ++; - } - - }); - - expect(productsList.length).toBe(cellProductsList.length); - expect(productsList.entries).toStrictEqual(cellProductsList.entries); - - expect(productCategoryList.length).toBe(cellProductCategoriesList.length); - expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); - - //Removing the stock monitoring init file and stock count file - expect(fs.unlinkSync(stockMonitoringConfig)).toBe(undefined); - expect(fs.unlinkSync(formPath)).toBe(undefined); - expect(fs.unlinkSync(formPropertiesPath)).toBe(undefined); - - const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); - for(const translationFile of translationFiles){ - - const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); - expect(messageFileContent).not.toBe(''); - const newMessageContent = messageFileContent.split('\n').map(message => { - if(!message.toString().includes('cht-stock-monitoring-workflow') && message.toString()!==''){ - return `${message.toString()}\n`; - } - }); - - expect(newMessageContent.includes('cht-stock-monitoring-workflow')).toBe(false); - fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); - fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); - + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); } + + // Check that the products and categories are available in stock count xform + const { productsList, productCategoryList } = await readDataFromXforms(stockCountScenario.productCategoryScenario, stockCountScenario.productsScenario, 'stock_count.xlsx'); + + expect(productsList.length).toBe(stockCountScenario.productsScenario.length); + expect(productsList.entries).toStrictEqual(stockCountScenario.productsScenario.entries); + expect(productCategoryList.length).toBe(stockCountScenario.productCategoryScenario.length); + expect(productCategoryList.entries).toStrictEqual(stockCountScenario.productCategoryScenario.entries); + }); }); diff --git a/test/stock-out-feature.spec.js b/test/stock-out-feature.spec.js new file mode 100644 index 0000000..3dfb693 --- /dev/null +++ b/test/stock-out-feature.spec.js @@ -0,0 +1,80 @@ +const ExcelJS = require('exceljs'); +const fs = require('fs'); +const path = require('path'); +const { stockOutConfigs } = require('./mocks/mocks'); +const { updateStockOut } = require('../src/features/stock-out'); +const { + setDirToprojectConfig, + revertBackToProjectHome, + cleanUp +} = require('./test-utils'); + +describe('updateStockOut', () => { + const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_out.properties.json', 'stock_out.xlsx']; + + + beforeEach(() => { + setDirToprojectConfig(); + }); + + afterEach(() => { + cleanUp(workingDir, createdAppFormFiles); + jest.clearAllMocks(); + revertBackToProjectHome(workingDir); + }); + + + it('should update the stock out form with correct values', async () => { + const processDir = process.cwd(); + + // Check that stock out xlsx and properties files exist. + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + // Call the function updateStockOut and check that the stock_out files are generated + await updateStockOut(stockOutConfigs); + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); + } + + // Check that stock out files content are correctly written. + const formPath = path.join(processDir, 'forms', 'app', 'stock_out.xlsx'); + const workbook = new ExcelJS.Workbook(); + await workbook.xlsx.readFile(formPath); + const spy = jest.spyOn(workbook, 'getWorksheet'); + const surveyWorkSheet = workbook.getWorksheet('survey'); + expect(spy).toHaveBeenCalledTimes(1); + const settingWorkSheet = workbook.getWorksheet('settings'); + expect(spy).toHaveBeenCalledTimes(2); + expect(surveyWorkSheet).not.toEqual([]); + expect(settingWorkSheet).not.toEqual([]); + + + const propertiesFileContent = fs.readFileSync( + path.join(processDir, 'forms', 'app', 'stock_out.properties.json'), + {encoding: 'utf-8'} + ); + + expect(JSON.parse(propertiesFileContent)).toEqual({ + 'context': { + 'expression': 'user.parent.contact_type === \'c50_supervision_area\'', + 'person': false, + 'place': false + }, + 'icon': 'icon-healthcare-medicine', + 'title': [ + { + 'content': 'Stock Out Title', + 'locale': 'en' + }, + { + 'content': 'Titre du Stock', + 'locale': 'fr' + } + ] + }); + + }); +}); diff --git a/test/stock-out-integration.spec.js b/test/stock-out-integration.spec.js new file mode 100644 index 0000000..0840212 --- /dev/null +++ b/test/stock-out-integration.spec.js @@ -0,0 +1,71 @@ +const { spawnSync } = require('child_process'); +const path = require('path'); +const fs = require('fs-extra'); + +const { stockOutScenario, stockCountScenario } = require('./mocks/mocks'); +const { + setDirToprojectConfig, + revertBackToProjectHome, + cleanUp, + readDataFromXforms +} = require('./test-utils'); + + +describe('Stock out integration test', () => { + const workingDir = process.cwd(); + const createdAppFormFiles = ['stock_count.properties.json', 'stock_count.xlsx', 'stock_out.properties.json', 'stock_out.xlsx']; + + + beforeEach(() => { + setDirToprojectConfig(); + }); + + afterEach(async() => { + cleanUp(workingDir, createdAppFormFiles); + revertBackToProjectHome(workingDir); + }); + + it('Add stock out integration test', async() => { + const processDir = process.cwd(); + + // Check that stock count and stock out xform and properties files does not exist + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(false); + } + + const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); + + if (childProcess.error) { + throw childProcess.error; + } + + // Add stock out feature test + const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); + if (stockOutChildProcess.error) { + throw stockOutChildProcess.error; + } + + expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); + + for(const createdAppFormFile of createdAppFormFiles){ + expect(fs.existsSync(path.join(processDir, 'forms', 'app', createdAppFormFile))).toBe(true); + } + + // Check that the products and categories are available in stock count xform + const { productsList, productCategoryList } = await readDataFromXforms(stockCountScenario.productCategoryScenario, stockCountScenario.productsScenario, 'stock_count.xlsx'); + + expect(productsList.length).toBe(stockCountScenario.productsScenario.length); + expect(productsList.entries).toStrictEqual(stockCountScenario.productsScenario.entries); + expect(productCategoryList.length).toBe(stockCountScenario.productCategoryScenario.length); + expect(productCategoryList.entries).toStrictEqual(stockCountScenario.productCategoryScenario.entries); + + // Check that the products are available in stock out xform + const stockOutProducts = await readDataFromXforms([], stockOutScenario.productsScenario, 'stock_out.xlsx'); + expect(stockOutScenario.productsScenario.length).toBe(stockOutProducts.productsList.length); + expect(stockOutScenario.productsScenario.entries).toStrictEqual(stockOutProducts.productsList.entries); + + }); + +}); + + diff --git a/test/stock-out.spec.js b/test/stock-out.spec.js deleted file mode 100644 index cac2d2d..0000000 --- a/test/stock-out.spec.js +++ /dev/null @@ -1,147 +0,0 @@ -const { spawnSync } = require('child_process'); -const path = require('path'); -const fs = require('fs-extra'); -//const { once } = require('events'); -const ExcelJS = require('exceljs'); - -const { stockOutScenario, stockCountScenario } = require('./mocks/mocks'); -const { - setDirToprojectConfig, - revertBackToProjectHome -} = require('./test-utils'); - - -describe('Stock out', () => { - const workingDir = process.cwd(); - - beforeEach(() => { - revertBackToProjectHome(workingDir); - setDirToprojectConfig(); - }); - - afterEach(async() => { - revertBackToProjectHome(workingDir); - }); - - it('Add stock out summaries test', async() => { - const processDir = process.cwd(); - const workbook = new ExcelJS.Workbook(); - const childProcess = spawnSync('../../main.js', stockOutScenario.initScenario); - - if(childProcess.status === 0) { - // Check that stock monitoring is initialized and stock count and stock out xform and properties files are generated - //const stockMonitoringConfig = path.join(processDir, 'stock-monitoring.config.json'); - - const formFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - for(const formFile of formFiles){ - if(formFile.toString().includes('stock_count') || formFile.toString().includes('stock_out')){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); - } - } - - expect(fs.existsSync(path.join(processDir, 'stock-monitoring.config.json'))).toBe(true); - - // Check that the products are available in stock count xform - const productCategoryList = stockCountScenario.productCategoryScenario; - const productsList = stockCountScenario.productsScenario; - await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_count.xlsx`)); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const cellProductCategoriesList = []; - const cellProductsList = []; - let productIndex = 0; - let productCatIndex =0; - nameCol.eachCell(function(cell){ - - if(cell.value === productCategoryList[productCatIndex] && productCatIndex < productCategoryList.length){ - cellProductCategoriesList.push(cell.value); - productCatIndex ++; - productIndex = 0; - } - - if(cell.value === productsList[productIndex] && productIndex < productsList.length){ - cellProductsList.push(cell.value); - productIndex ++; - } - - }); - - expect(productsList.length).toBe(cellProductsList.length); - expect(productsList.entries).toStrictEqual(cellProductsList.entries); - - expect(productCategoryList.length).toBe(cellProductCategoriesList.length); - expect(productCategoryList.entries).toStrictEqual(cellProductCategoriesList.entries); - - // Add stock out feature test - const stockOutChildProcess = spawnSync('../../main.js', stockOutScenario.addStockOutFeatureScenario); - if(stockOutChildProcess.status === 0){ - const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - for(const formFile of stockOutFormFiles){ - if(formFile.toString().includes('stock_out')){ - expect(fs.existsSync(path.join(processDir, 'forms', 'app', formFile))).toBe(true); - } - } - - // Check that the products are available in stock out xform - const stockOutProductsList = stockOutScenario.productsScenario; - await workbook.xlsx.readFile(path.join(processDir, 'forms', 'app', `stock_out.xlsx`)); - const surveyWorkSheet = workbook.getWorksheet('survey'); - const nameCol = surveyWorkSheet.getColumn('B'); - const stockOutCellProductsList = []; - productIndex = 0; - nameCol.eachCell(function(cell){ - if(cell.value === stockOutProductsList[productIndex] && productIndex < stockOutProductsList.length){ - stockOutCellProductsList.push(cell.value); - productIndex ++; - } - }); - - expect(stockOutProductsList.length).toBe(stockOutCellProductsList.length); - expect(stockOutProductsList.entries).toStrictEqual(stockOutCellProductsList.entries); - - } - - const stockOutFormFiles = fs.readdirSync(path.join(processDir, 'forms', 'app')); - - for(const formFile of stockOutFormFiles){ - if(formFile.toString().includes('stock_out') || formFile.toString().includes('stock_count')){ - expect(fs.unlinkSync(path.join(processDir, 'forms', 'app', formFile))).toBe(undefined); - } - } - - // Removing the stock monitoring init file and stock count file - const stockMonitoringInitPath = path.join(processDir, 'stock-monitoring.config.json'); - //const stockMonitoringInitFile = fs.stat - fs.stat(stockMonitoringInitPath, (error) => { - if (error) { - //console.log(error); - } - else { - expect(fs.unlinkSync(stockMonitoringInitPath)).toBe(undefined); - //console.log(stats); - } - }); - - const translationFiles = fs.readdirSync(path.join(processDir, 'translations')); - for(const translationFile of translationFiles){ - - const messageFileContent = fs.readFileSync(path.join(processDir, 'translations', translationFile), {encoding: 'utf-8'}); - expect(messageFileContent).not.toBe(''); - const newMessageContent = messageFileContent.split('\n').map(message => { - if(!message.toString().includes('cht-stock-monitoring-workflow') && message.toString()!==''){ - return `${message.toString()}\n`; - } - }); - - expect(newMessageContent.includes('cht-stock-monitoring-workflow')).toBe(false); - fs.truncate(path.join(processDir, 'translations', translationFile), 0, function () {}); - fs.writeFile(path.join(processDir, 'translations', translationFile),newMessageContent.toString().replaceAll(',', '')); - } - - } - - }); - -}); - - diff --git a/test/test-utils.js b/test/test-utils.js index a7cf32e..e4c740d 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -1,5 +1,7 @@ const process = require('process'); const path = require('path'); +const fs = require('fs-extra'); +const ExcelJS = require('exceljs'); const currentWorkingDirectory = () =>{ return process.cwd(); @@ -14,10 +16,70 @@ const revertBackToProjectHome = (projectHome) =>{ process.chdir(projectHome); }; +const cleanUp = (workingDir, fileNames) => { + const processDir = path.join(workingDir,'test/project-config/'); + for(const formFile of fileNames){ + const filePath = path.join(processDir, 'forms', 'app', formFile); + fs.stat(filePath, (error) => { + if (!error) { + fs.unlinkSync(filePath); + } + }); + } + + // Removing the stock monitoring init file and stock count file + const stockMonitoringInitPath = path.join(processDir, 'stock-monitoring.config.json'); + fs.stat(stockMonitoringInitPath, (error) => { + if (!error) { + fs.unlinkSync(stockMonitoringInitPath); + } + }); + +}; + +const readDataFromXforms = async (productCategoryScenario, productsScenario, fileName) => { + const projectPath = process.cwd(); + const productCategoryList = []; + const productsList = []; + + const workbook = new ExcelJS.Workbook(); + const xlsx = workbook.xlsx; + await xlsx.readFile(path.join(projectPath, 'forms', 'app', fileName)); + const surveyWorkSheet = workbook.getWorksheet('survey'); + const nameCol = surveyWorkSheet.getColumn('B'); + let productIndex = 0; + let productCatIndex =0; + nameCol.eachCell(function(cell){ + + if(productCategoryScenario !== undefined && productCategoryScenario.length > 0){ + if(cell.value === productCategoryScenario[productCatIndex] && productCatIndex < productCategoryScenario.length){ + productCategoryList.push(cell.value); + productCatIndex ++; + productIndex = 0; + } + } + + if(productsScenario !== undefined && productsScenario.length > 0){ + if(cell.value === productsScenario[productIndex] && productIndex < productsScenario.length){ + productsList.push(cell.value); + productIndex ++; + } + } + }); + + return { + productsList, + productCategoryList + }; + +}; + module.exports = { setDirToprojectConfig, currentWorkingDirectory, - revertBackToProjectHome + revertBackToProjectHome, + cleanUp, + readDataFromXforms };