Starting MSL Server

First you need to have Node.JS installed, go to nodejs.org for more about Node.JS
Once you have Node installed, you can install MSL Server from npm to start launching your app locally!

Local install of MSL Server npm package

Use the following command to install MSL Server
npm install msl-server

After the install, you can now launch the server by using the command below
./node_modules/msl-server/bin/msl [options]

Global install of MSL Server npm package

Use the following command to install MSL Server globally
npm install -g msl-server

After the install, you can now launch the server by using the command below
msl [options]

Availabe options for MSL Server

--basedir => specify the root directory(absolute path) of the app you want to launch locally, default is the directory where you run the command.
--port => specify the port that server will be listening on local host, default is 8000.
--debug => specify whether to output log in console or not, default is false.

An example how the options work
msl --basedir=./msl-sample-app --port=8001 --debug=true
*To validate whether your app is running, open up your favorite browser and navigate to http://localhost:<PORT>/<YOUR_FILE>


Choosing Client

Next, you can install the client that will be used to interact with the server. The client is used to set up the mock responses for the requests that will be made by your application running locally on the server. The client is also used to tell the server which requests to intercept for validation. MSL currently supports 3 clients with more language bindings coming soon.

Browser client can be used when you want to execute your test script on the browser (for instance Mocha, Jasmine tests). To use this client, simply add mockapi-browser.min.js to your HTML.

Following is an example of using msl-client-browser on a Jasmine test script:

JasmineSpecRunner.html
<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Jasmine Spec Runner v2.0.0</title>

  <link rel="shortcut icon" type="image/png" href="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine_favicon.png">
  <link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.css">

  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.js"></script>
  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine-html.js"></script>
  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/boot.js"></script>
  
  <!-- include msl browser client -->
  <script src="http://cdnjs.cloudflare.com/ajax/libs/msl-client-browser/1.0.6/mockapi-browser.min.js"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/msl-client-browser/1.0.6/appcontainer-driver.min.js"></script>

  <!-- include jquery library and spec files here-->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script type="text/javascript" src="spec/MSLTestSpec.js"></script>

</head>

<body>
</body>
</html>

To help you execute your scenarios with user interactions on the browser, please include appcontainer-driver.min.js to your HTML. This library will drive the app running on the msl-server inside an iframe.

