Writing role based unit tests using the cht test harness tool

Challenge
Unit tests for Tasks requiring the logged-in user role fail given the existing rules.nools.js code extracting the role from a browser cookie.
Node will throw errors since the window object is undefined in the node.js world. Therefore, we had to update the getUserRoles function on rules to look like this,
only this line was updated
var value = typeof window !== 'undefined' ? "; " + document.cookie : '';

Previously var value = "; " + document.cookie;

/**
     * Get the roles of the currently logged in user
     * @return an array of roles e.g ['chew']
     */
var getUserRoles = function() {
      var name = "userCtx";
      var roles = [];
      var value = typeof window !== 'undefined' ? "; " + document.cookie : '';
      var parts = value.split("; " + name + "=");
      if (parts.length == 2) {
        roles = JSON.parse(decodeURIComponent(parts.pop().split(";").shift())).roles;
      }
      return roles;
    };


This will resolve the error -

ReferenceError : window is not defined at object. Node.js



However, the tests will not pass since we do not have the set user role(in the specific test file) exposed
to the rest of the code at rules.nools.js.

Need to access the harness.userRole value at rules.nool.js.

Solution
After sharing the problem with Medic Developers, @derick suggested the use of custom permissions which will enable us to expose the harness user role to the rules.nools.js file.

Steps.

  1. Define the custom permission at app_settings.json
"can_view_moh_515_tasks": [
      "chew",
      "subcounty_focal_person"
    ]
  1. In the test file, add the user role
 harness.user = 'chew_id';
 harness.userRoles = ['chew'];
  1. Subsequently, add a user object at harnes.defaults.json
{
      "_id": "chew_id",
      "name": "CHEW",
      "role": "chew",
      "date_of_birth": "1971-03-10",
      "reported_date": 1550559625153,
      "type": "person",
      "parent": {
        "_id": "branch_id"
      }
    }

Notice we are adding the “role” key and its value. This will come in handy later when we need to also check which specific role is accessing the Task. based on the set permission - can_view_moh_515_tasks

  1. Update the right if conditional at rules.nools.js/**
     * Defined roles in the system
     */
    var ROLES = {
      chew: 'chew',
      facility_in_charge: 'facility_in_charge',
      hro: 'hro',
      subcounty_focal_person: 'subcounty_focal_person',
      branch_manager: 'branch_manager'
    };

if (user && user.parent.type === 'district_hospital' && c.contact && c.contact.type === 'district_hospital') {
      c.reports.forEach(function(r) {
        var userRole = getUserRoles()[0] **|| user.role;** // user.role gets the role value from harness.defaults.json
        var involvedRoles = [ROLES.chew, ROLES.subcounty_focal_person];
        switch (r.form) {
          case 'moh-515-summary-' + ROLES.chew + '-verified':
          case 'moh-515-summary-' + ROLES.subcounty_focal_person + '-verified':
          case 'moh-515-summary-' + ROLES.subcounty_focal_person + '-rejected':
          case 'moh-515-summary':
            schedule = Utils.getSchedule('moh-515-verified');

            // TODO: Think about wrapping this in a function for a more neater/cleaner code
            if (involvedRoles.indexOf(userRole) === -1 && cht.v1.hasPermissions(['can_view_moh_515_tasks']) === false) {
              return;
            }

            if (userRole === ROLES.chew) {
              if (r.form.endsWith('-verified')) return;

              if (r.fields.chew_id !== user._id) return;
            }

            if (userRole === ROLES.subcounty_focal_person) {
              if (r.form.endsWith('-rejected')) return;

              if (r.form.indexOf(userRole) > -1) {
                return;
              }

              if (r.form === 'moh-515-summary') return;
            }

            if (schedule) {
              schedule.events.forEach(function(s) {
                var task = createTask(c, s, r);
                task._id = r._id;
                task.date = Utils.addDate(new Date(r.reported_date), s.days);
                task.resolved = c.reports.some(function(someReport) {
                  if (someReport.form === 'moh_515_verified') {
                    return someReport.fields.feeding_report_id === r._id;
                  }
                  return false;
                });
                var data = {};
                for (key in r.fields) {
                  if (r.fields.hasOwnProperty(key)) {
                    var nk = key;
                    if (key.startsWith("new_")) {
                      nk = key.replace("new_", "");
                    }
                    data["input_" + nk] = r.fields[key];
                  }
                }
                task.actions.push({
                  type: "report",
                  form: "moh_515_verified",
                  label: "MOH 515 Verification",
                  content: {
                    source: "task",
                    source_id: r._id,
                    contact: c.contact,
                    user_role: userRole,
                    data: data,
                    current_user: user,
                    revision_msg: r.status_text ? r.status_text : ''
                  }
                });
                emitTask(task, s);
              });
            }
        }
      });
    }
  1. Run the unit tests
3 Likes