Testing Arc.js Applications

The recommended method of testing Arc.js applications is to use the Kibo eCommerce Action Simulator in conjunction with thorough integration testing.

Kibo eCommerce Action Simulator

Note:  The Kibo eCommerce Action Simulator is in prerelease. As such, the programming patterns are more complex and the features less robust than they will be in the final version.

The Kibo eCommerce Action Simulator produces a mock Kibo eCommerce context that you can utilize in your Arc.js test files to simulate data from Kibo eCommerce and verify that your Arc.js functions run as expected.

You can view the Kibo eCommerce Action Simulator library in the node_modules/mozu-action-simulator directory of your project folder. The simulator provides:

To use the simulator:

  1. Open the test file that corresponds to one of the actions you have scaffolded. Test files are located in the assets/test directory.
  2. Require the mozu-action-simulator package in your test file. For example:
    var Simulator = require('mozu-action-simulator');
  3. Access simulator features, such as Simulator.context() or Simulator.assert, to facilitate writing tests for your Arc.js function.

Example of Testing with the Simulator

In this example, the embedded.commerce.carts.addItem.before action has been designed to check whether an item added to the cart has a 'Hazardous' product attribute. If the new item is hazardous and the cart already contains an existing hazardous item, the action removes the new item from the cart. The following code block demonstrates how you would test this action within its corresponding test file using the Kibo eCommerce Action Simulator.

assets/test/embedded.commerce.carts.addItem.before.t.js
/**
* This is a scaffold for unit tests for the custom function for
* `embedded.commerce.carts.addItem.before`.
* Modify the test conditions below. You may:
*  - add special assertions for code actions from Simulator.assert
*  - create a mock context with Simulator.context() and modify it
*  - use and modify mock Mozu business objects from Simulator.fixtures
*/
//Test for:
//embedded.commerce.carts.addItem.before.t.js
'use strict';

var Simulator = require('mozu-action-simulator');
var assert = Simulator.assert;

var actionName = 'embedded.commerce.carts.addItem.before';

describe('embedded.commerce.carts.addItem.before implementing embedded.commerce.carts.addItem.before', function() {

	var action;

	before(function() {
		action = require('../src/domains/commerce.carts/embedded.commerce.carts.addItem.before');
	});

	it('runs successfully', function(done) {

		var callback = function(err) {
			assert.ok(!err, "Callback was called with an error: " + err);
			// more assertions
			done();
		};

		var context = Simulator.context(actionName, callback);

		// modify context as necessary

		context.exec.removeItem = function() {
		};

		Simulator.simulate(actionName, action, context, callback);
		});

		it('checks incoming product for hazard indicator and then removes hazardous items from the cart if the incoming item is hazardous', function(done) {
			var callback = function(err) {
				assert.ok(!err, "Callback was called with an error: " + err);
				// more assertions
				done();
			};
			//Test setup
			var context = Simulator.context(actionName, callback);

			var cart = context.get.cart();
			var cartItem = context.get.cartItem();
			var cartItemsCount = cart.items.length;
    
			cart.items[0].product.properties.push({
				"attributeFQN": "tenant~hazardous",
				"name": "Hazardous",
				"dataType": "Bool",
				"isMultiValue": false,
				"values": [
					{
						"value": true
					}
				]
			});
    
			cart.items[1].product.properties.push({
				"attributeFQN": "tenant~hazardous",
				"name": "Hazardous",
				"dataType": "Bool",
				"isMultiValue": false,
				"values": [
					{
						"value": true
					}
				]
			});

			cartItem.product.properties.push({
				"attributeFQN": "tenant~hazardous",
				"name": "Hazardous",
				"dataType": "Bool",
				"isMultiValue": false,
				"values": [
					{
						"value": true
					}
				]
			});

			context.get.cart = function() {
				return cart;
			}
    
			context.get.cartItem = function() {
				return cartItem;
			}

			context.exec.removeItem = function() {
				var alteredCart = context.get.cart().items;
				alteredCart.pop();
				assert.equal(alteredCart.length, 1);
			};

			Simulator.simulate(actionName, action, context, callback);

		});
});
assets/src/domains/commerce.carts/embedded.commerce.carts.addItem.before.js
module.exports = function(context, callback) {
	var cart = context.get.cart();
	var cartItem = context.get.cartItem();
	var isHazardousCart = false;

	cart.items.forEach(function(item) {
		item.product.properties.forEach(function(property) {
			if (property.attributeFQN === 'tenant~hazardous') {
				isHazardousCart = true;
			}

			if (isHazardousCart && property.attributeFQN === 'tenant~hazardous') {
				context.exec.removeItem();
			}
		});
	});
	callback();
};