Using the BYU Event Hub API by Example

The purpose of this blog entry is to provide instruction and a working code example of interacting with BYU's Event Hub API through our API Manager powered by WSO2. I will cover the following: - Setup of a Node.js project - Invoking a managed API through BYU's API Manager - Code examples of an Event Generating Application (EGA) - Code examples of an Event Consuming Application (ECA)

Let's dive right in and start creating a project and code!

Setup of a Node.js project

My examples assume that you have installed Node.js with Node's package manager npm. Install Node.js here (https://nodejs.org/en/download/)

Open a command prompt or terminal. I will be doing all the examples on a Mac OS, so all my commands will be in the form applicable to Apple's default terminal.

Create a new directory for this project:

mkdir eventapplicationdemo

Create a Node.js project inside that directory:

cd eventapplicationdemo
npm init

This will start the commandline wizard for a Node.js project. This is what you should see:

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (eventapplicationdemo) 

You can enter a new name for your application or keep the directory name as is indicated as the default. I recommend pressing enter to use the default choice eventapplicationdemo.

The next line of the wizard asks you to specify the initial version of your application:

version: (1.0.0) 

This line follows the Semantic Versioning scheme found here (http://semver.org/). Because you can only indicate MAJOR.MINOR.PATCH notation, values such as v1 or dev would not be accepted. You could specify 0.0.1 to indicate your first release. But, for simplicity, I'm just going to recommend that you press enter and use the default choice again.

The next line of the wizard asks you to provide a description of the application.

description: 

Let's put in the following for our description: Demo application showcasing Event Hub APIs

The next line of the wizard asks you to provide the entry point.

entry point: (index.js) 

The entry point is the file that will be invoked when consumers of your module use the "require" construct to include it. Keep the default index.js by pressing enter.

The next line of the wizard asks for a test command.

test command: 

We will be using the mocha and chai modules for testing, so enter the following:

mocha test

We will install those modules later, but might as well setup the test command now.

The next line of the wizard asks for a git repository.

git repository: 

We will not create a git repository in this example, so press enter to leave it blank.

The next line of the wizard asks for keywords.

keywords: 

Go ahead and leave these blank as well. Press enter to leave it blank.

The next line of the wizard asks for the name of the author.

author: 

Proudly put your name here:

Matthew Hailstone

And then press enter.

The next line of the wizard asks for the license that the project will be legally bound under.

license: (ISC) 

Notice that the default license is Open Source Initiative license ISC. BYU has decided on using the Apache 2.0 license instead, so enter the following:

Apache-2.0

After pressing enter, you should see something similar to the following:

About to write to /Users/demouser/eventapplicationdemo/package.json:

{
  "name": "eventapplicationdemo",
  "version": "1.0.0",
  "description": "Demo application showcasing Event Hub APIs",
  "main": "index.js",
  "scripts": {
    "test": "mocha test"
  },
  "author": "Matthew Hailstone",
  "license": "Apache-2.0"
}


Is this ok? (yes) 

Press enter again to accept writing the above content to the specified package.json file.

Invoking a managed API through BYU's API Manager

We will want to consume BYU's Event Hub API through BYU's API Manager. I will defer the subscription to the Event Hub API and supporting setup process to the help pages on BYU's Developer Portal found here. The Event Hub API is found here in the API Store.

After completing the setup and subscription steps in the API Store, you will have a consumer key (client ID) and consumer secret (client secret) that represent your client credentials in an OAuth 2.0 authentication/authorization approach to access APIs managed by BYU's API Manager. Learn more on BYU's use of OAuth 2.0 here.

So, let's create some code that will invoke the Event Hub API's /event-types endpoint through the BYU API Manager.

Inside our eventapplicationdemo directory, create an index.js file with the following contents:

'use strict';
const Promise = require('bluebird');
var request = Promise.promisify(require("request"), {multiArgs: true});
Promise.promisifyAll(request, {multiArgs: true});
const byuoauth = require('byu-wabs-oauth');
const oauth = byuoauth(process.env.CLIENT_ID, process.env.CLIENT_SECRET, 'https://api.byu.edu/.well-known/openid-configuration');

function getEventTypes() {

  oauth.getClientGrantAccessToken()
    .then(function (token) {
      request({
        url: "https://api.byu.edu/domains/eventhub/v1/event-types",
        method: "GET",
        headers: {
          Authorization: "Bearer " + token.accessToken,
          Accept: "application/json"
        }
      })
        .then(function (data) {
          if (data[0].statusCode == 200) {
            console.log(data[0].body);
          }
        });
    });
};

getEventTypes();

The getEventTypes function has two main parts of its implementation: - Retrieve an OAuth 2.0 access token - Invoke the /event-types endpoint of the Event Hub API to retrieve a list of declared event types

The byu-wabs-oauth module provides OAuth 2.0 functionality specific to BYU's API Manager. In the above example, we are using the getClientGrantAccessToken function to retrieve a client credential grant type access token. You'll notice that you need to set two environment variables: CLIENT_ID, and CLIENT_SECRET, which are used in initializing the byu-wabs-oauth module. These are the consumer key and consumer secret values you generated when going through the setup process in the BYU API Store.

After retrieving an access token, we use it in the Authorization header in the https://api.byu.edu/domains/eventhub/v1/event-types request defined in the Event Hub API.

Then, we print to the console, the results of a successful response.

In order to run index.js, run the following command in the eventapplicationdemo directory:

npm install --save bluebird request byu-wabs-oauth

This installs the specified modules and saves those dependencies to the package.json file. Your package.json file should now look similar to the following:

{
  "name": "eventapplicationdemo",
  "version": "1.0.0",
  "description": "Demo application showcasing Event Hub APIs",
  "main": "index.js",
  "scripts": {
    "test": "mocha test"
  },
  "author": "Matthew Hailstone",
  "license": "Apache-2.0",
  "dependencies": {
    "bluebird": "^3.5.0",
    "byu-wabs-oauth": "^1.1.0",
    "request": "^2.81.0"
  }
}

Now, we can run the program by running the following command:

node index.js

Create a utility function for retrieving an OAuth 2.0 access token

All the functionality needed to make the request is embedded in the getEventTypes function. If I wanted to make multiple requests to the Event Hub API, I would want to abstract out a utility function that retrieves an access token. This access token could then be used for each separate API call until it expires. I would need a way to determine when the access token expires and retrieve a new one. Let's create such a utility function.

Inside our eventapplicationdemo directory, create a util.js file with the following contents:

const Promise = require('bluebird');
var request = Promise.promisify(require("request"), {multiArgs: true});
Promise.promisifyAll(request, {multiArgs: true});
const byuoauth = require('byu-wabs-oauth');
const oauth = byuoauth(process.env.CLIENT_ID, process.env.CLIENT_SECRET, 'https://api.byu.edu/.well-known/openid-configuration');

var access_token;

exports.makeRequest = function(requestOptions) {
  try {
    if (access_token) {
      if (!requestOptions.headers) {
        requestOptions.headers = {}
      }
      requestOptions.headers["Authorization"] = "Bearer " + access_token;
      return request(requestOptions)
        .then(function (requestResponse) {
          if (requestResponse[0].statusCode == 401) {
            if (requestResponse[0].body.indexOf(access_token + ". Make sure your have given the correct access token") > -1) {
              return callWithNewAccessToken(requestOptions);
            }
            else {
              return requestResponse;
            }
          }
          else {
            return requestResponse;
          }
        })
        .catch(function (error) {
          console.log(error);
        });
    }
    else {
      return callWithNewAccessToken(requestOptions);
    }
  } catch (e) {
    console.log(e);
  }
};

function callWithNewAccessToken(requestOptions) {
  return oauth.getClientGrantAccessToken()
    .then(function (token) {
      access_token = token.accessToken;
      if (!requestOptions.headers) {
        requestOptions.headers = {}
      }
      requestOptions.headers["Authorization"] = "Bearer " + access_token;
      return request(requestOptions);
    });
}

The exported makeRequest function ensures that an access token exists for the provided request options, and if the access token does not exist or has expired, retrieves a new one and retries the request by calling the supporting callWithNewAccessToken function.

I'm sure there are many ways to implement caching an access token, but I wanted to provide at least a first approach example of how this might be done.

Now let's use this new makeRequest utility function in our index.js implementation of retrieving the event types.

Modify index.js to look like the following:

'use strict';
const util = require('./util.js');

function getEventTypes() {
  return util.makeRequest({
    url: "https://api.byu.edu/domains/eventhub/v1/event-types",
    method: "GET",
    headers: {
      Accept: "application/json"
    }
  })
  .then(function (data) {
    if (data[0].statusCode == 200) {
      console.log(data[0].body);
      return;
    }
  });
};

getEventTypes();

This makes the event-types request much more straight forward and simple. Now, we only need to worry about passing the options for a request. In this case, it is the url, method, and Accept header. We could create more API calls as needed and all the OAuth 2.0 authentication/authorization is handled by our utility function.

Now that we have a good scaffolding of invoking the Event Hub API, let's focus on the two types of applications that interact with the Event Hub API. Applications that define domains, entities, event types using the Event Hub API, and that raise events on the Event Hub are labeled as an Event Generating Application or EGA. Applications that subscribe to events, consume and acknowledge events using the Event Hub API, and/or register a webhook to consume events are labeled as an Event Consuming Application or ECA. How you authenticate to the Event Hub API is how you are identified as an EGA/ECA. You can use the same credentials (CLIENT_ID, CLIENT_SECRET) to act both as an EGA and ECA, as we will do to simplify this example, but in practice it is recommended that you have separate credentials for an EGA and ECA.

The following sections are examples of how an EGA and ECA would invoke the Event Hub API.

Code examples of an Event Generating Application (EGA)

To help separate the concern of an Event Generating Application (EGA), inside our eventapplicationdemo directory, create an event_generating_application.js file with the following contents:

'use strict';
const util = require('./util');

exports.createDomain = function (domain_definition) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/domains",
    method: "POST",
    json: true,
    body: domain_definition
  };

  return util.makeRequest(requestOptions);
};