MSLTestSpec.js
describe('Example suite', function() {

    var callbackFunc = function (req, responseText) {
	return '[' + responseText + ']';
    }
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
	
    beforeEach(function(done) {
        // Load app inside iframe
        openApp('http://localhost:8001/msl-sample-app/index.html');

        setTimeout(function() {
            done();
        }, 200);
    });

    afterEach(function() {
        unRegisterMock('localhost', 8001, "");
    });

    it('Test for register and get mock response', function(done) {
        // Use msl-client to set mock response
        var mockResponse = {};
        mockResponse.requestPath = '/services/getlanguages';
        mockResponse.responseText = '[{"label":"apache"},{"label":"apple"}]';
        mockResponse.statusCode = 200;
        mockResponse.delayTime = 0;
        setMockRespond('localhost', 8001, mockResponse);

        // Type into first input field which triggers a REST call to return a JSON response
        getElement('#autocomplete').val('a');
        getElement('#autocomplete').keydown();

        setTimeout(function() {
            // Validate the drop down is display correctly with mock response
            expect(getElement('ul li:nth-of-type(1)').text()).toBe('apache');
            expect(getElement('ul li:nth-of-type(2)').text()).toBe('apple');

            // Click on the Second item from the drop down
            getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').click();

            // Validate that correct item was selected
            expect(getElement('#autocomplete').val()).toBe('apple');

            done();
        }, 500);
    });
	
	
    it('Test for register and get mock response using function', function(done) {
        // Use msl-client to set mock response
        var mockResponse = {};
        mockResponse.requestPath = '/services/getlanguages';
        mockResponse.responseText = '{"label":"apache"},{"label":"apple"}';
	mockResponse.eval = callbackFunc;
        mockResponse.statusCode = 200;
        mockResponse.delayTime = 0;
        setMockRespond('localhost', 8001, mockResponse);

        // Type into first input field which triggers a REST call to return a JSON response
        getElement('#autocomplete').val('a');
        getElement('#autocomplete').keydown();

        setTimeout(function() {
            // Validate the drop down is display correctly with mock response
            expect(getElement('ul li:nth-of-type(1)').text()).toBe('apache');
            expect(getElement('ul li:nth-of-type(2)').text()).toBe('apple');

            // Click on the Second item from the drop down
            getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').click();

            // Validate that correct item was selected
            expect(getElement('#autocomplete').val()).toBe('apple');

            done();
        }, 500);
    });
	
    it('Test setup mock response with template', function(done) {

        // Registering the template that will be used for the response
        registerTemplate('localhost', 8001,
            '[{"label":"{{param1}}"},{"label":"{{param2}}"}]', 'example');
        // Set up the object that contains our response configuration
        var configurations = {};
        configurations.requestPath = '/services/getlanguages';
        configurations.contentType = 'application/json';
        configurations.id = 'example';
        configurations.keyValues = {
            'param1': 'Boat',
            'param2': 'Cat'
        };
        configurations.statusCode = 200;
        configurations.delayTime = 0;
        // Use msl-client to set mock response
        setMockRespond('localhost', 8001, configurations);

        // Type into first input field which triggers a REST call to return a JSON response
        getElement('#autocomplete').val('b');
        getElement('#autocomplete').keydown();

        setTimeout(function() {
            // Validate the drop down is display correctly with mock response using template
            expect(getElement('ul li:nth-of-type(1)').text()).toBe('Boat');
            expect(getElement('ul li:nth-of-type(2)').text()).toBe('Cat');

            // Click on the first item from the drop down
            getElement('.ui-autocomplete .ui-menu-item:nth-of-type(1)').click();

            // Validate that correct item was selected
            expect(getElement('#autocomplete').val()).toBe('Boat');

            done();
        }, 500);
    });

    it('Test XHR intercept, Get method', function(done) {
        // Use msl-client to register intercept
        setInterceptXHR('localhost', 8001, '/services/getservice');

        // Type into second input field and click GET button which triggers a GET request
        getElement('#getInput').val('testGet');
        getElement('#getRequest').click();

        // Retrieve intercepted XHR and validate correct GET request was made by the app
        getInterceptedXHR('localhost', 8001, '/services/getservice', function(resp) {
            var intrReq = JSON.parse(resp).xhr_1;
            expect(intrReq.xhr.url).toBe('/services/getservice?term=testGet');
            expect(intrReq.xhr.method).toBe('GET');
        });
        done();
    });
    
    it('Test XHR intercept, Post method', function(done) {
        // Use msl-client to register intercept
        setInterceptXHR('localhost', 8001, '/services/postservice');

        // Type into second input field and click GET button which triggers a GET request
        getElement('#output-box').val('testPost');
        getElement('#postRequest').click();

        setTimeout(function() {
            // Retrieve intercepted XHR and validate correct POST request was made by the app
            getInterceptedXHR('localhost', 8001, '/services/postservice', function(resp) {
                var intrReq = JSON.parse(resp).xhr_1;
		var regex = new RegExp('timestamp=\\d*&text=testPost');
		expect(intrReq.xhr.url).toBe('/services/postservice');
		expect(regex.test(intrReq.post)).toBe(true);
		expect(intrReq.xhr.method).toBe('POST');
            });
            
	    done();
        }, 500);
    });

    it('Test for setting the delay time of returning a mock response', function(done) {
        // Use msl-client to set mock response
        var mockResponse = {};
        mockResponse.requestPath = '/services/getlanguages';
        mockResponse.responseText = '[{"label":"apache"},{"label":"apple"}]';
        mockResponse.statusCode = 200;
        mockResponse.delayTime = 3000;
        setMockRespond('localhost', 8001, mockResponse);

        // Type into first input field which triggers a REST call to return a JSON response
        getElement('#autocomplete').val('a');
        getElement('#autocomplete').keydown();

        setTimeout(function() {
            // Validate that the response is delayed
            expect(getElement('.ui-autocomplete .ui-menu-item:nth-of-type(1)').size()).toBe(0);
            expect(getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').size()).toBe(0);
        }, 500);

        setTimeout(function() {
            // Validate the drop down is display correctly with mock response
            expect(getElement('ul li:nth-of-type(1)').text()).toBe('apache');
            expect(getElement('ul li:nth-of-type(2)').text()).toBe('apple');

            // Click on the Second item from the drop down
            getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').click();

            // Validate that correct item was selected
            expect(getElement('#autocomplete').val()).toBe('apple');

            done();
        }, 3500);
    });

    it('Test unRegisterMock function', function(done) {
        // Use msl-client to set mock response
        var mockResponse = {};
        mockResponse.requestPath = '/services/getlanguages';
        mockResponse.responseText = '[{"label":"Ice Cream"},{"label":"Candy"}]';
        mockResponse.statusCode = 200;
        mockResponse.delayTime = 0;
        setMockRespond('localhost', 8001, mockResponse);

        // Type into first input field which triggers a REST call to return a JSON response
        getElement('#autocomplete').val('I');
        getElement('#autocomplete').keydown();

        setTimeout(function() {
            // Click on the first item from the drop down
            expect(getElement('ul li:nth-of-type(1)').text()).toBe('Ice Cream');
            expect(getElement('ul li:nth-of-type(2)').text()).toBe('Candy');

            getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').click();

	    setTimeout(function() {
              // Validate that correct item was selected
              expect(getElement('#autocomplete').val()).toBe('Candy');
	      // Reload Page
              openApp('http://localhost:8001/msl-sample-app/index.html');
	      setTimeout(function() {
                unRegisterMock('localhost', 8001, '/services/getlanguages');
              	getElement('#autocomplete').val('I');
                expect(getElement('.ui-autocomplete .ui-menu-item:nth-of-type(2)').size()).toBe(0);
		done();
	      }, 200);
	    }, 500);
	}, 500);
    });

    it('Test mocking POST ajax success', function(done) {
      // Use msl-client to set mock response
      setMockRespond('localhost', 8001, {"requestPath":"/services/postservice", "responseText":'{"outputBoxValue":"hello"}'});

      // Type hellomsl on text area and click POST button
      getElement('#output-box').val('hellomsl');
      getElement('#postRequest').click();
      
      setTimeout(function() {
        // Validate that postResult span is populated with the text 'hello' which was the success call from the ajax call
        expect(getElement('#postResult').text()).toBe('hello');
        done();
      }, 500);
    });
});

You will need to start the MSL server on port 8001 (as shown above) before these tests can be run from the root directory. Once that is done, simply go to http://localhost:8001/test/msl-client-browser/JasmineSpecRunner.html on a browser and you should be able to see the tests execute.
To start things off, you will need to create a new Java project in any IDE and get the necessary libraries. If you create a maven project, then you will just need to include the following dependencies:


POM Snippet:

   <dependency>
      <groupId>org.finra.msl</groupId>
      <artifactId>msl-client-java</artifactId>
      <version>1.0.0</version>
   </dependency>
   <dependency>
      <groupId>org.finra.jtaf</groupId>
      <artifactId>jtaf-extwebdriver</artifactId>
      <version>1.4</version>
   </dependency>

These will get you the Java client API and the ExtWebDriver that will be used in this example to interact with the elements on the page. Along with these libraries, you should also include JUnit 4 which can be done as shown here.

Using the sample app that is on the GitHub project, this example will test some of the core functionality - setting up a mock response using both plain text and a template, getting intercepted HTTP requests for both POST and GET requests, and unregistering a mock when it is no longer needed.

package org.finra.msl.client;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.finra.jtaf.ewd.ExtWebDriver;
import org.finra.jtaf.ewd.session.SessionManager;
import org.finra.jtaf.ewd.widget.element.Element;
import org.finra.jtaf.ewd.widget.element.InteractiveElement;
import org.finra.msl.client.MockAPI;
import org.finra.msl.client.MockAPI.XHR;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

/**
 * Tests for msl-client-java and msl-server
 */
public class MockAPITest {
    public static ExtWebDriver ewd;

    @BeforeClass
    public static void setUp() throws Exception {
        // Get a new ExtWebDriver session
        ewd = SessionManager.getInstance().getNewSession();
    }

    @Before
    public void openApp() {
        // Open the test application
        ewd.open("http://localhost:8001/msl-sample-app/index.html");
    }

    @Test
    public void testTextResponse() throws Exception {
        // Create object for autocomplete element
        InteractiveElement autocomplete = new InteractiveElement(".//*[@id=\"autocomplete\"]");

        // Set up the object that contains our response configuration
        Map configurations = new HashMap();
        configurations.put("requestPath", "/services/getlanguages");
        configurations.put("responseText", "{\"label\":\"Java\"},{\"label\":\"Perl\"}");
        configurations.put("contentType", "application/json");
        configurations.put("eval",
                "function (req,responseText) { return '[' + responseText + ']'; }");
        configurations.put("statusCode", "200");
        configurations.put("delayTime", "0");

        // Setting up the mock response using the configuration
        MockAPI.setMockRespond("localhost", 8001, configurations);

        // Triggering the event
        autocomplete.type("J");

        Element dropdown = new Element(".//ul[contains(@class, \"ui-autocomplete\")]");
        dropdown.waitForVisible();

        // Getting all of the options from the dropdown menu to be validated
        List elements = ewd.findElements(By
                .xpath(".//ul[contains(@class, \"ui-autocomplete\")]/li"));

        // Verify that the options are from the mocked response
        Assert.assertEquals("Java", elements.get(0).getText());
        Assert.assertEquals("Perl", elements.get(1).getText());
    }

    @Test
    public void testTemplateResponse() throws Exception {
        MockAPI.registerTemplate("localhost", 8001,
                "[{\"label\":\"{{param1}}\"},{\"label\":\"{{param2}}\"}]", "example");

        InteractiveElement autocomplete = new InteractiveElement(".//*[@id=\"autocomplete\"]");

        Map configurations = new HashMap();
        configurations.put("requestPath", "/services/getlanguages");
        configurations.put("contentType", "application/json");
        configurations.put("statusCode", "200");
        configurations.put("delayTime", "0");

        Map keyValue = new HashMap();
        keyValue.put("param1", "German");
        keyValue.put("param2", "English");
        configurations.put("keyValues", keyValue);
        configurations.put("id", "example");

        // Setting up the mock response using the configuration
        MockAPI.setMockRespond("localhost", 8001, configurations);

        // Triggering the event
        autocomplete.type("J");

        Element dropdown = new Element(".//ul[contains(@class, \"ui-autocomplete\")]");
        dropdown.waitForVisible();

        // Getting all of the options from the dropdown menu to be validated
        List elements = ewd.findElements(By
                .xpath(".//ul[contains(@class, \"ui-autocomplete\")]/li"));

        // Verify that the options are from the mocked response
        Assert.assertEquals("German", elements.get(0).getText());
        Assert.assertEquals("English", elements.get(1).getText());
    }

    @Test
    public void testGetIntercept() throws Exception {
        MockAPI.setInterceptXHR("localhost", 8001, "/services/getservice");

        InteractiveElement input = new InteractiveElement(".//*[@id=\"getInput\"]");
        input.type("GET Example");

        InteractiveElement button = new InteractiveElement(".//*[@id=\"getRequest\"]");
        button.click();

        // Due to WebDriver operating too quickly sometimes, it is held up so
        // that the web-server has enough time to intercept
        Thread.sleep(5);

        // Get the HTTP requests that have been intercepted
        XHR[] interceptedXHR = MockAPI.getInterceptedXHR("localhost", 8001, "/services/getservice");

        // Verify that the intercepted HTTP request is the one we are looking
        // for by checking its content
        Assert.assertEquals("GET", interceptedXHR[0].getMethodType());
        Assert.assertEquals("/services/getservice?term=GET+Example", interceptedXHR[0].getUrl());
        Assert.assertEquals("GET Example", interceptedXHR[0].getQueryString().get("term"));
    }

    @Test
    public void testPostIntercept() throws Exception {
        // Setting
        MockAPI.setInterceptXHR("localhost", 8001, "/services/postservice");

        InteractiveElement input = new InteractiveElement(".//*[@id=\"output-box\"]");
        input.type("POST Example");

        InteractiveElement button = new InteractiveElement(".//*[@id=\"postRequest\"]");
        button.click();

        // Due to WebDriver operating too quickly sometimes, it is held up so
        // that the web-server has enough time to intercept
        Thread.sleep(5);

        // Get the HTTP requests that have been intercepted
        XHR[] interceptedXHR = MockAPI
                .getInterceptedXHR("localhost", 8001, "/services/postservice");

        // Verify that the intercepted HTTP request is the one we are looking
        // for by checking its content
        Assert.assertEquals("POST", interceptedXHR[0].getMethodType());
        Assert.assertEquals("/services/postservice", interceptedXHR[0].getUrl());
        Assert.assertTrue(interceptedXHR[0].getBody().contains("timestamp="));
        Assert.assertTrue(interceptedXHR[0].getBody().contains("text=POST+Example"));
    }

    @Test
    public void testUnRegisterMock() throws Exception {

        // Create object for autocomplete element
        InteractiveElement autocomplete = new InteractiveElement(".//*[@id=\"autocomplete\"]");

        // Set up the object that contains our response configuration
        Map configurations = new HashMap();
        configurations.put("requestPath", "/services/getlanguages");
        configurations.put("responseText", "[{\"label\":\"Java\"},{\"label\":\"Perl\"}]");
        configurations.put("contentType", "application/json");
        configurations.put("statusCode", "200");
        configurations.put("delayTime", "0");

        // Set up the response using the configuration that was just created
        MockAPI.setMockRespond("localhost", 8001, configurations);

        // Type into the autocomplete to trigger the event
        autocomplete.type("J");

        Element dropdown = new Element(".//ul[contains(@class, \"ui-autocomplete\")]");
        dropdown.waitForVisible();

        List elements = ewd.findElements(By
                .xpath(".//ul[contains(@class, \"ui-autocomplete\")]/li"));

        autocomplete.getWebElement().clear();

        // Verify the dropdown elements
        Assert.assertEquals("Java", elements.get(0).getText());
        Assert.assertEquals("Perl", elements.get(1).getText());

        // Unregister this request so web-server.js no longer responds to it
        MockAPI.unRegisterMock("localhost", 8001, "/services/getlanguages");

        // Trigger event again
        autocomplete.type("J");

        // Verify that the dropdown no longer appears now that there
        // is no response
        Assert.assertEquals(false, !dropdown.isElementPresent());

    }

    @AfterClass
    public static void tearDown() {
        ewd.close();
    }
}


For this to work, you must first start up MSL Server on port 8001(as described above) and, if you want to see what it is doing, you can turn on debug mode as is shown in the example above. Once the server is up and running, you should be able to execute the test to see MSL Server in action using HtmlUnit.

If you would like to have the test execute against your favorite browser or change any other ExtWebDriver options, you will need to include a properties file as shown in the Client Properties page.
To use the Node client, first install MSL Client from your working directory using npm:

npm install msl-client

You can now use it within your Node script by requiring 'msl-client'

var msl = require('msl-client');
To demonstrate how the msl-client works, an example test has been provided using the sample application that can be obtained from the GitHub project. This example registers responses using text and a template, validates intercepted requests, and unregisters a mock when it is no longer needed.

To run this example, you will first need the selenium-webdriver package and the standalone Selenium-server that will be used to drive the example application. Next, you will need the Mocha testing framework package which we recommend be installed globally. When that is all done, create a new JavaScript project that will contain the following example:


// This allows for the use of the msl-client API
var msl = require('msl-client');

var assert = require("assert"),
SeleniumServer = require('selenium-webdriver/remote').SeleniumServer,
webdriver = require('selenium-webdriver');


var server = new SeleniumServer('./selenium-server-standalone-2.39.0.jar', {
		port : 4444
	});
server.start();

describe('Running Selenium tests', function () {
	var client;
	this.timeout(50000);

	var callbackFunc = function (req, responseText) {
		return '[' + responseText + ']';
	}

	before(function () {
		// Builds the webdriver before the tests start.
		client = new webdriver.Builder().
		usingServer(server.address()).
		withCapabilities(webdriver.Capabilities.chrome()).build();
	});

	beforeEach(function (done) {
		// Navigate to the URL for each test and wait for the autocomplete to be present
		client.get('http://localhost:8001/msl-sample-app/index.html');
		var element = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]'));
		element.getText().then(function () {
			done();
		});

	});

	after(function (done) {
		// After the tests are done, the webdriver is killed
		client.quit().then(function () {
			done();
		});
	});

	it('The dropdown should appear and contain the mocked data', function (done) {
		// Set up the object that contains our response configuration
		var configurations = {};
		configurations.requestPath = "/services/getlanguages";
		configurations.responseText = '{"label":"Java"},{"label":"Perl"}';
		configurations.contentType = "application/json";
		configurations.eval = callbackFunc.toString();
		configurations.statusCode = 200;
		configurations.delayTime = 0;

		// Setting up the mock response using the configuration
		msl.setMockRespond("localhost", 8001, configurations);

		// Triggering the event
		var autocomplete = client.findElement(webdriver.By.xpath('.//*[@id="autocomplete"]'));
		client.executeScript("$('#autocomplete').val('J')");
		client.executeScript("$('#autocomplete').keydown()");

		// Wait for the dropdown elements to appear
		client.wait(function () {
			return client.isElementPresent(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));
		}, 500);

		// Get the elements from the dropdown to check the values
		var optionOne = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));
		var optionTwo = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[2]'));

		// Verify that the options are from the mocked response
		optionOne.getText().then(function (title) {
			assert.equal("Java", title);
		});
		optionTwo.getText().then(function (title) {
			assert.equal("Perl", title);
			done();
		});
	});

	it('The dropdown should appear and contain the template data', function (done) {

		// Registering the template that will be used for the response
		msl.registerTemplate('localhost', 8001,
			'[{"label":"{{param1}}"},{"label":"{{param2}}"}]', 'example');
		// Set up the object that contains our response configuration
		var configurations = {};
		configurations.requestPath = "/services/getlanguages";
		configurations.contentType = "application/json";
		configurations.id = "example";
		configurations.keyValues = {
			"param1" : "German",
			"param2" : "English"
		};
		configurations.statusCode = 200;
		configurations.delayTime = 0;

		// Setting up the mock response using the configuration
		msl.setMockRespond("localhost", 8001, configurations);

		// Triggering the event
		var autocomplete = client.findElement(webdriver.By.xpath('.//*[@id="autocomplete"]'));
		client.executeScript("$('#autocomplete').val('JA')");
		client.executeScript("$('#autocomplete').keydown()");

		// Wait for the dropdown elements to appear
		client.wait(function () {
			return client.isElementPresent(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));
		}, 500);

		// Get the elements from the dropdown to check the values
		var optionOne = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));
		var optionTwo = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[2]'));

		// Verify that the options are from the mocked response
		optionOne.getText().then(function (title) {
			assert.equal("German", title);
		});
		optionTwo.getText().then(function (title) {
			assert.equal("English", title);
			done();
		});

	});

	it('Testing validation of get requests', function (done) {
		// Set up the callback function that will be called when the intercepted http requests
		// are retrieved to validate the data
		var getValidation = function (responseText) {
			var response = JSON.parse(responseText);
			var body = response.xhr_1;
			assert.equal(body.xhr.url, '/services/getservice?term=GET+Example');
			assert.equal(body.xhr.method, 'GET');
			done();
		}
		// Registering the request path that http requests will be intercepted for
		msl.setInterceptXHR("localhost", 8001, "/services/getservice");

		// Triggering the event
		client.executeScript("$('#getInput').val('GET Example')");
		client.executeScript("$('#getRequest').click()");

		// Pausing and then retrieving all of the intercepted http requests before validating
		setTimeout(function () {
			msl.getInterceptedXHR("localhost", 8001, "/services/getservice", getValidation);
		}, 500);

	});

	it('Testing validation of post requests', function (done) {
		// Set up the callback function that will be called when the intercepted http requests
		// are retrieved to validate the data
		var postValidation = function (responseText) {
			var response = JSON.parse(responseText);
			var body = response.xhr_1;
			var regex = new RegExp("timestamp=\\d*&text=POST\\+Example");
			assert.equal(body.xhr.url, '/services/postservice');
			assert.equal(true, regex.test(body.post));
			assert.equal(body.xhr.method, 'POST');

			done();
		}

		// Registering the request path that http requests will be intercepted for
		msl.setInterceptXHR("localhost", 8001, "/services/postservice");

		// Triggering the event
		client.executeScript("$('#output-box').val('POST Example')");
		client.executeScript("$('#postRequest').click()");

		// Pausing and then retrieving all of the intercepted http requests before validating
		setTimeout(function () {
			msl.getInterceptedXHR("localhost", 8001, "/services/postservice", postValidation);
		}, 500);

	});

	it('Testing unRegisterMock', function (done) {

		// Set up the object that contains our response configuration
		var configurations = {};
		configurations.requestPath = "/services/getlanguages";
		configurations.responseText = '[{"label":"French"},{"label":"Spanish"}]';
		configurations.contentType = "application/json";
		configurations.statusCode = 200;
		configurations.delayTime = 0;

		// Setting up the mock response using the configuration
		msl.setMockRespond("localhost", 8001, configurations);

		// Triggering the event
		var autocomplete = client.findElement(webdriver.By.xpath('.//*[@id="autocomplete"]'));
		client.executeScript("$('#autocomplete').val('JA')");
		client.executeScript("$('#autocomplete').keydown()");

		// Wait for the dropdown to appear
		client.wait(function () {
			return client.isElementPresent(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));
		}, 5000);

		// Getting the first element from the list
		var optionOne = client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]'));

		// Verify that the options are from the mocked response and then unregistering that mock
		optionOne.getText().then(function (title) {
			assert.equal("French", title);
			msl.unRegisterMock("localhost", 8001, "/services/getlanguages");

			// Used to remove focus from the input to make sure dropdown disappears
			client.executeScript("$('#autocomplete').blur()");
		});

		// Triggering the event again
		client.executeScript("$('#autocomplete').val('J')");
		client.executeScript("$('#autocomplete').keydown()");

		// Validating that the first element is now no longer present
		client.findElement(webdriver.By.xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]')).
		then(function (element) {
			element.isDisplayed().then(function (displayed) {
				assert.equal(false, displayed);
				done();
			});

		});

	});

});


