# Class: Harness

## Harness(optionsopt)

A harness for testing MedicMobile WebApp configurations

## Constructor

#### new Harness(optionsopt)

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`options` | Object | <optional> | Specify the behavior of the Harness ###### Properties
Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`verbose` | boolean | <optional> | false | Detailed console logging when true
`logFormErrors` | boolean | <optional> | false | Errors displayed by forms will be logged via console when true
`directory` | string | <optional> | process' working directory | Path to directory of configuration files being tested
`xformFolderPath` | string | <optional> | path.join(options.directory, 'forms') | Path to directory containing xform files
`appXFormFolderPath` | string | <optional> | path.join(options.xformFolderPath, 'app') | Path used by the loadForm interface
`contactXFormFolderPath` | string | <optional> | path.join(options.xformFolderPath, 'contact') | Path used by the fillContactForm interface
`appSettingsPath` | string | <optional> | path.join(options.directory, 'app_settings.json') | Path to file containing app_settings.json to test
`harnessDataPath` | string | <optional> | path.join(options.directory, 'harness.defaults.json') | Path to harness configuration file
`coreVersion` | string | <optional> | harness configuration file | The version of cht-core to emulate @example "3.8.0"
`user` | HarnessInputs | <optional> | harness configuration file | The default HarnessInputs controlling the environment in which your application is running
`subject` | HarnessInputs | <optional> | harness configuration file | The default HarnessInputs controlling the environment in which your application is running
`content` | HarnessInputs | <optional> | harness configuration file | The default HarnessInputs controlling the environment in which your application is running
`contactSummary` | HarnessInputs | <optional> | harness configuration file | The default HarnessInputs controlling the environment in which your application is running
`headless` | boolean | <optional> | true | The options object is also passed into Puppeteer and can be used to control any of its options
`slowMo` | boolean | <optional> | false | The options object is also passed into Puppeteer and can be used to control any of its options

Source:
  - harness.js, line 44

##### Example

    const Harness = require('medic-conf-test-harness');
    const instance = new Harness({
      verbose: true,
      directory: '/home/me/config-me/',
    });
    await instance.start();
    await instance.setNow('2000-01-01');
    await instance.loadForm('my_xform');
    const result = await instance.fillForm(['first page, first answer', 'first page, second answer'], ['second page, first answer']);
    expect(result.errors).to.be.empty;
    expect(result.report).to.deep.include({
     fields: {
       patient_name: 'Patient Name',
       next_pnc: {
         s_next_pnc: 'no',
         next_pnc_date: '',
       },
     }
    });

### Members

#### consoleErrors

A filtered set of errors inside of state.console. Useful for easy assertions.

Source:
  - harness.js, line 512

##### Example

    expect(harness.consoleErrors).to.be.empty;

#### content

`content` from the HarnessInputs set through the constructor (defaulting to values from harness.defaults.json file)

Source:
  - harness.js, line 538

#### coreVersion

`coreVersion` is the version of the cht-core that is being emulated in testing (eg. 3.9.0)

Source:
  - harness.js, line 533

#### state

Details the current HarnessState of the Harness

Source:
  - harness.js, line 561

#### user

`user` from the HarnessInputs set through the constructor (defaulting to values from harness.defaults.json file)

Source:
  - harness.js, line 521

### Methods

#### (async) clear() → {Promise}

Resets the HarnessState

Source:
  - harness.js, line 167

##### Returns:

Resolves when the state of the harness when cleared

Type
  Promise

#### (async) countTaskDocsByState(optionsopt)

Counts the number of task documents grouped by state. Explanation of task documents and states

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`options` | Object | <optional> | Some options when summarizing the tasks ###### Properties
Name | Type | Attributes | Description
--- | --- | --- | ---
`title` | string | <optional> | Filter task documents counted to only those with emitted `title` equal to this parameter. Filter is skipped if undefined.
`actionForm` | string | <optional> | Filter task documents counted to only those whose action opens the form equal to this parameter. Filter is skipped if undefined.
`ownedBySubject` | boolean | <optional> | Filter task documents counted to only those owned by the subject. Filter is skipped if false.

Source:
  - harness.js, line 386

##### Returns:

Map with keys equal to task document state and values equal to the number of task documents in that state.

##### Example

    const summary = await countTaskDocsByState({ title: 'my-task-title' });
    expect(summary).to.nested.include({
      Complete: 1, // 1 task events were marked as resolved
      Failed: 2,   // 2 task events were not marked as resolved prior to expiring
      Draft: 3,    // 3 task events are in the future
    });

#### (async) fillContactForm(contactType, …answers)

Loads and fills a contact form,

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`contactType` | string |  | Type of contact that should be created
`answers` | Array.<string> | <repeatable> | Provide an array for the answers given on each page. See fillForm for more details.

Source:
  - harness.js, line 209

#### (async) fillForm(load, …answers) → {FillResult}

Fills in a form given some answers

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`load` | Object | string |  | An optional shorthand for loading a form before filling it. If a string is provided, this will be passed to loadForm as the formName. If an Object is provided, it can have attributes { form, user, content, contactSummary }
`answers` | Array.<string> | <repeatable> | Provide an array for the answers given on each page

Source:
  - harness.js, line 300

##### Returns:

The result of filling the form