exports.listDomains = function () {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/domains",
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };

  return util.makeRequest(requestOptions);
};

exports.deleteDomain = function (domain) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/domains/"+domain,
    method: "DELETE"
  };

  return util.makeRequest(requestOptions);
};

exports.createEntity = function (entity_definition) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/entities",
    method: "POST",
    json: true,
    body: entity_definition
  };

  return util.makeRequest(requestOptions);
};

exports.listEntities = function () {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/entities",
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };

  return util.makeRequest(requestOptions);
};

exports.listEntity = function (entity_name) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/entities?entity="+entity_name,
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };

  return util.makeRequest(requestOptions);
};

exports.deleteEntity = function (domain, entity_name) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/entities/"+domain+"/"+entity_name,
    method: "DELETE"
  };

  return util.makeRequest(requestOptions);
};

exports.defineEventType = function (event_type_definition) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/event-types",
    method: "POST",
    json: true,
    body: event_type_definition
  };

  return util.makeRequest(requestOptions);
};

exports.listEventTypes = function () {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/event-types",
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };

  return util.makeRequest(requestOptions);
};

exports.listEventType = function (domain, entity_name, event_type) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/event-types?domain="+domain+"&entity="+entity_name+"&event-type="+event_type,
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };

  return util.makeRequest(requestOptions);
};

