From 3a2bd43767a2ba483a93c6f44fc0cf8458a667db Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Fri, 18 Jun 2021 16:58:23 +0300 Subject: [PATCH 01/11] Handle dates with Luxon --- package-lock.json | 5 +++++ package.json | 1 + src/dateUtils.js | 40 ++++++++++++++++++++++++++++++++++++++++ src/harness.js | 19 +++---------------- src/toDate.js | 23 ----------------------- 5 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 src/dateUtils.js delete mode 100644 src/toDate.js diff --git a/package-lock.json b/package-lock.json index 2bd527dd..0d5ec8d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3114,6 +3114,11 @@ "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" }, + "luxon": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.27.0.tgz", + "integrity": "sha512-VKsFsPggTA0DvnxtJdiExAucKdAnwbCCNlMM5ENvHlxubqWd0xhZcdb4XgZ7QFNhaRhilXCFxHuoObP5BNA4PA==" + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", diff --git a/package.json b/package.json index e956ecea..3720030a 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "lodash": "^4.17.15", + "luxon": "^1.27.0", "md5": "^2.3.0", "moment": "^2.24.0", "nools": "^0.4.4", diff --git a/src/dateUtils.js b/src/dateUtils.js new file mode 100644 index 00000000..d55702f1 --- /dev/null +++ b/src/dateUtils.js @@ -0,0 +1,40 @@ +const { DateTime, Duration } = require('luxon'); + +const toDate = val => { + if (DateTime.isDateTime(val)){ + return val; + } else if (typeof val === 'number'){ + return DateTime.fromMillis(val); + } else if (typeof val === 'object' && val.getMonth && typeof val.getMonth === 'function'){ + return DateTime.fromJSDate(val); + } else if (typeof val === 'string' && val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ + return DateTime.fromISO(val); + } else if (typeof val === 'object'){ + return DateTime.fromObject(val); + } else if (typeof val === 'string'){ + return DateTime.fromRFC2822(val); + } + return undefined; +} + +const toDuration = val => { + if (Duration.isDuration(val)){ + return val; + } else if (typeof val === 'object'){ + return Duration.fromObject(val); + } else if (typeof val === 'number'){ + return Duration.fromObject({days: val}); + } else { + return Duration.fromISO(val); + } +} + +const addDate = (start, period) => { + return toDate(start).plus(toDuration(period)); +} + +module.exports = { + addDate, + toDate, + toDuration +}; diff --git a/src/harness.js b/src/harness.js index 3b90ecca..18bbf814 100644 --- a/src/harness.js +++ b/src/harness.js @@ -10,7 +10,7 @@ const uuid = require('uuid/v4'); const devMode = require('./dev-mode'); const coreAdapter = require('./core-adapter'); const ChtCoreFactory = require('./cht-core-factory'); -const toDate = require('./toDate'); +const { toDate, addDate } = require('./dateUtils'); const pathToHost = path.join(__dirname, 'form-host/form-host.html'); if (!fs.existsSync(pathToHost)) { @@ -246,9 +246,7 @@ class Harness { if (!now) { throw Error('undefined date passed to setNow'); } - - const parseableNow = typeof now === 'object' ? now.getTime() : now; - const asTimestamp = toDate(parseableNow).getTime(); + const asTimestamp = toDate(now).toMillis(); this._now = asTimestamp; sinon.useFakeTimers(asTimestamp); return this.page && this.page.evaluate(innerNow => window.now = new Date(innerNow), this._now); @@ -271,18 +269,7 @@ class Harness { */ async flush(amount) { let now = this._now || Date.now(); - if (typeof amount === 'object') { - const { years = 0, days = 0, hours = 0, minutes = 0, seconds = 0, ms = 0 } = amount; - now = now + - years * 1000 * 60 * 60 * 24 * 365 + - days * 1000 * 60 * 60 * 24 + - hours * 1000 * 60 * 60 + - minutes * 1000 * 60 + - seconds * 1000 + - ms; - } else { // shorthand is for days - now += amount * 24 * 60 * 60 * 1000; - } + now = addDate(now, amount); return this.setNow(now); } diff --git a/src/toDate.js b/src/toDate.js deleted file mode 100644 index 5ae0c744..00000000 --- a/src/toDate.js +++ /dev/null @@ -1,23 +0,0 @@ -// TODO: When project code can use moment, replace this with moment - -const toDate = val => { - let parsedDate = new Date(val); - if (isNaN(parsedDate.getTime())) { - return undefined; - } - - /* - Most date formats are interpretted as local time, but this specific date form is UTC - new Date('2000-01-02').getDate() west of UTC returns 1 and east of UTC returns 2 - This code adjusts new Date() to ignore this - */ - const isIsoInput = typeof val === 'string' && val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/); - if (isIsoInput) { - const timezoneOffset = parsedDate.getTimezoneOffset() * 60 * 1000; - parsedDate = new Date(parsedDate.getTime() + timezoneOffset); - } - - return parsedDate; -}; - -module.exports = toDate; From aa31216b2411bd97328a4898f9bcdb249efaa848 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Fri, 18 Jun 2021 17:37:04 +0300 Subject: [PATCH 02/11] Additional format --- src/dateUtils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dateUtils.js b/src/dateUtils.js index d55702f1..a874062a 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -9,6 +9,8 @@ const toDate = val => { return DateTime.fromJSDate(val); } else if (typeof val === 'string' && val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ return DateTime.fromISO(val); + } else if (typeof val === 'string' && val.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){ + return DateTime.fromFormat(val, 'dd/MM/yyyy'); } else if (typeof val === 'object'){ return DateTime.fromObject(val); } else if (typeof val === 'string'){ From e375fccb0299b8c86f9e8d1964d19160f09d33e1 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Tue, 22 Jun 2021 11:59:35 +0300 Subject: [PATCH 03/11] Feedback --- package-lock.json | 5 ----- package.json | 1 - src/dateUtils.js | 17 +++++++++-------- test/contact-forms.spec.js | 10 +++++----- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d5ec8d8..71ed67ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3518,11 +3518,6 @@ } } }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", diff --git a/package.json b/package.json index 3720030a..bac2ee3e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "lodash": "^4.17.15", "luxon": "^1.27.0", "md5": "^2.3.0", - "moment": "^2.24.0", "nools": "^0.4.4", "pojo2xml": "^1.7.2", "pouchdb": "^7.2.2", diff --git a/src/dateUtils.js b/src/dateUtils.js index a874062a..f99b0c61 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -5,18 +5,19 @@ const toDate = val => { return val; } else if (typeof val === 'number'){ return DateTime.fromMillis(val); - } else if (typeof val === 'object' && val.getMonth && typeof val.getMonth === 'function'){ + } else if (typeof val === 'object' && typeof val.getMonth === 'function'){ return DateTime.fromJSDate(val); - } else if (typeof val === 'string' && val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ - return DateTime.fromISO(val); - } else if (typeof val === 'string' && val.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){ - return DateTime.fromFormat(val, 'dd/MM/yyyy'); - } else if (typeof val === 'object'){ - return DateTime.fromObject(val); } else if (typeof val === 'string'){ + if (val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ + return DateTime.fromISO(val); + } else if (val.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){ + return DateTime.fromFormat(val, 'dd/MM/yyyy'); + } return DateTime.fromRFC2822(val); + } else if (typeof val === 'object'){ + return DateTime.fromObject(val); } - return undefined; + throw 'Unsupported date value'; } const toDuration = val => { diff --git a/test/contact-forms.spec.js b/test/contact-forms.spec.js index 94fc26bc..39edc54c 100644 --- a/test/contact-forms.spec.js +++ b/test/contact-forms.spec.js @@ -1,5 +1,5 @@ const chai = require('chai'); -const moment = require('moment'); +const { DateTime } = require('luxon'); const chaiExclude = require('chai-exclude'); const path = require('path'); const Harness = require('../src/harness'); @@ -22,8 +22,8 @@ describe('contact forms', () => { afterEach(() => { expect(harness.consoleErrors).to.be.empty; }); it('district-hospital with new primary contact', async () => { - const now = moment('2000-01-01'); - await harness.setNow(now.valueOf()); + const now = DateTime.fromISO('2000-01-01'); + await harness.setNow(now); const result = await harness.fillContactForm( 'district_hospital', ['new_person', 'Full', 'Short', '1990-08-06', undefined, '+1-555-227-7744', undefined, 'female', 'patient'], @@ -139,8 +139,8 @@ describe('contact forms', () => { }); it('form without pages', async () => { - const now = moment('2000-01-01'); - await harness.setNow(now.valueOf()); + const now = DateTime.fromISO('2000-01-01'); + await harness.setNow(now); const result = await harness.fillContactForm('no_pages', [ undefined, 'chw', '123', 'full name', '1990-10-08', undefined, 'male', '555-123-4567', 'no', 'english', From 7393bff7eec71991be98a48034f1f6f2e85a398d Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Tue, 22 Jun 2021 12:03:22 +0300 Subject: [PATCH 04/11] Object type --- src/dateUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dateUtils.js b/src/dateUtils.js index f99b0c61..0ded51bd 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -5,8 +5,6 @@ const toDate = val => { return val; } else if (typeof val === 'number'){ return DateTime.fromMillis(val); - } else if (typeof val === 'object' && typeof val.getMonth === 'function'){ - return DateTime.fromJSDate(val); } else if (typeof val === 'string'){ if (val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ return DateTime.fromISO(val); @@ -15,6 +13,9 @@ const toDate = val => { } return DateTime.fromRFC2822(val); } else if (typeof val === 'object'){ + if (typeof val.getMonth === 'function'){ + return DateTime.fromJSDate(val); + } return DateTime.fromObject(val); } throw 'Unsupported date value'; From 4a6f36ecd1ba00fe214bd407453f9deb6a9031a1 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Tue, 22 Jun 2021 12:11:31 +0300 Subject: [PATCH 05/11] Welcome back moment --- package-lock.json | 6 ++++++ package.json | 1 + 2 files changed, 7 insertions(+) diff --git a/package-lock.json b/package-lock.json index 71ed67ac..5127b944 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3518,6 +3518,12 @@ } } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "dev": true + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", diff --git a/package.json b/package.json index bac2ee3e..d30ac8b6 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "jsdoc": "^3.6.3", "medic-enketo-xslt": "^1.5.0", "mocha": "^6.1.4", + "moment": "^2.29.1", "openrosa-xpath-evaluator": "^1.5.1", "raw-loader": "^1.0.0", "rewire": "^4.0.1", From e661dba392076aa4dc00e594422b632994f2a5c5 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Tue, 22 Jun 2021 12:28:06 +0300 Subject: [PATCH 06/11] lint --- src/dateUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dateUtils.js b/src/dateUtils.js index 0ded51bd..84468c16 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -19,7 +19,7 @@ const toDate = val => { return DateTime.fromObject(val); } throw 'Unsupported date value'; -} +}; const toDuration = val => { if (Duration.isDuration(val)){ @@ -31,11 +31,11 @@ const toDuration = val => { } else { return Duration.fromISO(val); } -} +}; const addDate = (start, period) => { return toDate(start).plus(toDuration(period)); -} +}; module.exports = { addDate, From 21040500663f1d04883644646166ef915f2615ac Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Sun, 27 Jun 2021 00:02:03 +0300 Subject: [PATCH 07/11] Feedback --- src/dateUtils.js | 55 +++++++++++++++++++++++++------------------- src/harness.js | 4 ++-- test/harness.spec.js | 5 ++-- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/dateUtils.js b/src/dateUtils.js index 84468c16..2bd93f70 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -1,44 +1,51 @@ const { DateTime, Duration } = require('luxon'); const toDate = val => { + let t; if (DateTime.isDateTime(val)){ - return val; - } else if (typeof val === 'number'){ - return DateTime.fromMillis(val); - } else if (typeof val === 'string'){ - if (val.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)){ - return DateTime.fromISO(val); - } else if (val.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){ - return DateTime.fromFormat(val, 'dd/MM/yyyy'); - } - return DateTime.fromRFC2822(val); + t = val; } else if (typeof val === 'object'){ - if (typeof val.getMonth === 'function'){ - return DateTime.fromJSDate(val); + if (val instanceof Date && typeof val.getTime() === 'number'){ + t = DateTime.fromJSDate(val); + } else { + t = DateTime.fromObject(val); } - return DateTime.fromObject(val); + } + if (typeof val === 'number'){ + t = DateTime.fromMillis(val); + } + if (typeof val === 'string'){ + const parsedDate = new Date(val); + if (!isNaN(parsedDate.getTime())){ + t = DateTime.fromJSDate(parsedDate); + } + } + if (t instanceof DateTime && t.isValid){ + return t.toUTC(); } throw 'Unsupported date value'; }; const toDuration = val => { + let d; if (Duration.isDuration(val)){ - return val; + d = val; } else if (typeof val === 'object'){ - return Duration.fromObject(val); - } else if (typeof val === 'number'){ - return Duration.fromObject({days: val}); - } else { - return Duration.fromISO(val); + d = Duration.fromObject(val); } -}; - -const addDate = (start, period) => { - return toDate(start).plus(toDuration(period)); + if (typeof val === 'number'){ + d = Duration.fromObject({days: val}); + } + if (typeof val === 'string'){ + d = Duration.fromISO(val); + } + if (d instanceof Duration && d.isValid){ + return d; + } + throw 'Unsupported duration value'; }; module.exports = { - addDate, toDate, toDuration }; diff --git a/src/harness.js b/src/harness.js index 18bbf814..c9716384 100644 --- a/src/harness.js +++ b/src/harness.js @@ -10,7 +10,7 @@ const uuid = require('uuid/v4'); const devMode = require('./dev-mode'); const coreAdapter = require('./core-adapter'); const ChtCoreFactory = require('./cht-core-factory'); -const { toDate, addDate } = require('./dateUtils'); +const { toDate, toDuration } = require('./dateUtils'); const pathToHost = path.join(__dirname, 'form-host/form-host.html'); if (!fs.existsSync(pathToHost)) { @@ -269,7 +269,7 @@ class Harness { */ async flush(amount) { let now = this._now || Date.now(); - now = addDate(now, amount); + now = toDate(now).plus(toDuration(amount)); return this.setNow(now); } diff --git a/test/harness.spec.js b/test/harness.spec.js index ad33c3ca..71bee9d3 100644 --- a/test/harness.spec.js +++ b/test/harness.spec.js @@ -38,15 +38,14 @@ describe('Harness tests', () => { await harness.setNow('1985-08-06'); await harness.flush({ years: 1, days: 1, hours: 2 }); const now = await harness.getNow(); - // TODO: This is timezone sensitive... - expect(new Date(now).toString()).to.include('Thu Aug 07 1986 02:00:00'); + expect(new Date(now).toUTCString()).to.include('Thu, 07 Aug 1986 02:00:00'); }); it('flush shorthands as days', async () => { await harness.setNow('1985-08-06'); await harness.flush(5); const now = await harness.getNow(); - expect(new Date(now).toString()).to.include('Sun Aug 11 1985 00:00:00'); + expect(new Date(now).toUTCString()).to.include('Sun, 11 Aug 1985 00:00:00'); }); it('control now', async () => { From 0ee8f6d4979ca20c5be2e5189d9d7cdcca6d5061 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Mon, 28 Jun 2021 00:06:28 +0300 Subject: [PATCH 08/11] Tests + docs --- docs/Harness.html | 177 +++++++++++++++--- docs/core-adapter.js.html | 4 +- ...ock.medic-conf.contact-summary-lib.js.html | 2 +- ...dev-mode_mock.medic-conf.nools-lib.js.html | 2 +- ...de_mock.rules-engine.rules-emitter.js.html | 2 +- docs/form-host_form-filler.js.html | 2 +- docs/global.html | 6 +- docs/harness.js.html | 40 ++-- docs/index.html | 4 +- docs/jsdocs.js.html | 2 +- ...medic-conf.module_contact-summary-lib.html | 2 +- docs/mock.medic-conf.module_nools-lib.html | 2 +- ...ock.rules-engine.module_rules-emitter.html | 2 +- docs/module-core-adapter.html | 4 +- src/harness.js | 4 +- test/harness.spec.js | 24 +++ 16 files changed, 207 insertions(+), 72 deletions(-) diff --git a/docs/Harness.html b/docs/Harness.html index b851dc69..7bbb67e6 100644 --- a/docs/Harness.html +++ b/docs/Harness.html @@ -500,7 +500,7 @@
Properties
-HarnessInputs +string @@ -539,7 +539,7 @@
Properties
-HarnessInputs +string @@ -578,7 +578,7 @@
Properties
-HarnessInputs +Object @@ -617,7 +617,7 @@
Properties
-HarnessInputs +Object @@ -886,7 +886,7 @@

consoleE
Source:
@@ -953,7 +953,7 @@

contentSource:
@@ -1015,7 +1015,7 @@

coreVersio
Source:
@@ -1077,7 +1077,7 @@

stateSource:
@@ -1139,7 +1139,7 @@

userSource:
@@ -1517,7 +1517,7 @@
Properties
Source:
@@ -1717,7 +1717,7 @@
Parameters:
Source:
@@ -1901,7 +1901,7 @@
Parameters:
Source:
@@ -2022,6 +2022,9 @@
Parameters:
Object | +Duration +| + number @@ -2032,7 +2035,7 @@
Parameters:
- Either an object describing how far to move forward in time. Has attributes { years, days, hours, minutes, seconds, ms }. Or an number describing how many days to move forward in time. + An object with attributes { years, quarters, months, weeks, days, hours, minutes, seconds, milliseconds } describing how far to move forward in time, a Duration object or a number describing how many days to move forward in time. @@ -2073,7 +2076,7 @@
Parameters:
Source:
@@ -2294,7 +2297,7 @@
Parameters:
Source:
@@ -2404,7 +2407,7 @@

getNowSource:
@@ -2639,7 +2642,7 @@
Properties
Source:
@@ -2990,7 +2993,7 @@
Properties
Source:
@@ -3149,7 +3152,7 @@
Parameters:
Source:
@@ -3207,7 +3210,7 @@
Example
-

(async) loadForm(formName, optionsopt) → {HarnessState}

+

(async) loadForm(formName) → {HarnessState}

@@ -3290,13 +3293,50 @@
Parameters:
- options + options.user + + + + + +string + + + + + + + + + <optional>
+ + + + + + + + + + + + + + + You can override some or all of the HarnessInputs attributes. + + + + + + + options.subject -HarnessInputs +string @@ -3317,7 +3357,85 @@
Parameters:
- Default values specified via constructor + harness configuration file + + + + + You can override some or all of the HarnessInputs attributes. + + + + + + + options.content + + + + + +Object + + + + + + + + + <optional>
+ + + + + + + + + + + + harness configuration file + + + + + You can override some or all of the HarnessInputs attributes. + + + + + + + options.contactSummary + + + + + +Object + + + + + + + + + <optional>
+ + + + + + + + + + + + harness configuration file @@ -3365,7 +3483,7 @@
Parameters:
Source:
@@ -3536,7 +3654,7 @@
Parameters:
Source:
@@ -3625,6 +3743,9 @@
Parameters:
Date | +DateTime +| + number | @@ -3638,7 +3759,7 @@
Parameters:
- A Date object or a value which can be parsed into a Date + A Date object, DateTime object or a value which can be parsed into a Date @@ -3679,7 +3800,7 @@
Parameters:
Source:
@@ -3961,7 +4082,7 @@

Home

Modules

  • diff --git a/docs/core-adapter.js.html b/docs/core-adapter.js.html index b2a477e2..69f13c31 100644 --- a/docs/core-adapter.js.html +++ b/docs/core-adapter.js.html @@ -234,13 +234,13 @@

    Source: core-adapter.js


    - Documentation generated by JSDoc 3.6.6 on Fri May 28 2021 10:35:15 GMT-0700 (Pacific Daylight Time) + Documentation generated by JSDoc 3.6.6 on Mon Jun 28 2021 00:03:56 GMT+0300 (East Africa Time)
    diff --git a/docs/dev-mode_mock.medic-conf.contact-summary-lib.js.html b/docs/dev-mode_mock.medic-conf.contact-summary-lib.js.html index 0bf39066..cc2a2199 100644 --- a/docs/dev-mode_mock.medic-conf.contact-summary-lib.js.html +++ b/docs/dev-mode_mock.medic-conf.contact-summary-lib.js.html @@ -71,7 +71,7 @@

    Home

    Modules

    • diff --git a/docs/dev-mode_mock.medic-conf.nools-lib.js.html b/docs/dev-mode_mock.medic-conf.nools-lib.js.html index 0ae7ef41..0cec8c39 100644 --- a/docs/dev-mode_mock.medic-conf.nools-lib.js.html +++ b/docs/dev-mode_mock.medic-conf.nools-lib.js.html @@ -74,7 +74,7 @@

      Home

      Modules

      • diff --git a/docs/dev-mode_mock.rules-engine.rules-emitter.js.html b/docs/dev-mode_mock.rules-engine.rules-emitter.js.html index e2dc3d3a..0d1356cf 100644 --- a/docs/dev-mode_mock.rules-engine.rules-emitter.js.html +++ b/docs/dev-mode_mock.rules-engine.rules-emitter.js.html @@ -173,7 +173,7 @@

        Home

        Modules

        • diff --git a/docs/form-host_form-filler.js.html b/docs/form-host_form-filler.js.html index f723588e..2f77637d 100644 --- a/docs/form-host_form-filler.js.html +++ b/docs/form-host_form-filler.js.html @@ -317,7 +317,7 @@

          Home

          Modules

          • diff --git a/docs/global.html b/docs/global.html index aed69738..4422b129 100644 --- a/docs/global.html +++ b/docs/global.html @@ -240,7 +240,7 @@
            Properties:
            Source:
            @@ -1020,7 +1020,7 @@
            Properties:
            Source:
            @@ -1633,7 +1633,7 @@

            Home

            Modules

            • diff --git a/docs/harness.js.html b/docs/harness.js.html index 779d4f4d..75fd9c7b 100644 --- a/docs/harness.js.html +++ b/docs/harness.js.html @@ -38,7 +38,7 @@

              Source: harness.js

              const devMode = require('./dev-mode'); const coreAdapter = require('./core-adapter'); const ChtCoreFactory = require('./cht-core-factory'); -const toDate = require('./toDate'); +const { toDate, toDuration } = require('./dateUtils'); const pathToHost = path.join(__dirname, 'form-host/form-host.html'); if (!fs.existsSync(pathToHost)) { @@ -82,10 +82,10 @@

              Source: harness.js

              * @param {string} [options.appSettingsPath=path.join(options.directory, 'app_settings.json')] Path to file containing app_settings.json to test * @param {string} [options.harnessDataPath=path.join(options.directory, 'harness.defaults.json')] Path to harness configuration file * @param {string} [options.coreVersion=harness configuration file] The version of cht-core to emulate @example "3.8.0" - * @param {HarnessInputs} [options.user=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running - * @param {HarnessInputs} [options.subject=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running - * @param {HarnessInputs} [options.content=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running - * @param {HarnessInputs} [options.contactSummary=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running + * @param {string} [options.user=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running + * @param {string} [options.subject=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running + * @param {Object} [options.content=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running + * @param {Object} [options.contactSummary=harness configuration file] The default {@link HarnessInputs} controlling the environment in which your application is running * @param {boolean} [options.headless=true] The options object is also passed into Puppeteer and can be used to control [any of its options]{@link https://github.com/GoogleChrome/puppeteer/blob/v1.18.1/docs/api.md#puppeteerlaunchoptions} * @param {boolean} [options.slowMo=false] The options object is also passed into Puppeteer and can be used to control [any of its options]{@link https://github.com/GoogleChrome/puppeteer/blob/v1.18.1/docs/api.md#puppeteerlaunchoptions} */ @@ -108,7 +108,7 @@

              Source: harness.js

              const fileBasedDefaults = loadJsonFromFile(this.options.harnessDataPath); this.defaultInputs = _.defaults( this.options, - _.pick(fileBasedDefaults, 'useDevMode', 'coreVersion'), + fileBasedDefaults, { subject: 'default_subject', user: 'default_user', @@ -201,7 +201,10 @@

              Source: harness.js

              * Load a form from the app folder into the harness for testing * * @param {string} formName Filename of an Xml file describing an XForm to load for testing - * @param {HarnessInputs} [options=Default values specified via constructor] You can override some or all of the {@link HarnessInputs} attributes. + * @param {string} [options.user] You can override some or all of the {@link HarnessInputs} attributes. + * @param {string} [options.subject=harness configuration file] You can override some or all of the {@link HarnessInputs} attributes. + * @param {Object} [options.content=harness configuration file] You can override some or all of the {@link HarnessInputs} attributes. + * @param {Object} [options.contactSummary=harness configuration file] You can override some or all of the {@link HarnessInputs} attributes. * @returns {HarnessState} The current state of the form * @deprecated Use fillForm interface (#40) */ @@ -265,15 +268,13 @@

              Source: harness.js

              /** * Set the current mock-time of the harness. Mocks global time {@link https://sinonjs.org/releases/v1.17.6/fake-timers/|uses sinon} - * @param {Date|number|string} now A Date object or a value which can be parsed into a Date + * @param {Date|DateTime|number|string} now A Date object, {@link https://moment.github.io/luxon/docs/class/src/datetime.js~DateTime.html|DateTime object} or a value which can be parsed into a Date */ setNow(now) { if (!now) { throw Error('undefined date passed to setNow'); } - - const parseableNow = typeof now === 'object' ? now.getTime() : now; - const asTimestamp = toDate(parseableNow).getTime(); + const asTimestamp = toDate(now).toMillis(); this._now = asTimestamp; sinon.useFakeTimers(asTimestamp); return this.page && this.page.evaluate(innerNow => window.now = new Date(innerNow), this._now); @@ -289,25 +290,14 @@

              Source: harness.js

              /** * Increment the current time by an amount - * @param {Object|number} amount Either an object describing how far to move forward in time. Has attributes { years, days, hours, minutes, seconds, ms }. Or an number describing how many days to move forward in time. + * @param {Object|Duration|number} amount An object with attributes { years, quarters, months, weeks, days, hours, minutes, seconds, milliseconds } describing how far to move forward in time, a {@link https://moment.github.io/luxon/docs/class/src/duration.js~Duration.html|Duration object} or a number describing how many days to move forward in time. * @example * await flush({ years: 1, minutes: 5 }); // move one year and 5 minutes forward in time * await flush(1); // move one day forward in time */ async flush(amount) { let now = this._now || Date.now(); - if (typeof amount === 'object') { - const { years = 0, days = 0, hours = 0, minutes = 0, seconds = 0, ms = 0 } = amount; - now = now + - years * 1000 * 60 * 60 * 24 * 365 + - days * 1000 * 60 * 60 * 24 + - hours * 1000 * 60 * 60 + - minutes * 1000 * 60 + - seconds * 1000 + - ms; - } else { // shorthand is for days - now += amount * 24 * 60 * 60 * 1000; - } + now = toDate(now).plus(toDuration(amount)); return this.setNow(now); } @@ -785,7 +775,7 @@

              Home

              Modules

              • diff --git a/docs/index.html b/docs/index.html index f38cf146..112910f3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -135,13 +135,13 @@

                Getting Started as a Developer


                - Documentation generated by JSDoc 3.6.6 on Fri May 28 2021 10:35:15 GMT-0700 (Pacific Daylight Time) + Documentation generated by JSDoc 3.6.6 on Mon Jun 28 2021 00:03:56 GMT+0300 (East Africa Time)
                diff --git a/docs/jsdocs.js.html b/docs/jsdocs.js.html index a55a9a78..85d8a38a 100644 --- a/docs/jsdocs.js.html +++ b/docs/jsdocs.js.html @@ -152,7 +152,7 @@

                Home

                Modules

                • diff --git a/docs/mock.medic-conf.module_contact-summary-lib.html b/docs/mock.medic-conf.module_contact-summary-lib.html index fb056a19..50400f56 100644 --- a/docs/mock.medic-conf.module_contact-summary-lib.html +++ b/docs/mock.medic-conf.module_contact-summary-lib.html @@ -123,7 +123,7 @@

                  Home

                  Modules

                  • diff --git a/docs/mock.medic-conf.module_nools-lib.html b/docs/mock.medic-conf.module_nools-lib.html index 6fa816c3..f514a09c 100644 --- a/docs/mock.medic-conf.module_nools-lib.html +++ b/docs/mock.medic-conf.module_nools-lib.html @@ -123,7 +123,7 @@

                    Home

                    Modules

                    • diff --git a/docs/mock.rules-engine.module_rules-emitter.html b/docs/mock.rules-engine.module_rules-emitter.html index aa1773ca..34b8d75c 100644 --- a/docs/mock.rules-engine.module_rules-emitter.html +++ b/docs/mock.rules-engine.module_rules-emitter.html @@ -628,7 +628,7 @@

                      Home

                      Modules

                      • diff --git a/docs/module-core-adapter.html b/docs/module-core-adapter.html index 68dd0e9d..579b57f0 100644 --- a/docs/module-core-adapter.html +++ b/docs/module-core-adapter.html @@ -70,13 +70,13 @@

                        Module: core-adapter


                        - Documentation generated by JSDoc 3.6.6 on Fri May 28 2021 10:35:15 GMT-0700 (Pacific Daylight Time) + Documentation generated by JSDoc 3.6.6 on Mon Jun 28 2021 00:03:56 GMT+0300 (East Africa Time)
                        diff --git a/src/harness.js b/src/harness.js index c9716384..fd384976 100644 --- a/src/harness.js +++ b/src/harness.js @@ -240,7 +240,7 @@ class Harness { /** * Set the current mock-time of the harness. Mocks global time {@link https://sinonjs.org/releases/v1.17.6/fake-timers/|uses sinon} - * @param {Date|number|string} now A Date object or a value which can be parsed into a Date + * @param {Date|DateTime|number|string} now A Date object, {@link https://moment.github.io/luxon/docs/class/src/datetime.js~DateTime.html|DateTime object} or a value which can be parsed into a Date */ setNow(now) { if (!now) { @@ -262,7 +262,7 @@ class Harness { /** * Increment the current time by an amount - * @param {Object|number} amount Either an object describing how far to move forward in time. Has attributes { years, days, hours, minutes, seconds, ms }. Or an number describing how many days to move forward in time. + * @param {Object|Duration|number} amount An object with attributes { years, quarters, months, weeks, days, hours, minutes, seconds, milliseconds } describing how far to move forward in time, a {@link https://moment.github.io/luxon/docs/class/src/duration.js~Duration.html|Duration object} or a number describing how many days to move forward in time. * @example * await flush({ years: 1, minutes: 5 }); // move one year and 5 minutes forward in time * await flush(1); // move one day forward in time diff --git a/test/harness.spec.js b/test/harness.spec.js index 71bee9d3..7cbcf30e 100644 --- a/test/harness.spec.js +++ b/test/harness.spec.js @@ -1,5 +1,6 @@ const path = require('path'); const { expect } = require('chai'); +const { DateTime, Duration } = require('luxon'); const Harness = require('../src/harness'); const formName = 'pnc_followup'; @@ -57,6 +58,29 @@ describe('Harness tests', () => { patient_age_in_years: '19', }); }); + + it('setNow works with DateTime', async () => { + const t = DateTime.now(); + await harness.setNow(t); + expect(harness.getNow()).to.equal(t.toMillis()); + }); + + it('flush works with Duration', async () => { + await harness.setNow('2000-01-01'); + const d = Duration.fromISO('P5Y3M'); // 5 years, 3 months + await harness.flush(d); + const now = await harness.getNow(); + expect(new Date(now).toUTCString()).to.include('Fri, 01 Apr 2005 00:00:00'); + }); + + it('flush accounts for DST', async () => { + const t = DateTime.fromISO('2019-11-03', { zone: 'Canada/Pacific' }); + await harness.setNow(t); + await harness.flush(1); + const now = await harness.getNow(); + const parsed = DateTime.fromMillis(now, { zone: 'Canada/Pacific' }); + expect(parsed.toISO()).to.include('2019-11-03T23:00:00'); + }); }); describe('fillForm', () => { From b94de84bcf052d3cdf870022c23e6a1818ef5408 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Mon, 5 Jul 2021 17:50:04 +0300 Subject: [PATCH 09/11] Restructure + more tests --- src/dateUtils.js | 15 ++++++++------- test/harness.spec.js | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/dateUtils.js b/src/dateUtils.js index 2bd93f70..cb438caf 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -4,12 +4,12 @@ const toDate = val => { let t; if (DateTime.isDateTime(val)){ t = val; - } else if (typeof val === 'object'){ - if (val instanceof Date && typeof val.getTime() === 'number'){ - t = DateTime.fromJSDate(val); - } else { - t = DateTime.fromObject(val); - } + } + if (val instanceof Date && typeof val.getTime() === 'number'){ + t = DateTime.fromJSDate(val); + } + if (typeof val === 'object' && t === undefined){ + t = DateTime.fromObject(val); } if (typeof val === 'number'){ t = DateTime.fromMillis(val); @@ -30,7 +30,8 @@ const toDuration = val => { let d; if (Duration.isDuration(val)){ d = val; - } else if (typeof val === 'object'){ + } + if (typeof val === 'object' && d === undefined){ d = Duration.fromObject(val); } if (typeof val === 'number'){ diff --git a/test/harness.spec.js b/test/harness.spec.js index 7cbcf30e..a81be4ec 100644 --- a/test/harness.spec.js +++ b/test/harness.spec.js @@ -59,13 +59,22 @@ describe('Harness tests', () => { }); }); - it('setNow works with DateTime', async () => { + it('setNow works with Luxon DateTime', async () => { const t = DateTime.now(); await harness.setNow(t); expect(harness.getNow()).to.equal(t.toMillis()); }); - it('flush works with Duration', async () => { + it('setNow throws for invalid date formats', async () => { + expect(harness.setNow, 'notadate').to.throw(); + }); + + xit('flush throws for invalid duration', async () => { + await harness.setNow('2000-01-01'); + expect(await harness.flush, 'notaduration').to.throw(); + }); + + it('flush works with Luxon Duration', async () => { await harness.setNow('2000-01-01'); const d = Duration.fromISO('P5Y3M'); // 5 years, 3 months await harness.flush(d); @@ -73,7 +82,7 @@ describe('Harness tests', () => { expect(new Date(now).toUTCString()).to.include('Fri, 01 Apr 2005 00:00:00'); }); - it('flush accounts for DST', async () => { + it('#20 - flush accounts for DST', async () => { const t = DateTime.fromISO('2019-11-03', { zone: 'Canada/Pacific' }); await harness.setNow(t); await harness.flush(1); @@ -81,6 +90,29 @@ describe('Harness tests', () => { const parsed = DateTime.fromMillis(now, { zone: 'Canada/Pacific' }); expect(parsed.toISO()).to.include('2019-11-03T23:00:00'); }); + + it('setNow works with a variety of date formats', async () => { + let now; + + await harness.setNow('2000-01-01'); + expect(harness.getNow()).to.equal(946684800000); + + await harness.setNow('December 17, 2005'); + now = await harness.getNow(); + expect(new Date(now).toString()).to.include('Sat Dec 17 2005'); + + await harness.setNow('2010 Feb 28'); + now = await harness.getNow(); + expect(new Date(now).toString()).to.include('Sun Feb 28 2010'); + + await harness.setNow('05/20/2010'); + now = await harness.getNow(); + expect(new Date(now).toString()).to.include('Thu May 20 2010'); + + await harness.setNow({ year: 2010, month: 6, day: 1}); + now = await harness.getNow(); + expect(new Date(now).toString()).to.include('Tue Jun 01 2010'); + }); }); describe('fillForm', () => { From 8f0d096810d8439edead0b76dee47079be14abeb Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Mon, 5 Jul 2021 18:45:20 +0300 Subject: [PATCH 10/11] Look at this later --- test/harness.spec.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/harness.spec.js b/test/harness.spec.js index becb0588..97f86fa2 100644 --- a/test/harness.spec.js +++ b/test/harness.spec.js @@ -69,10 +69,11 @@ describe('Harness tests', () => { expect(harness.setNow, 'notadate').to.throw(); }); - xit('flush throws for invalid duration', async () => { - await harness.setNow('2000-01-01'); - expect(await harness.flush, 'notaduration').to.throw(); - }); + // it('flush throws for invalid duration', async () => { + // // bind to correct 'this' context + // await harness.setNow('2000-01-01'); + // expect(await harness.flush, 'notaduration').to.throw(); + // }); it('flush works with Luxon Duration', async () => { await harness.setNow('2000-01-01'); From a4c6d20abb78a47afd0558ab1d81b4eb8be0bcac Mon Sep 17 00:00:00 2001 From: Kenn Sippell Date: Mon, 5 Jul 2021 11:14:53 -0700 Subject: [PATCH 11/11] Fix failing test --- src/dateUtils.js | 8 ++++---- test/harness.spec.js | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/dateUtils.js b/src/dateUtils.js index cb438caf..95041529 100644 --- a/src/dateUtils.js +++ b/src/dateUtils.js @@ -23,7 +23,7 @@ const toDate = val => { if (t instanceof DateTime && t.isValid){ return t.toUTC(); } - throw 'Unsupported date value'; + throw Error('Unsupported date value'); }; const toDuration = val => { @@ -31,7 +31,7 @@ const toDuration = val => { if (Duration.isDuration(val)){ d = val; } - if (typeof val === 'object' && d === undefined){ + if (typeof val === 'object' && d === undefined) { d = Duration.fromObject(val); } if (typeof val === 'number'){ @@ -40,10 +40,10 @@ const toDuration = val => { if (typeof val === 'string'){ d = Duration.fromISO(val); } - if (d instanceof Duration && d.isValid){ + if (d instanceof Duration && d.isValid){ return d; } - throw 'Unsupported duration value'; + throw Error('Unsupported duration value'); }; module.exports = { diff --git a/test/harness.spec.js b/test/harness.spec.js index 97f86fa2..53ef7db8 100644 --- a/test/harness.spec.js +++ b/test/harness.spec.js @@ -66,14 +66,23 @@ describe('Harness tests', () => { }); it('setNow throws for invalid date formats', async () => { - expect(harness.setNow, 'notadate').to.throw(); + try { + await harness.setNow(); + expect.fail('Should throw'); + } catch (err) { + expect(err.message).to.include('undefined date'); + } }); - // it('flush throws for invalid duration', async () => { - // // bind to correct 'this' context - // await harness.setNow('2000-01-01'); - // expect(await harness.flush, 'notaduration').to.throw(); - // }); + it('flush throws for invalid duration', async () => { + await harness.setNow('2000-01-01'); + try { + await harness.flush(); + expect.fail('Should throw'); + } catch (err) { + expect(err.message).to.include('Unsupported duration value'); + } + }); it('flush works with Luxon Duration', async () => { await harness.setNow('2000-01-01');