You will need to start the MSL server on port 8001 (as shown above) before these tests can be run. Once that is done, simply run Mocha and you should be able to see the tests execute.
To use the Python client, for now you will have to check it out from the GitHub page and when that is done, you can install it by running the following from the mslclient directory:

pip install .

You can now use it within your Python script by importing 'mslclient'

import mslclient
An example test has been provided along with the client and setup script as a guide on how it can be used and to see how it performs. Like the others, this test uses the sample application located on the GitHub page and works by registering responses using text and a template, validates intercepted requests, and unregisters a mock when it is no longer needed.

The only other module you will need to install for this test is the python selenium-webdriver binding which is used to interact with the elements on the page.


import mslclient
import unittest
import time
import json
import re
from selenium import webdriver


class TestSequenceFunctions(unittest.TestCase):
    

    @classmethod
    def setUpClass(self):
        '''Used to create the webdriver instance and open the page to be used for testing 
        before any test are started.
        '''
        global chrome 
        chrome = webdriver.Chrome()
        chrome.get("http://localhost:8001/msl-sample-app/index.html")
        
   
      
    def test_textResponse(self):
        '''This tests the setMockRespond method using a string and a javascript function to set up
        the format of the string.
        '''

        # Clear the autocomplete to make sure this test starts from scratch.
        autocomplete = chrome.find_element_by_id('autocomplete')        

        autocomplete.clear()
        chrome.find_element_by_id('postRequest').click()
        time.sleep(1)

        # Setup all of the needed data like request path, the response, function
        # for formatting, etc.
        configurations = {}
        configurations["requestPath"] = "/services/getlanguages"
        configurations["responseText"] = "{\"label\":\"Java\"},{\"label\":\"Perl\"}"
        configurations["contentType"] = "application/json"
        configurations["eval"] = "function (req,responseText) { return '[' + responseText + ']'; }"
        configurations["statusCode"] = "200"
        configurations["delayTime"] = "0"
        
        # Actually make the call  to register this information.
        mslclient.setMockRespond("localhost", "8001", configurations)
        
        # Trigger event that fires off request.
        autocomplete.send_keys('J')
        
        time.sleep(1)
        
        # Grab the dropdown elements and validate the data against the registered response.
        elementOne = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]')
        elementTwo = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[2]')

         
        assert elementOne.get_attribute("textContent") == 'Java'
        assert elementTwo.get_attribute("textContent") == 'Perl'


    def test_templateResponse(self):
        '''This tests the setMockRespond method using a template
        the format of the string.
        '''
        # Register the template that will be used later with the key-value pairs.
        mslclient.registerTemplate("localhost", "8001",
                "[{\"label\":\"{{param1}}\"},{\"label\":\"{{param2}}\"}]", "example")

        # Clear the autocomplete to make sure this test starts from scratch.
        autocomplete = chrome.find_element_by_id('autocomplete')        

        autocomplete.clear()
        chrome.find_element_by_id('postRequest').click()
        time.sleep(1)

        # Setup all of the needed data like request path, key-value pairs, and template id.        
        configurations = {}
        configurations["requestPath"] = "/services/getlanguages"
        configurations["contentType"] = "application/json"
        configurations["statusCode"] = "200"
        configurations["delayTime"] = "0"
        
        # The values that are to replace the keys in the registered template.
        keyVals = {}
        keyVals["param1"] = "German"
        keyVals["param2"] = "English"
        
        configurations["keyValues"] = keyVals
        configurations["id"] = "example"
        
        # Actually make the call  to register this information.
        mslclient.setMockRespond("localhost", "8001", configurations)

        # Trigger event that fires off request.
        autocomplete.send_keys('J')
        
        time.sleep(1)
        # Grab the dropdown elements and validate the data against the registered response.
        elementOne = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]')
        elementTwo = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[2]')

         
        assert elementOne.get_attribute("textContent") == 'German'
        assert elementTwo.get_attribute("textContent") == 'English'
        
        autocomplete.clear()


        
    def test_getIntercepted(self):
        '''This tests the ability to intercept, and validate intercepted, get requests. '''
        # Register the request path of the get request to be intercepted
        mslclient.setInterceptXHR("localhost", "8001", "/services/getservice")

        # Put text into input box which will be added to get request
        inputBox = chrome.find_element_by_id('getInput')
        inputBox.send_keys('GET Example')
        
        # Trigger the get request
        postButton = chrome.find_element_by_id('getRequest')
        postButton.click()
        
        time.sleep(1)

        # Retrieve all request intercepted that have the provided request path
        intercepted = json.loads(mslclient.getInterceptedXHR("localhost", "8001", "/services/getservice"))

        # Validate the method and url of the intercepted request
        req1 = intercepted['xhr_1']
        assert req1['xhr']['method'] == 'GET'
        assert req1['xhr']['url'] == '/services/getservice?term=GET+Example'
        assert req1['post'] is None


    
    def test_postIntercepted(self):
        '''This tests the ability to intercept, and validate intercepted, post requests.'''
        
        # Register the request path of the post request to be intercepted
        mslclient.setInterceptXHR("localhost", "8001", "/services/postservice")

        # Put text into input box which will be added to post request
        inputBox = chrome.find_element_by_id('output-box')
        inputBox.send_keys('POST Example')
        
        # Trigger the post request
        postButton = chrome.find_element_by_id('postRequest')
        postButton.click()
        
        time.sleep(1)

        # Retrieve all request intercepted that have the provided request path
        intercepted = json.loads(mslclient.getInterceptedXHR("localhost", "8001", "/services/postservice"))
        
        # Validate the method and url of the intercepted request
        req1 = intercepted['xhr_1']
        assert req1['xhr']['method'] == 'POST'
        assert req1['xhr']['url'] == '/services/postservice'
        matched = re.match('timestamp=\\d*&text=POST\+Example', req1['post'])
        assert matched.group(0) is not None
        assert matched.group(0) == req1['post']

        
    
    def test_unRegisterMock(self):
        '''This is used to test unregistering a request path.'''

        # Clear the autocomplete to make sure this test starts from scratch.
        autocomplete = chrome.find_element_by_id('autocomplete')        

        autocomplete.clear()
        chrome.find_element_by_id('postRequest').click()
        time.sleep(1)

        # Setup all of the needed data like request path, the response, function
        # for formatting, etc.
        configurations = {}
        configurations["requestPath"] = "/services/getlanguages"
        configurations["responseText"] = "{\"label\":\"Java\"},{\"label\":\"Perl\"}"
        configurations["contentType"] = "application/json"
        configurations["eval"] = "function (req,responseText) { return '[' + responseText + ']'; }"
        configurations["statusCode"] = "200"
        configurations["delayTime"] = "0"
        
        # Actually make the call  to register this information.
        mslclient.setMockRespond("localhost", "8001", configurations)
        
        # Trigger event that fires off request.
        autocomplete.send_keys('J')
        
        time.sleep(1)

        # Grab the dropdown elements and validate the data against the registered response to
        # make sure the initial register worked.
        elementOne = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[1]')
        elementTwo = chrome.find_element_by_xpath('.//ul[contains(@class, "ui-autocomplete")]/li[2]')

         
        assert elementOne.get_attribute("textContent") == 'Java'
        assert elementTwo.get_attribute("textContent") == 'Perl'

        # Unregister the request path
        mslclient.unRegisterMock("localhost", "8001", '/services/getlanguages')
        autocomplete.clear()
        chrome.find_element_by_id('postRequest').click()

        autocomplete.send_keys('J')
        assert elementOne.is_displayed() == False

    @classmethod
    def tearDownClass(self):
        '''Closes the browser since it is no longer needed.'''
        chrome.close()
        chrome.quit()
        
        