exports.deleteEventType = function (domain, entity, event_type) {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/event-types/"+domain+"/"+entity+"/"+event_type,
    method: "DELETE"
  };

  return util.makeRequest(requestOptions);
};

exports.raiseEvents = function (events) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/events",
    method: "POST",
    json: true,
    body: events
  };

  return util.makeRequest(requestOptions);
};

Code examples of an Event Consuming Application (ECA)

To help separate the concern of an Event Consuming Application (ECA), inside our eventapplicationdemo directory, create an event_consuming_application.js file with the following contents:

'use strict';
const util = require('./util');

exports.subscribeToEventType = function (subscription) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/subscriptions",
    method: "POST",
    json: true,
    body: subscription
  };

  return util.makeRequest(requestOptions);
};

exports.listSubscriptions = function () {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/subscriptions",
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };
  return util.makeRequest(requestOptions);
};

exports.unsubscribeFromEventType = function (domain, entity, event_type) {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/subscriptions/"+domain+"/"+entity+"/"+event_type,
    method: "DELETE"
  };
  return util.makeRequest(requestOptions);
};

exports.consumeEvents = function () {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/events",
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };
  return util.makeRequest(requestOptions);
};

exports.acknowledgeEvents = function (eventID) {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/events/"+eventID,
    method: "DELETE"
  };
  return util.makeRequest(requestOptions);
};

exports.registerWebhook = function (webhook) {

  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/webhooks",
    method: "POST",
    json: true,
    body: webhook
  };

  return util.makeRequest(requestOptions);
};

exports.listWebhooks = function (eca_identity_id) {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/webhooks?identity_id="+eca_identity_id,
    method: "GET",
    headers: {
      "Accept": "application/json"
    }
  };
  return util.makeRequest(requestOptions);
};

