From 39fe990fac53ce3307ba7e25311919fc61ed4c18 Mon Sep 17 00:00:00 2001 From: Elijah Karari Date: Tue, 6 Jul 2021 10:21:35 +0300 Subject: [PATCH] Improve date handling (#118) * Handle dates with Luxon * Additional format * Feedback * Object type * Welcome back moment * lint * Feedback * Tests + docs * Restructure + more tests * Look at this later * Fix failing test Co-authored-by: Kenn Sippell --- docs/Harness.html | 112 +++++++++++++++--- docs/core-adapter.js.html | 3 +- ..._mock.cht-conf.contact-summary-lib.js.html | 2 +- docs/dev-mode_mock.cht-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 | 56 +++++---- docs/index.html | 2 +- docs/jsdocs.js.html | 2 +- ...k.cht-conf.module_contact-summary-lib.html | 2 +- docs/mock.cht-conf.module_nools-lib.html | 2 +- ...ock.rules-engine.module_rules-emitter.html | 2 +- docs/module-core-adapter.html | 2 +- package-lock.json | 8 +- package.json | 3 +- src/dateUtils.js | 52 ++++++++ src/harness.js | 23 +--- src/toDate.js | 23 ---- test/contact-forms.spec.js | 10 +- test/harness.spec.js | 71 ++++++++++- 21 files changed, 281 insertions(+), 106 deletions(-) create mode 100644 src/dateUtils.js delete mode 100644 src/toDate.js diff --git a/docs/Harness.html b/docs/Harness.html index 392e92df..317ae7cf 100644 --- a/docs/Harness.html +++ b/docs/Harness.html @@ -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,75 @@

userSource:
+ + + + + + + + + + + + + + + + +

userSettingsDoc

+ + + + +
+ `userSettingsDoc` from the HarnessInputs set through the constructor +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Default Value:
+
    +
  • {Object} A constructed object of type `user-settings` https://docs.communityhealthtoolkit.org/core/overview/db-schema/#users based on +known user information
  • +
+ + + +
Source:
+
@@ -1517,7 +1585,7 @@
Properties
Source:
@@ -1717,7 +1785,7 @@
Parameters:
Source:
@@ -1901,7 +1969,7 @@
Parameters:
Source:
@@ -2022,6 +2090,9 @@
Parameters:
Object | +Duration +| + number @@ -2032,7 +2103,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 +2144,7 @@
Parameters:
Source:
@@ -2294,7 +2365,7 @@
Parameters:
Source:
@@ -2404,7 +2475,7 @@

getNowSource:
@@ -2639,7 +2710,7 @@
Properties
Source:
@@ -2990,7 +3061,7 @@
Properties
Source:
@@ -3149,7 +3220,7 @@
Parameters:
Source:
@@ -3651,7 +3722,7 @@
Parameters:
Source:
@@ -3740,6 +3811,9 @@
Parameters:
Date | +DateTime +| + number | @@ -3753,7 +3827,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 @@ -3794,7 +3868,7 @@
Parameters:
Source:
@@ -4076,7 +4150,7 @@

Home

Modules

  • diff --git a/docs/core-adapter.js.html b/docs/core-adapter.js.html index 855005ca..a120344e 100644 --- a/docs/core-adapter.js.html +++ b/docs/core-adapter.js.html @@ -123,6 +123,7 @@

    Source: core-adapter.js

    chtCore.RulesEmitter.initialize({ rules: appSettings.tasks.rules, contact: user, + taskSchedules: rulesSettings.taskSchedules }); } }; @@ -240,7 +241,7 @@

    Home

    Modules

    • diff --git a/docs/dev-mode_mock.cht-conf.contact-summary-lib.js.html b/docs/dev-mode_mock.cht-conf.contact-summary-lib.js.html index 78bf6ebf..196a0a11 100644 --- a/docs/dev-mode_mock.cht-conf.contact-summary-lib.js.html +++ b/docs/dev-mode_mock.cht-conf.contact-summary-lib.js.html @@ -71,7 +71,7 @@

      Home

      Modules

      • diff --git a/docs/dev-mode_mock.cht-conf.nools-lib.js.html b/docs/dev-mode_mock.cht-conf.nools-lib.js.html index 3aebbeee..98f5a3dd 100644 --- a/docs/dev-mode_mock.cht-conf.nools-lib.js.html +++ b/docs/dev-mode_mock.cht-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 a54ca7dd..87e0bf98 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 e56c858c..fcfad01d 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 29b39f20..c7509e92 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 9a57bea8..836249fc 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)) { @@ -217,16 +217,15 @@

                Source: harness.js

                subject: this.options.subject, content: this.options.content, user: this.options.user, + userSettingsDoc: this.userSettingsDoc, }); const xformFilePath = path.resolve(this.options.appXFormFolderPath, `${formName}.xml`); const content = await resolveContent(this.coreAdapter, this.state, options.content, options.subject); - const user = await resolveMock(this.coreAdapter, this.state, options.user); - const contactSummary = options.contactSummary || await this.getContactSummary(content.contact); const serializedContactSummary = serializeContactSummary(contactSummary); - await doLoadForm(this, this.page, xformFilePath, content, user, serializedContactSummary); + await doLoadForm(this, this.page, xformFilePath, content, options.userSettingsDoc, serializedContactSummary); this._state.pageContent = await this.page.content(); return this._state; } @@ -268,15 +267,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); @@ -292,25 +289,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); } @@ -578,6 +564,32 @@

                Source: harness.js

                } set subject(value) { this.options.subject = value; } + + /** + * `userSettingsDoc` from the {@link HarnessInputs} set through the constructor + * @default {Object} A constructed object of type `user-settings` https://docs.communityhealthtoolkit.org/core/overview/db-schema/#users based on + * known user information + */ + get userSettingsDoc() { + if (this.options.userSettingsDoc) { + return this.options.userSettingsDoc; + } + + const user = this.user; + if (!user) { + return undefined; + } + + return { + _id: `org.couchdb.user:${user._id}`, + name: user._id, + type: 'user-settings', + contact_id: user._id, + facility_id: user.parent && user.parent._id, + }; + } + set userSettingsDoc(value) { this.options.userSettingsDoc = value; } + /** * @typedef HarnessState * @property {Object[]} console Each element represents an event within Chrome console. @@ -788,7 +800,7 @@

                Home

                Modules

                • diff --git a/docs/index.html b/docs/index.html index 7ef94c09..4117c670 100644 --- a/docs/index.html +++ b/docs/index.html @@ -141,7 +141,7 @@

                  Home

                  Modules

                  • diff --git a/docs/jsdocs.js.html b/docs/jsdocs.js.html index 9e3cdf1a..50d85b06 100644 --- a/docs/jsdocs.js.html +++ b/docs/jsdocs.js.html @@ -152,7 +152,7 @@

                    Home

                    Modules

                    • diff --git a/docs/mock.cht-conf.module_contact-summary-lib.html b/docs/mock.cht-conf.module_contact-summary-lib.html index 23bcc556..d5b809bd 100644 --- a/docs/mock.cht-conf.module_contact-summary-lib.html +++ b/docs/mock.cht-conf.module_contact-summary-lib.html @@ -123,7 +123,7 @@

                      Home

                      Modules

                      • diff --git a/docs/mock.cht-conf.module_nools-lib.html b/docs/mock.cht-conf.module_nools-lib.html index 3310ad46..883d602c 100644 --- a/docs/mock.cht-conf.module_nools-lib.html +++ b/docs/mock.cht-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 8be62ed9..30a2539c 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 d5ca8cb6..00a309ea 100644 --- a/docs/module-core-adapter.html +++ b/docs/module-core-adapter.html @@ -76,7 +76,7 @@

                            Home

                            Modules

                            • diff --git a/package-lock.json b/package-lock.json index bba572cd..73be4c55 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", @@ -3516,7 +3521,8 @@ "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "dev": true }, "ms": { "version": "2.1.1", diff --git a/package.json b/package.json index 7f43a957..fa4d7a22 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ }, "dependencies": { "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", @@ -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", diff --git a/src/dateUtils.js b/src/dateUtils.js new file mode 100644 index 00000000..95041529 --- /dev/null +++ b/src/dateUtils.js @@ -0,0 +1,52 @@ +const { DateTime, Duration } = require('luxon'); + +const toDate = val => { + let t; + if (DateTime.isDateTime(val)){ + t = 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); + } + 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 Error('Unsupported date value'); +}; + +const toDuration = val => { + let d; + if (Duration.isDuration(val)){ + d = val; + } + if (typeof val === 'object' && d === undefined) { + d = Duration.fromObject(val); + } + 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 Error('Unsupported duration value'); +}; + +module.exports = { + toDate, + toDuration +}; diff --git a/src/harness.js b/src/harness.js index 069da1db..7a56c0bb 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, toDuration } = require('./dateUtils'); const pathToHost = path.join(__dirname, 'form-host/form-host.html'); if (!fs.existsSync(pathToHost)) { @@ -239,15 +239,13 @@ 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) { 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); @@ -263,25 +261,14 @@ 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 */ 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); } 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; 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', diff --git a/test/harness.spec.js b/test/harness.spec.js index 145e297b..53ef7db8 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'; @@ -38,15 +39,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 () => { @@ -58,6 +58,71 @@ describe('Harness tests', () => { patient_age_in_years: '19', }); }); + + it('setNow works with Luxon DateTime', async () => { + const t = DateTime.now(); + await harness.setNow(t); + expect(harness.getNow()).to.equal(t.toMillis()); + }); + + it('setNow throws for invalid date formats', async () => { + try { + await harness.setNow(); + expect.fail('Should throw'); + } catch (err) { + expect(err.message).to.include('undefined date'); + } + }); + + 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'); + 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('#20 - 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'); + }); + + 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', () => {