if __name__ == '__main__':
    unittest.main()



The MSL server will need to be started on port 8001 (as shown above) for things to work properly. After that, simply execute the mslclientTest script to see the client in action.
Like the Python client, for now you will have to check out the Ruby client from the GitHub page and when that is done, you can install it by running the following from the msl-client-ruby directory:

gem install msl-client

You can now use it within your Ruby script by requiring 'msl-client'

require 'msl-client'
An example test has been provided along with the other files as a guide on how it can be used and to see how it performs. This test also uses the sample application located on the GitHub page and works by registering responses using text and a template, validates intercepted requests, and unregisters a mock when it is no longer needed.

One of the gems you will need to install for this test is the ruby selenium-webdriver binding which is used to interact with the elements on the page. The only other gem you will need is the test-unit gem if you have an older version that does not allow for startup and shutdown to be used.


require 'msl-client'
require 'test/unit'
require 'json'
require  'selenium-webdriver'


class MockapiTest < Test::Unit::TestCase
		class << self
			# Sets up the webdriver before before starting the tests.
			def startup
				ENV['HTTP_PROXY'] = ENV['http_proxy'] = nil
				$driver = Selenium::WebDriver.for :chrome
				$driver.navigate.to 'http://localhost:8001/msl-sample-app/index.html'
			end
		
			# Kills the webdriver instance when all tests are finished.
			def shutdown
				$driver.quit
			end
        end
		
		# This is used to test the basic text response. A function is executed
		# on the web-server to format the text.
		def testTextResponse
		
			# Clear the autocomplete to make sure this test starts from scratch.
			autocomplete = $driver.find_element(:id => 'autocomplete')        
			autocomplete.clear()
			# Take focus off of the autocomplete box to make sure the dropdown
			# goes away.
			$driver.find_element(:id => 'postRequest').click()
			sleep(1)
			
			# Setup all of the needed data like request path, the response, function
			# for formatting, etc.
			configurations = {}
			configurations['requestPath'] = '/services/getlanguages'
			configurations['responseText'] = '{"label":"Java"},{"label":"Perl"}'
			configurations['contentType'] = 'application/json'
			configurations['eval'] = 'function (req,responseText) { return "[" + responseText + "]"; }'
			configurations['statusCode'] = '200'
			configurations['delayTime'] = '0'
			
			# Actually make the call  to register this information.
			setMockRespond('localhost', 8001,configurations.to_json)
			
			# Trigger event that fires off request.
			autocomplete.send_keys 'J'
			
			# Grab the dropdown elements and validate the data against the registered response.
			wait = Selenium::WebDriver::Wait.new(:timeout => 10)
			wait.until {$driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]').displayed?}
			optionOne = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]')
			optionTwo = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[2]')
			
			
			assert_equal('Java',optionOne.text)
			assert_equal('Perl',optionTwo.text)
			
		end
	
		# This tests using a template to generate a response.
		def testTemplateResponse
		
			# Clear the autocomplete to make sure this test starts from scratch.
			autocomplete = $driver.find_element(:id => 'autocomplete')        
			autocomplete.clear()
			# Take focus off of the autocomplete box to make sure the dropdown
			# goes away.
			$driver.find_element(:id => 'postRequest').click()
			sleep(1)

			# Register the template that will be used later with the key-value pairs.
			registerTemplate('localhost', 8001,
                '[{"label":"{{param1}}"},{"label":"{{param2}}"}]', 'example')
			
			# Setup all of the needed data like request path, key-value pairs, and template id.
			configurations = {}
			configurations['requestPath'] = '/services/getlanguages'
			configurations['contentType'] = 'application/json'
			configurations['statusCode'] = '200'
			configurations['delayTime'] = '0'
			
			# The values that are to replace the keys in the registered template.
			keyVals = {}
			keyVals['param1'] = 'German'
			keyVals['param2'] = 'English'
			
			configurations['keyValues'] = keyVals
			configurations['id'] = 'example'
			
			# Actually make the call  to register this information.
			setMockRespond('localhost', 8001,configurations.to_json)
			
			# Trigger event that fires off request.
			autocomplete.send_keys 'J'
			
			# Grab the dropdown elements and validate the data against the registered response.
			wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
			wait.until {$driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]').displayed?}
			optionOne = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]')
			optionTwo = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[2]')
			
			assert_equal('German',optionOne.text)
			assert_equal('English',optionTwo.text)
			
		end
		
		# This tests the ability to intercept, and validate intercepted, get requests.
		def test_getIntercepted
			# Register the request path of the get request to be intercepted
			setInterceptXHR('localhost', 8001, '/services/getservice')

			# Put text into input box which will be added to get request
			inputBox = $driver.find_element(:id => 'getInput')
			inputBox.send_keys 'GET Example'
			
			# Trigger the get request
			postButton = $driver.find_element(:id =>'getRequest')
			postButton.click()
			
			sleep(1)
			# Retrieve all request intercepted that have the provided request path
			intercepted = JSON.parse(getInterceptedXHR('localhost', '8001', '/services/getservice'))

			# Validate the method and url of the intercepted request
			req1 = intercepted['xhr_1']
			assert_equal('GET',req1['xhr']['method'])
			assert_equal('/services/getservice?term=GET+Example', req1['xhr']['url'])
			assert_equal(nil, req1['post'])
		end
		
		
		# This tests the ability to intercept, and validate intercepted, post requests.
		def test_postIntercepted
			# Register the request path of the post request to be intercepted
			setInterceptXHR('localhost', 8001, '/services/postservice')

			# Put text into input box which will be added to post request
			inputBox = $driver.find_element(:id => 'output-box')
			inputBox.send_keys 'POST Example'
			
			# Trigger the post request
			postButton = $driver.find_element(:id =>'postRequest')
			postButton.click()
			
			sleep(1)
			
			# Retrieve all request intercepted that have the provided request path
			intercepted = JSON.parse(getInterceptedXHR('localhost', '8001', '/services/postservice'))
			
			# Validate the method and url of the intercepted request
			req1 = intercepted['xhr_1']
			assert_equal('POST',req1['xhr']['method'])
			assert_equal('/services/postservice', req1['xhr']['url'])
			assert_equal(req1['post'], req1['post'][/timestamp=\d*&text=POST\+Example/])
		end
		
		
		
		# This is used to test unregistering a request path.
		def testUnRegisterMock
		
			# Clear the autocomplete to make sure this test starts from scratch.
			autocomplete = $driver.find_element(:id => 'autocomplete')        
			autocomplete.clear()
			# Take focus off of the autocomplete box to make sure the dropdown
			# goes away.
			$driver.find_element(:id => 'postRequest').click()
			sleep(1)
			
			# Setup all of the needed data like request path, the response, function
			# for formatting, etc.
			configurations = {}
			configurations['requestPath'] = '/services/getlanguages'
			configurations['responseText'] = '[{"label":"Java"},{"label":"Perl"}]'
			configurations['contentType'] = 'application/json'
			configurations['statusCode'] = '200'
			configurations['delayTime'] = '0'
			
			# Actually make the call  to register this information.
			setMockRespond('localhost', 8001,configurations.to_json)
			
			# Trigger event that fires off request.
			element = $driver.find_element(:id => 'autocomplete')
			element.send_keys 'J'
			
			# Grab the dropdown elements and validate the data against the registered response to make sure
			# it worked before unregistering.
			wait = Selenium::WebDriver::Wait.new(:timeout => 10)
			wait.until {$driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]').displayed?}
			optionOne = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]')
			optionTwo = $driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[2]')
			
			
			assert_equal('Java',optionOne.text)
			assert_equal('Perl',optionTwo.text)
			
			# Unregister the request path
            unRegisterMock('localhost', 8001, '/services/getlanguages');
			autocomplete.clear()
			$driver.find_element(:id => 'postRequest').click()
			element.send_keys 'J'

			assert_true(!$driver.find_element(:xpath => './/ul[contains(@class, "ui-autocomplete")]/li[1]').displayed?)

			
		end