Type
  FillResult

##### Example

    // Load a form and then fill it in
    await harness.loadForm('my_form');
    const result = await harness.fillForm(['first page first answer', 'first page second answer'], ['second page first answer']);

    // Load and fill a form in one statement
    const result = await harness.fillForm('my_form', ['1', '2'], ['3']});

#### (async) flush(amount)

Increment the current time by an amount

##### Parameters:

Name | Type | Description
--- | --- | ---
`amount` | Object | number | 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.

Source:
  - harness.js, line 269

##### 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) getContactSummary(contactopt, reportsopt, lineageopt) → {ContactSummary}

Obtains the result of the running the contact-summary.js or the compiled contact-summary.templated.js scripts from the project folder

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`contact` | string | <optional> | The contact doc that will be passed into the contactSummary script. Given a {string}, a contact will be loaded and hydrated from HarnessState. If left empty, the subject will be used.
`reports` | Array.<Object> | <optional> | An array of reports associated with contact. If left empty, the contact's reports will be loaded from HarnessState.
`lineage` | Array.<Object> | <optional> | An array of the contact's hydrated ancestors. If left empty, the contact's ancestors will be used from HarnessState.

Source:
  - harness.js, line 617

##### Returns:

The result of the contact summary under test.

Type
  ContactSummary

#### getNow() → {number}

Get the current mock-time. If no time has been set, defaults to the current system time.

Source:
  - harness.js, line 258

##### Returns:

The current mock-time as epoch time (set via `setNow` or `flush`). If time has not been mocked, defaults to the current system clock.

Type
  number

#### (async) getTargets(optionsopt) → {Array.<Target>}

Check the state of targets

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`options` | Object | <optional> | Some options for looking for checking for targets ###### Properties
Name | Type | Attributes | Description
--- | --- | --- | ---
`type` | string | Array.<string> | <optional> | Filter the returns targets to those with an `id` which matches type (when string) or is included in type (when Array).

Source:
  - harness.js, line 422

##### Returns:

An array of targets which would be visible to the user

Type
  Array.<Target>

#### (async) getTasks(optionsopt) → {Array.<Task>}

Check which tasks are visible

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`options` | Object | <optional> | Some options when checking for tasks ###### Properties
Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`title` | string | <optional> |  | Filter the returns tasks to those with attribute `title` equal to this value. Filter is skipped if undefined.
`user` | Object | <optional> | Default specified via constructor | The current logged-in user which is viewing the tasks.
`actionForm` | string | <optional> |  | Filter task documents to only those whose action opens the form equal to this parameter. Filter is skipped if undefined.
`ownedBySubject` | boolean | <optional> |  | Filter task documents to only those owned by the subject. Filter is skipped if false.

Source:
  - harness.js, line 340

##### Returns:

An array of task documents which would be visible to the user given the current HarnessState

Type
  Array.<Task>

#### (async) loadAction(taskDoc)

Simulates the user clicking on an action

##### Parameters:

Name | Type | Description
--- | --- | ---
`taskDoc` | Object | A Task or, if that task has multiple actions then one of the direct actions

Source:
  - harness.js, line 468

##### Example

    // Complete a form on January 1
    await harness.setNow('2000-01-01')
    const initialResult = await harness.fillForm('pnc_followup', ['no'], ['yes', '2000-01-07']);
    expect(initialResult.errors).to.be.empty;

    // Verify a task appears on January 7
    await harness.setNow('2000-01-07');
    const tasks = await harness.getTasks();
    expect(tasks).to.have.property('length', 1);

    // Complete the task's action
    await harness.loadAction(tasks[0]);
    const followupResult = await harness.fillForm(['no_come_back']);
    expect(followupResult.errors).to.be.empty;

    // Verify the task got resolved
    const actual = await harness.getTasks();
    expect(actual).to.be.empty;

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

Load a form from the app folder into the harness for testing

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`formName` | string |  |  | Filename of an Xml file describing an XForm to load for testing
`options` | HarnessInputs | <optional> | Default values specified via constructor | You can override some or all of the HarnessInputs attributes.

Deprecated:
  - Use fillForm interface (#40)
Source:
  - harness.js, line 180

##### Returns:

The current state of the form

Type
  HarnessState

#### pushMockedDoc(…docs)

Push a mocked document directly into the state

##### Parameters:

Name | Type | Attributes | Description
--- | --- | --- | ---
`docs` | Object | <repeatable> | The document to push

Source:
  - harness.js, line 567

#### setNow(now)

Set the current mock-time of the harness. Mocks global time uses sinon

##### Parameters:

Name | Type | Description
--- | --- | ---
`now` | Date | number | string | A Date object or a value which can be parsed into a Date

Source:
  - harness.js, line 242

#### (async) start() → {Promise.Browser}

Starts a virtual browser. Typically put this in your test's before hook or alike.

Source:
  - harness.js, line 128

##### Returns:

Resolves a Puppeteer Browser when the harness is ready.

Type
  Promise.Browser

##### Example

    before(async () => { return await harness.start(); });

#### (async) stop() → {Promise}

Stops and cleans up the virtual browser.

Source:
  - harness.js, line 157

##### Returns:

Resolves when the harness is fully cleaned up.

Type
  Promise

##### Example

    after(async () => { return await harness.stop(); });