exports.unregisterWebhook = function () {
  let requestOptions = {
    url: "https://api.byu.edu/domains/eventhub/v1/webhooks",
    method: "DELETE"
  };
  return util.makeRequest(requestOptions);
};

Testing the EGA and ECA functions

Now that we have both an EGA abstraction of functions and an ECA abstraction of functions, let's build some tests that will invoke those functions.

For this example, I chosen the chai module to test each function in order of how it may be invoked as an EGA or ECA lifecycle. Inside our eventapplicationdemo directory, create another directory test. Inside that test directory create a test.js file with the following contents:

'use strict';
const expect            = require('chai').expect;
const ega             = require('../event_generating_application');
const eca             = require('../event_consuming_application');
const jp                = require('jsonpath');

const demo_domain = "edu.byu.demo";
const demo_domain_description = "BYU demo domain";
const demo_entity = "Event Hub Demo";
const demo_entity_description = "Demo application showcasing Event Hub APIs";
const demo_event_type = "Test Event";
const demo_webhook_endpoint = "https://origin1.byu.edu/";

describe('Event Hub Demo', ()=> {

  var event_id = "";
  var eca_identity_id = "";

  it('Creates a domain', function() {
    let domain_definition =   {
      "domain_definition": {
        "domain": demo_domain,
        "description": demo_domain_description
      }
    };
    return ega.createDomain(domain_definition)
      .then(function (domainResponse) {
        // console.log(domainResponse[0].body);
        // expect(domainResponse[0].statusCode).to.be.equal(201);
        expect(domainResponse[0].statusCode).to.be.equal(200);
        expect(domainResponse[0].body.domain_definition.domain).to.be.equal(demo_domain);
        expect(domainResponse[0].body.domain_definition.description).to.be.equal(demo_domain_description);
      });
  });

  it('List domains', function() {
    return ega.listDomains()
      .then(function (domainResponse) {
        expect(domainResponse[0].statusCode).to.be.equal(200);
        // console.log(domainResponse[0].body);
      });
  });

  it('Creates an entity', function() {
    let entity_definition =   {
      "entity_definition": {
        "domain": demo_domain,
        "entity": demo_entity,
        "description": demo_entity_description
      }
    };
    return ega.createEntity(entity_definition)
      .then(function (entityResponse) {
        // console.log(entityResponse[0].body);
        // expect(entityResponse[0].statusCode).to.be.equal(201);
        expect(entityResponse[0].statusCode).to.be.equal(200);
        expect(entityResponse[0].body.entity_definition.domain).to.be.equal(demo_domain);
        expect(entityResponse[0].body.entity_definition.entity).to.be.equal(demo_entity);
        expect(entityResponse[0].body.entity_definition.description).to.be.equal(demo_entity_description);
      });
  });

  it('List entities', function() {
    return ega.listEntities()
      .then(function (entityResponse) {
        expect(entityResponse[0].statusCode).to.be.equal(200);
        // console.log(entityResponse[0].body);
      });
  });

  it('List entity', function() {
    return ega.listEntity(demo_entity)
      .then(function (entityResponse) {
        expect(entityResponse[0].statusCode).to.be.equal(200);
        var entity = jp.query(JSON.parse(entityResponse[0].body), "$.entities.entity_definition[?(@.entity == '"+demo_entity+"' && @.domain == '"+demo_domain+"')]");
        expect(entity[0].entity).to.be.equal(demo_entity);
        // console.log(entityResponse[0].body);
      });
  });

  it('Define an event type', function() {
    let event_type_definition =   {
      "event_type_definition": {
        "domain": demo_domain,
        "entity": demo_entity,
        "event_type": demo_event_type,
        "description": demo_event_type,
        "filter_names": ""
      }
    };
    return ega.defineEventType(event_type_definition)
      .then(function (eventTypeResponse) {
        expect(eventTypeResponse[0].statusCode).to.be.equal(200);
        expect(eventTypeResponse[0].body.event_type_definition.domain).to.be.equal(demo_domain);
        expect(eventTypeResponse[0].body.event_type_definition.entity).to.be.equal(demo_entity);
        expect(eventTypeResponse[0].body.event_type_definition.event_type).to.be.equal(demo_event_type);
      });
  });

  it('List event types', function() {
    return ega.listEventTypes()
      .then(function (entityResponse) {
        expect(entityResponse[0].statusCode).to.be.equal(200);
        // console.log(entityResponse[0].body);
      });
  });

  it('List event type', function() {
    return ega.listEventType(demo_domain,demo_entity, demo_event_type)
      .then(function (eventTypeResponse) {
        // console.log(eventTypeResponse[0].body);
        expect(eventTypeResponse[0].statusCode).to.be.equal(200);
        let event_types = JSON.parse(eventTypeResponse[0].body);
        if(Array.isArray(event_types.event_type_definition)) {
          event_types = jp.query(event_types, "$.event_types.event_type_definition[?(@.domain == '"+demo_domain+"' && @.entity == '"+demo_entity+"' && @.event_type == '"+demo_event_type+"')]");
          expect(event_types[0].domain).to.be.equal(demo_domain);
          expect(event_types[0].entity).to.be.equal(demo_entity);
          expect(event_types[0].event_type).to.be.equal(demo_event_type);
        }
        else {
          expect(event_types.event_types.event_type_definition.domain).to.be.equal(demo_domain);
          expect(event_types.event_types.event_type_definition.entity).to.be.equal(demo_entity);
          expect(event_types.event_types.event_type_definition.event_type).to.be.equal(demo_event_type);
        }
      });
  });

  it('Subscribe to event type', function() {
    let subscription = {
      "subscription": {
        "domain": demo_domain,
        "entity": demo_entity,
        "event_type": demo_event_type
      }
    };
    return eca.subscribeToEventType(subscription)
      .then(function (subscriptionResponse) {
        // console.log(subscriptionResponse[0].body);
        // expect(subscriptionResponse[0].statusCode).to.be.equal(201);
        expect(subscriptionResponse[0].statusCode).to.be.equal(200);
        expect(subscriptionResponse[0].body.subscription.domain).to.be.equal(demo_domain);
        expect(subscriptionResponse[0].body.subscription.entity).to.be.equal(demo_entity);
        expect(subscriptionResponse[0].body.subscription.event_type).to.be.equal(demo_event_type);
      });
  });

  it('List subscriptions', function() {
    return eca.listSubscriptions()
      .then(function (subscriptionsResponse) {
        expect(subscriptionsResponse[0].statusCode).to.be.equal(200);

        // console.log(subscriptionsResponse[0].body);
        let subscriptions = JSON.parse(subscriptionsResponse[0].body);
        if(Array.isArray(subscriptions.subscriptions.subscription)) {
          subscriptions = jp.query(subscriptions, "$.subscriptions.subscription[?(@.domain == '"+demo_domain+"' && @.entity == '"+demo_entity+"' && @.event_type == '"+demo_event_type+"')]");
          eca_identity_id = subscriptions[0].eca_identity_id;
          expect(subscriptions[0].domain).to.be.equal(demo_domain);
          expect(subscriptions[0].entity).to.be.equal(demo_entity);
          expect(subscriptions[0].event_type).to.be.equal(demo_event_type);
        }
        else {
          eca_identity_id = subscriptions.subscriptions.subscription.eca_identity_id;
          expect(subscriptions.subscriptions.subscription.domain).to.be.equal(demo_domain);
          expect(subscriptions.subscriptions.subscription.entity).to.be.equal(demo_entity);
          expect(subscriptions.subscriptions.subscription.event_type).to.be.equal(demo_event_type);
        }
      });
  });

  it('Raise event', function() {
    let events = {
      "events": {
        "event": [
          {
            "event_header": {
              "domain": demo_domain,
              "entity": demo_entity,
              "event_type": demo_event_type
            },
            "filters": "",
            "event_body": {
              "hello": "demo"
            }
          }
        ]
      }
    };

    return ega.raiseEvents(events)
      .then(function (eventResponse) {
        // console.log(eventResponse[0].body);
        event_id = eventResponse[0].body.events_return.event_return.event_id;
        expect(eventResponse[0].statusCode).to.be.equal(200);
        expect(eventResponse[0].body.events_return.event_return.domain).to.be.equal(demo_domain);
        expect(eventResponse[0].body.events_return.event_return.entity).to.be.equal(demo_entity);
        expect(eventResponse[0].body.events_return.event_return.event_type).to.be.equal(demo_event_type);
      });
  });

  it('Consume event', function() {
    return eca.consumeEvents()
      .then(function (consumeResponse) {
        // console.log(consumeResponse[0].body);
        expect(consumeResponse[0].statusCode).to.be.equal(200);
        let events = JSON.parse(consumeResponse[0].body);
        if(Array.isArray(events.events.event)) {
          events = jp.query(events.events.event, "$.events.events.event[?(@.event_header.domain == '"+demo_domain+"' && @.event_header.entity == '"+demo_entity+"' && @.event_header.event_type == '"+demo_event_type+"')]");
          expect(events[0].event_header.domain).to.be.equal(demo_domain);
          expect(events[0].event_header.entity).to.be.equal(demo_entity);
          expect(events[0].event_header.event_type).to.be.equal(demo_event_type);
          expect(events[0].event_header.event_id).to.be.equal(event_id);
        }
        else {
          expect(events.events.event.event_header.domain).to.be.equal(demo_domain);
          expect(events.events.event.event_header.entity).to.be.equal(demo_entity);
          expect(events.events.event.event_header.event_type).to.be.equal(demo_event_type);
          expect(events.events.event.event_header.event_id).to.be.equal(event_id);
        }
      });
  });

  it('Acknowledge event', function() {
    return eca.acknowledgeEvents(event_id)
      .then(function (eventResponse) {
        // console.log(eventResponse[0].body);
        // expect(eventResponse[0].statusCode).to.be.equal(204);
        expect(eventResponse[0].statusCode).to.be.equal(200);
      });
  });

  it('Unsubscribe from event type', function() {
    return eca.unsubscribeFromEventType(demo_domain,demo_entity, demo_event_type)
      .then(function (eventTypeResponse) {
        // expect(eventTypeResponse[0].statusCode).to.be.equal(204);
        expect(eventTypeResponse[0].statusCode).to.be.equal(200);
      });
  });

  it('Deletes an event type', function() {
    return ega.deleteEventType(demo_domain,demo_entity, demo_event_type)
      .then(function (eventTypeResponse) {
        // expect(eventTypeResponse[0].statusCode).to.be.equal(204);
        expect(eventTypeResponse[0].statusCode).to.be.equal(200);
      });
  });

  it('Deletes an entity', function() {
    return ega.deleteEntity(demo_domain,demo_entity)
      .then(function (entityResponse) {
        // expect(entityResponse[0].statusCode).to.be.equal(204);
        expect(entityResponse[0].statusCode).to.be.equal(200);
      });
  });

  it('Deletes an domain', function() {
    return ega.deleteDomain(demo_domain,demo_entity)
      .then(function (domainResponse) {
        // expect(domainResponse[0].statusCode).to.be.equal(204);
        expect(domainResponse[0].statusCode).to.be.equal(200);
      });
  });

  it('Register webhook', function() {
    let webhook = {
      "webhook": {
        "identity_id": eca_identity_id,
        "content_type": "application/json",
        "push_option": "Push Message",
        "endpoint": demo_webhook_endpoint
      }
    };

    return eca.registerWebhook(webhook)
      .then(function (webhookResponse) {
        // console.log(webhookResponse[0].body);
        expect(webhookResponse[0].statusCode).to.be.equal(200);
        expect(webhookResponse[0].body.webhook.endpoint).to.be.equal(demo_webhook_endpoint);
        expect(webhookResponse[0].body.webhook.security_option).to.be.equal('HMAC');
      });
  });

  it('List webhook', function() {
    return eca.listWebhooks(eca_identity_id)
      .then(function (webhookResponse) {
        // console.log(webhookResponse[0].body);
        expect(webhookResponse[0].statusCode).to.be.equal(200);

        let webhooks = JSON.parse(webhookResponse[0].body);
          expect(webhooks.webhooks.entity_id).to.be.equal(eca_identity_id);
          expect(webhooks.webhooks.endpoint).to.be.equal(demo_webhook_endpoint);
          expect(webhooks.webhooks.security_option).to.be.equal('HMAC');
      });
  });

  it('Unregister webhook', function() {
    return eca.unregisterWebhook()
      .then(function (webhookResponse) {
        console.log(webhookResponse[0].body);
        // expect(domainResponse[0].statusCode).to.be.equal(204);
        expect(webhookResponse[0].statusCode).to.be.equal(200);
      });
  });
});

In order to run this suite of tests, we need to install the mocha and chai modules. To do this, run the following command:

npm install --save-dev mocha chai

The --save-dev option saves these modules to the devDependencies section of the package.json file. The devDependencies are installed only when creating an environment to run tests. Read more on package.json here.

Now, you can run the tests by running the command:

npm test

The tests show how to structure the payloads of the POST and PUT calls and assert the data in the response.

Well, there you have it: working examples of how to use the BYU Event Hub API. Also, for your reference, the code found in these examples can be found in the GitHub repository here. Hope this tutorial was helpful!

Icon: 

Share this post

Feedback