end


After starting the MSL server on port 8001 (as shown above), execute the msl-client-test script to see the client in action.

Running Your Tests Using Karma

If you are using the browser client to write your tests, we recommend you to use the Karma Plugin to run your tests. The karma plugin will allow automatic starting of MSL Server and execution of tests using the MSL Browser Client.

Installation

The easiest way is to keep karma-msl as a devDependency in your package.json.
{
  "devDependencies": {
    "karma": "~0.12.0",
    "karma-msl": "~0.0.14"
  }
}

You can simply do it by:
npm install karma-msl --save-dev

Configuration

Including the following in your karma configuration file
// karma.conf.js
module.exports = function(config) {
  config.set({
    frameworks: ['jasmine', 'msl'],

    files: [
      'spec/*.js'
    ],

    // configuration for msl plugin
    msl: {
      port: '8002', //port to start msl server.  8000 by default.
      basedir: '../src/', // directory containing the app code (front-end code under test).  current dir by default.
      debug: 'true', // true to turn on debugging. false by default.
      extensions: 'parseUrl.js' // specify extension files you want to plugin to MSL to parse URL differently.
    },

    // this port should match the msl port specified in msl plugin config
    proxies: {
      '/' : 'http://localhost:8002/'
    },

    // this port should match the msl port used within the tests
    port: 8001,
  });
};

Execution

Run your tests by executing the following
karma start karma.conf.js