<commit_before>describe('Service: vnCart', function () {

	'use strict';

	// load the service's module
	beforeEach(module('Volusion.toolboxCommon'));

	// instantiate service
	var vnCart, $httpBackend, $rootScope, $q;//, response;

	beforeEach(inject(function (_vnCart_, $injector) {
		vnCart = _vnCart_;
//		var cart = vnCart.getCart();
		$httpBackend = $injector.get('$httpBackend');
		$q = $injector.get('$q');
		$rootScope = $injector.get('$rootScope');
	}));

	afterEach(function () {
		vnCart = null;
		$httpBackend = null;
		$rootScope = null;
	});

	it('should not have a cart when uninitialized', function () {
		expect(vnCart).not.toEqual(null);
		expect(vnCart).not.toEqual(undefined);
		expect(vnCart.getCart()).toEqual({});
	});

	it('should handle initialization', function() {

		// Response to the init GET request
		$httpBackend.when('GET', 'http://www.samplestore.io/api/v1/carts')
			.respond(200, VnApiMockLibrary.initialCartResponse());

		vnCart.init();

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		var cart = vnCart.getCart();

		expect(cart).not.toEqual({});
		expect(cart.totals.qty).toBe(0);

	});

	it('should return data on success', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', 'http://www.samplestore.io/api/v1/carts')
			.respond(200, VnApiMockLibrary.saveCartResponse({success: true}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'success'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data).not.toBeFalsy();
		expect(data.totals.qty).toBe(5);
		expect(data.items.length).toBe(5);
		expect(data.totals.qty).toBe(data.items.length);
		expect(data.serviceErrors.length).toBe(0);
		expect(data.warnings.length).toBe(0);
	});

	it('should handle warnings', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', 'http://www.samplestore.io/api/v1/carts')
			.respond(500, VnApiMockLibrary.saveCartResponse({success: false}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'errors'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data.warnings[0]).toBeTruthy();
		expect(data.warnings[0]).toBeTruthy();
		var warn1 = data.warnings[0];
		expect(warn1.Code).toBe('CART_ITEM_SHIPPING_DELAY');
		expect(warn1.Message).toBe('The shipping time for this product is delayed by 42 micro seconds.');
		expect(warn1.Identifier).toBe('ah-chairbamboo');
	});

	it('should handle serviceErrors', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', 'http://www.samplestore.io/api/v1/carts')
			.respond(500, VnApiMockLibrary.saveCartResponse({success: false}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'warning'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data.serviceErrors[0]).toBeTruthy();
		var err1 = data.serviceErrors[0];
		expect(err1.Code).toBe('CART_ITEM_MIN_ORDER_QTY');
		expect(err1.Message).toBe('The minimum order quantity for product \"Modern Bamboo Chair\" is 2.');
		expect(err1.Identifier).toBe('ah-chairbamboo');
	});
});
<commit_msg>Code Review Suggestions: * Be consistent with module injection in beforeEach * Use vnApiEndpoint.getApiUrl() to drive the mock response set up<commit_after>describe('Service: vnCart', function () {

	'use strict';

	// load the service's module
	beforeEach(module('Volusion.toolboxCommon'));

	// instantiate service
	var vnCart, vnApiEndpoint, $httpBackend, $rootScope, $q;//, response;

	beforeEach(inject(function ($injector) {
		vnCart = $injector.get('vnCart');
		vnApiEndpoint = $injector.get('vnDataEndpoint');
		$httpBackend = $injector.get('$httpBackend');
		$q = $injector.get('$q');
		$rootScope = $injector.get('$rootScope');
	}));

	afterEach(function () {
		vnCart = null;
		$httpBackend = null;
		$rootScope = null;
	});

	it('should not have a cart when uninitialized', function () {
		expect(vnCart).not.toEqual(null);
		expect(vnCart).not.toEqual(undefined);
		expect(vnCart.getCart()).toEqual({});
	});

	it('should handle initialization', function() {

		// Response to the init GET request
		$httpBackend.when('GET', vnApiEndpoint.getApiUrl() + '/carts')
			.respond(200, VnApiMockLibrary.initialCartResponse());

		vnCart.init();

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		var cart = vnCart.getCart();

		expect(cart).not.toEqual({});
		expect(cart.totals.qty).toBe(0);

	});

	it('should return data on success', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', vnApiEndpoint.getApiUrl() + '/carts')
			.respond(200, VnApiMockLibrary.saveCartResponse({success: true}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'success'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data).not.toBeFalsy();
		expect(data.totals.qty).toBe(5);
		expect(data.items.length).toBe(5);
		expect(data.totals.qty).toBe(data.items.length);
		expect(data.serviceErrors.length).toBe(0);
		expect(data.warnings.length).toBe(0);
	});

	it('should handle warnings', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', vnApiEndpoint.getApiUrl() + '/carts')
			.respond(500, VnApiMockLibrary.saveCartResponse({success: false}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'errors'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data.warnings[0]).toBeTruthy();
		expect(data.warnings[0]).toBeTruthy();
		var warn1 = data.warnings[0];
		expect(warn1.Code).toBe('CART_ITEM_SHIPPING_DELAY');
		expect(warn1.Message).toBe('The shipping time for this product is delayed by 42 micro seconds.');
		expect(warn1.Identifier).toBe('ah-chairbamboo');
	});

	it('should handle serviceErrors', function () {
		var data,
			deferred = $q.defer(),
			promise = deferred.promise;

		// Respond to the saveCart POST
		$httpBackend.when('POST', vnApiEndpoint.getApiUrl() + '/carts')
			.respond(500, VnApiMockLibrary.saveCartResponse({success: false}));

		promise.then(function (response) {
			data = response;
		});

		vnCart.saveCart({action: 'warning'})
			.then(function (response) {
				deferred.resolve(response);
			});

		// Get ready for tests
		$httpBackend.flush();
		$rootScope.$digest();

		expect(data.serviceErrors[0]).toBeTruthy();
		var err1 = data.serviceErrors[0];
		expect(err1.Code).toBe('CART_ITEM_MIN_ORDER_QTY');
		expect(err1.Message).toBe('The minimum order quantity for product \"Modern Bamboo Chair\" is 2.');
		expect(err1.Identifier).toBe('ah-chairbamboo');
	});
});
<|endoftext|>


<commit_before>import Tile from '../../../../src/ol/Tile.js';
import TileRange from '../../../../src/ol/TileRange.js';
import {get as getProjection} from '../../../../src/ol/proj.js';
import Projection from '../../../../src/ol/proj/Projection.js';
import Source from '../../../../src/ol/source/Source.js';
import TileSource from '../../../../src/ol/source/Tile.js';
import {getKeyZXY} from '../../../../src/ol/tilecoord.js';
import TileGrid from '../../../../src/ol/tilegrid/TileGrid.js';

/**
 * Tile source for tests that uses a EPSG:4326 based grid with 4 resolutions and
 * 256x256 tiles.
 *
 * @param {Object<string, ol.TileState>} tileStates Lookup of tile key to
 *     tile state.
 */
class MockTile extends TileSource {
  constructor(tileStates) {
    const tileGrid = new TileGrid({
      resolutions: [360 / 256, 180 / 256, 90 / 256, 45 / 256],
      origin: [-180, -180],
      tileSize: 256
    });

    super({
      projection: getProjection('EPSG:4326'),
      tileGrid: tileGrid
    });

    for (const key in tileStates) {
      this.tileCache.set(key, new Tile(key.split('/'), tileStates[key]));
    }
  }
}

/**
 * @inheritDoc
 */
MockTile.prototype.getTile = function(z, x, y) {
  const key = getKeyZXY(z, x, y);
  if (this.tileCache.containsKey(key)) {
    return /** @type {!ol.Tile} */ (this.tileCache.get(key));
  } else {
    const tile = new Tile(key, 0); // IDLE
    this.tileCache.set(key, tile);
    return tile;
  }
};

describe('ol.source.Tile', function() {

  describe('constructor', function() {
    it('returns a tile source', function() {
      const source = new TileSource({
        projection: getProjection('EPSG:4326')
      });
      expect(source).to.be.a(Source);
      expect(source).to.be.a(TileSource);
    });
    it('sets a custom cache size', function() {
      const projection = getProjection('EPSG:4326');
      const source = new TileSource({
        projection: projection,
        cacheSize: 42
      });
      expect(source.getTileCacheForProjection(projection).highWaterMark).to.be(42);
    });
  });

  describe('#setKey()', function() {
    it('sets the source key', function() {
      const source = new TileSource({});
      expect(source.getKey()).to.equal('');

      const key = 'foo';
      source.setKey(key);
      expect(source.getKey()).to.equal(key);
    });
  });

  describe('#setKey()', function() {
    it('dispatches a change event', function(done) {
      const source = new TileSource({});

      const key = 'foo';
      source.once('change', function() {
        done();
      });
      source.setKey(key);
    });

    it('does not dispatch change if key does not change', function(done) {
      const source = new TileSource({});

      const key = 'foo';
      source.once('change', function() {
        source.once('change', function() {
          done(new Error('Unexpected change event after source.setKey()'));
        });
        setTimeout(function() {
          done();
        }, 10);
        source.setKey(key); // this should not result in a change event
      });

      source.setKey(key); // this should result in a change event
    });

  });

  describe('#forEachLoadedTile()', function() {

    let callback;
    beforeEach(function() {
      callback = sinon.spy();
    });

    it('does not call the callback if no tiles are loaded', function() {
      const source = new MockTile({});
      const grid = source.getTileGrid();
      const extent = [-180, -180, 180, 180];
      const zoom = 3;
      const range = grid.getTileRangeForExtentAndZ(extent, zoom);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(callback.callCount).to.be(0);
    });

    it('does not call getTile() if no tiles are loaded', function() {
      const source = new MockTile({});
      sinon.spy(source, 'getTile');
      const grid = source.getTileGrid();
      const extent = [-180, -180, 180, 180];
      const zoom = 3;
      const range = grid.getTileRangeForExtentAndZ(extent, zoom);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(source.getTile.callCount).to.be(0);
      source.getTile.restore();
    });

    it('calls callback for each loaded tile', function() {
      const source = new MockTile({
        '1/0/0': 2, // LOADED
        '1/0/1': 2, // LOADED
        '1/1/0': 1, // LOADING,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(callback.callCount).to.be(3);
    });

    it('returns true if range is fully loaded', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 2, // LOADED,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom, range,
        function() {
          return true;
        });
      expect(covered).to.be(true);
    });

    it('returns false if range is not fully loaded', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 1, // LOADING,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom,
        range, function() {
          return true;
        });
      expect(covered).to.be(false);
    });

    it('allows callback to override loaded check', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 2, // LOADED,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom, range,
        function() {
          return false;
        });
      expect(covered).to.be(false);
    });

  });

  describe('#getTileCoordForTileUrlFunction()', function() {

    it('returns the expected tile coordinate - {wrapX: true}', function() {
      const tileSource = new TileSource({
        projection: 'EPSG:3857',
        wrapX: true
      });

      let tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);
    });

    it('returns the expected tile coordinate - {wrapX: false}', function() {
      const tileSource = new TileSource({
        projection: 'EPSG:3857',
        wrapX: false
      });

      let tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql(null);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
      expect(tileCoord).to.eql(null);
    });

    it('works with wrapX and custom projection without extent', function() {
      const tileSource = new TileSource({
        projection: new Projection({
          code: 'foo',
          global: true,
          units: 'm'
        }),
        wrapX: true
      });

      const tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);
    });
  });

  describe('#refresh()', function() {
    it('checks clearing of internal state', function() {
      // create a source with one loaded tile
      const source = new MockTile({
        '1/0/0': 2 // LOADED
      });
      // check the loaded tile is there
      const tile = source.getTile(1, 0, 0);
      expect(tile).to.be.a(Tile);
      // check tile cache is filled
      expect(source.tileCache.getCount()).to.eql(1);
      // refresh the source
      source.refresh();
      // check tile cache after refresh (should be empty)
      expect(source.tileCache.getCount()).to.eql(0);
    });
  });

});

describe('MockTile', function() {

  describe('constructor', function() {
    it('creates a tile source', function() {
      const source = new MockTile({});
      expect(source).to.be.a(TileSource);
      expect(source).to.be.a(MockTile);
    });
  });

  describe('#getTile()', function() {
    it('returns a tile with state based on constructor arg', function() {
      const source = new MockTile({
        '0/0/0': 2, // LOADED,
        '1/0/0': 2 // LOADED
      });
      let tile;

      // check a loaded tile
      tile = source.getTile(0, 0, 0);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(2); // LOADED

      // check a tile that is not loaded
      tile = source.getTile(1, 0, -1);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(0); // IDLE

      // check another loaded tile
      tile = source.getTile(1, 0, 0);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(2); // LOADED

    });
  });

});
<commit_msg>Test cache size<commit_after>import Tile from '../../../../src/ol/Tile.js';
import TileRange from '../../../../src/ol/TileRange.js';
import {get as getProjection} from '../../../../src/ol/proj.js';
import Projection from '../../../../src/ol/proj/Projection.js';
import Source from '../../../../src/ol/source/Source.js';
import TileSource from '../../../../src/ol/source/Tile.js';
import {getKeyZXY} from '../../../../src/ol/tilecoord.js';
import TileGrid from '../../../../src/ol/tilegrid/TileGrid.js';

/**
 * Tile source for tests that uses a EPSG:4326 based grid with 4 resolutions and
 * 256x256 tiles.
 *
 * @param {Object<string, ol.TileState>} tileStates Lookup of tile key to
 *     tile state.
 */
class MockTile extends TileSource {
  constructor(tileStates) {
    const tileGrid = new TileGrid({
      resolutions: [360 / 256, 180 / 256, 90 / 256, 45 / 256],
      origin: [-180, -180],
      tileSize: 256
    });

    super({
      projection: getProjection('EPSG:4326'),
      tileGrid: tileGrid
    });

    for (const key in tileStates) {
      this.tileCache.set(key, new Tile(key.split('/'), tileStates[key]));
    }
  }
}

/**
 * @inheritDoc
 */
MockTile.prototype.getTile = function(z, x, y) {
  const key = getKeyZXY(z, x, y);
  if (this.tileCache.containsKey(key)) {
    return /** @type {!ol.Tile} */ (this.tileCache.get(key));
  } else {
    const tile = new Tile(key, 0); // IDLE
    this.tileCache.set(key, tile);
    return tile;
  }
};

describe('ol.source.Tile', function() {

  describe('constructor', function() {
    it('returns a tile source', function() {
      const source = new TileSource({
        projection: getProjection('EPSG:4326')
      });
      expect(source).to.be.a(Source);
      expect(source).to.be.a(TileSource);
    });
    it('sets a screen dependent cache size', function() {
      const source = new TileSource({});
      expect(source.tileCache.highWaterMark).to.be(4 * Math.ceil(screen.availWidth / 256) * Math.ceil(screen.availHeight / 256));
    });
    it('sets a custom cache size', function() {
      const projection = getProjection('EPSG:4326');
      const source = new TileSource({
        projection: projection,
        cacheSize: 42
      });
      expect(source.getTileCacheForProjection(projection).highWaterMark).to.be(42);
    });
  });

  describe('#setKey()', function() {
    it('sets the source key', function() {
      const source = new TileSource({});
      expect(source.getKey()).to.equal('');

      const key = 'foo';
      source.setKey(key);
      expect(source.getKey()).to.equal(key);
    });
  });

  describe('#setKey()', function() {
    it('dispatches a change event', function(done) {
      const source = new TileSource({});

      const key = 'foo';
      source.once('change', function() {
        done();
      });
      source.setKey(key);
    });

    it('does not dispatch change if key does not change', function(done) {
      const source = new TileSource({});

      const key = 'foo';
      source.once('change', function() {
        source.once('change', function() {
          done(new Error('Unexpected change event after source.setKey()'));
        });
        setTimeout(function() {
          done();
        }, 10);
        source.setKey(key); // this should not result in a change event
      });

      source.setKey(key); // this should result in a change event
    });

  });

  describe('#forEachLoadedTile()', function() {

    let callback;
    beforeEach(function() {
      callback = sinon.spy();
    });

    it('does not call the callback if no tiles are loaded', function() {
      const source = new MockTile({});
      const grid = source.getTileGrid();
      const extent = [-180, -180, 180, 180];
      const zoom = 3;
      const range = grid.getTileRangeForExtentAndZ(extent, zoom);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(callback.callCount).to.be(0);
    });

    it('does not call getTile() if no tiles are loaded', function() {
      const source = new MockTile({});
      sinon.spy(source, 'getTile');
      const grid = source.getTileGrid();
      const extent = [-180, -180, 180, 180];
      const zoom = 3;
      const range = grid.getTileRangeForExtentAndZ(extent, zoom);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(source.getTile.callCount).to.be(0);
      source.getTile.restore();
    });

    it('calls callback for each loaded tile', function() {
      const source = new MockTile({
        '1/0/0': 2, // LOADED
        '1/0/1': 2, // LOADED
        '1/1/0': 1, // LOADING,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      source.forEachLoadedTile(source.getProjection(), zoom, range, callback);
      expect(callback.callCount).to.be(3);
    });

    it('returns true if range is fully loaded', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 2, // LOADED,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom, range,
        function() {
          return true;
        });
      expect(covered).to.be(true);
    });

    it('returns false if range is not fully loaded', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 1, // LOADING,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom,
        range, function() {
          return true;
        });
      expect(covered).to.be(false);
    });

    it('allows callback to override loaded check', function() {
      // a source with no loaded tiles
      const source = new MockTile({
        '1/0/0': 2, // LOADED,
        '1/0/1': 2, // LOADED,
        '1/1/0': 2, // LOADED,
        '1/1/1': 2 // LOADED
      });

      const zoom = 1;
      const range = new TileRange(0, 1, 0, 1);

      const covered = source.forEachLoadedTile(
        source.getProjection(), zoom, range,
        function() {
          return false;
        });
      expect(covered).to.be(false);
    });

  });

  describe('#getTileCoordForTileUrlFunction()', function() {

    it('returns the expected tile coordinate - {wrapX: true}', function() {
      const tileSource = new TileSource({
        projection: 'EPSG:3857',
        wrapX: true
      });

      let tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);
    });

    it('returns the expected tile coordinate - {wrapX: false}', function() {
      const tileSource = new TileSource({
        projection: 'EPSG:3857',
        wrapX: false
      });

      let tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql(null);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);

      tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
      expect(tileCoord).to.eql(null);
    });

    it('works with wrapX and custom projection without extent', function() {
      const tileSource = new TileSource({
        projection: new Projection({
          code: 'foo',
          global: true,
          units: 'm'
        }),
        wrapX: true
      });

      const tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
      expect(tileCoord).to.eql([6, 33, 22]);
    });
  });

  describe('#refresh()', function() {
    it('checks clearing of internal state', function() {
      // create a source with one loaded tile
      const source = new MockTile({
        '1/0/0': 2 // LOADED
      });
      // check the loaded tile is there
      const tile = source.getTile(1, 0, 0);
      expect(tile).to.be.a(Tile);
      // check tile cache is filled
      expect(source.tileCache.getCount()).to.eql(1);
      // refresh the source
      source.refresh();
      // check tile cache after refresh (should be empty)
      expect(source.tileCache.getCount()).to.eql(0);
    });
  });

});

describe('MockTile', function() {

  describe('constructor', function() {
    it('creates a tile source', function() {
      const source = new MockTile({});
      expect(source).to.be.a(TileSource);
      expect(source).to.be.a(MockTile);
    });
  });

  describe('#getTile()', function() {
    it('returns a tile with state based on constructor arg', function() {
      const source = new MockTile({
        '0/0/0': 2, // LOADED,
        '1/0/0': 2 // LOADED
      });
      let tile;

      // check a loaded tile
      tile = source.getTile(0, 0, 0);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(2); // LOADED

      // check a tile that is not loaded
      tile = source.getTile(1, 0, -1);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(0); // IDLE

      // check another loaded tile
      tile = source.getTile(1, 0, 0);
      expect(tile).to.be.a(Tile);
      expect(tile.state).to.be(2); // LOADED

    });
  });

});
<|endoftext|>


<commit_before>/******************************************************************************
 The MIT License (MIT)

 Copyright (c) 2016 Gary Bell

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 ******************************************************************************
 *
 * A library for uploading files and sending them to a server without
 * submitting a full page form page.
 *
 *****************************************************************************/

/**
 * Constructor for Charon
 * @param setupObject - An object with values to override the default Charon values
 */
var Charon = function (setupObject) {

    // Loop through each set object item and set it against the relevant item on the prototype object
    for (var key in setupObject)
    {
        //this.key = setupObject.key
        eval('Charon.prototype.' + key + ' = setupObject. ' + key);
    }

    return Charon.prototype;

};

/**
 * The prototype for the Charon object.
 * All functionality will be in here
 * @type {{url: string, file: string, additionalData: string}}
 */
Charon.prototype = {

    /**
     * Define variables for the upload sending
     */
    // URL to post the files to
    url: ''

    // file input field to upload
    , file: ''

    // other information to submit at the same time as the file
    , additionalData: ''

    // should we output debug to the console
    , outputDebugging: false

    /**
     * User defined callbacks for different events.
     * This will allow the using application to customise the way they handle each events.
     */
    // the callback to run when progress has begun
    , loadStartCallback: ''

    // the callback to run when the operation is in progress
    , progressCallback: null

    // the callback to run when the loading of the file has been aborted
    , abortCallback: ''

    // the callback to run when a resource failed to load
    , errorCallback: ''

    // the callback to run when a resource and its dependents have finished loading
    , loadCallback: ''

    // the callback to run when a resource has timed out
    , timeoutCallback: ''

    // the callback to run when progression has stopped.  This is called after error, abort or load
    , loadEndCallback: ''

    // the callback to run whenever the readyState of the resource load has changed
    , readyStateChangeCallback: ''

    /**
     * Pass messages in to be shown on the console.  Will only output if outputDebugging is set to true
     * @param message - the message to output to the console log
     */
    , debug: function (message) {
        if (this.outputDebugging) {
            console.log(message);
        }
    }

    /**
     * Check to see is a particular user callback is set.  If so, we know we can make a function call
     * @param callbackName - the name of the callback to use.  This will be one of:
     *  - loadStartCallback
     *  - progressCallback
     *  - abortCallback
     *  - errorCallback
     *  - loadCallback
     *  - timeoutCallback
     *  - loadEndCallback
     *  - readyStateChangeCallback
     * @return boolean - true is the callback is set.  False if it is not.
     */
    , callbackIsSet: function (callbackName) {
        // going to assume the callback is not set.
        var callbackSet = false;

        /**
         * Check to see that the passed in callbackName is a valid callback reference
         * Whilst this makes painful reading, we're going to be using the eval function so don't want anything malicious to be called by this
         * TODO: find a better way of doing this
         */
        /*if (callbackName === 'loadStartCallback'
            || callbackName === 'progressCallback'
            || callbackName === 'abortCallback'
            || callbackName === 'errorCallback'
            || callbackName === 'loadCallback'
            || callbackName === 'timeoutCallback'
            || callbackName === 'loadEndCallback'
            || callbackName === 'readyStateChangeCallback'
        ) {*/
            //var callbackValue = eval(callbackName);
            if (callbackName !== undefined
                && callbackName !== ''
            ) {
                callbackSet = true;
            }
        //}

        return callbackSet;
    }

    /**
     * Check if a particular item is traversable by a for-key-in loop
     * @param objectToTest - the object/item to check when seeing if it is an array
     * @return boolean
     */
    , isTraversable: function (objectToTest) {
        this.debug(Object.prototype.toString(objectToTest));
        this.debug(objectToTest);
        return (Object.prototype.toString(objectToTest) === "[object Array]" ||
            Object.prototype.toString(objectToTest) === "[object Object]");
    }

    /**
     * Upload the file and any additional data which might be needed
     */
    , sendFile: function () {

        // check we have set the URL before we try and do anything
        if (this.url === '')
        {
            throw new Error('No URL set.  Cannot continue');
        }

        // setup a form data variable so we can build the form with the information we need rather than everything.
        var formData = new FormData();

        /**
         * Check that additionalData is an array
         * If it is, get each item and build the form data
         */
        if (this.isTraversable(this.additionalData)) {
            for (key in this.additionalData) {
                // to stop a blank row going in
                if (this.additionalData[key] !== undefined) {
                    // add the item to the form data in the form key, value
                    formData.append(key, this.additionalData[key]);
                }
            }
        }
        else
        {
            this.debug('additionaData is not an array');
        }

        try {
            // set the file to upload
            var uploadFile = this.file.files[0];
            formData.append('charonFile', uploadFile);
        }
        catch(e)
        {
            throw new Error('No file set for upload.  Cannot continue');
        }

        // create the XMLHttpRequest object for sending the information
        var xhr = new XMLHttpRequest();

        // open the request, set the URL from that was given to send the file to, and set the transport to be POST
        xhr.open('POST', this.url, true);

        /**
         * Set up the callback functionality for the different events which can be used
         */

        // setup the loadstart listener and functionality
        xhr.addEventListener('loadstart', this.charonLoadStart);

        // setup the progress listener and functionality
        xhr.addEventListener('progress', this.charonProgress);

        // setup the abort listener and functionality
        xhr.addEventListener('abort', this.charonAbort);

        // setup the error listener and functionality
        xhr.addEventListener('error', this.charonError);

        // setup the load listener and functionality
        xhr.addEventListener('load', this.charonLoad);

        // setup the timeout listener and functionality
        xhr.addEventListener('timeout', this.charonTimeOut);

        // setup the loadend listener and functionality
        xhr.addEventListener('loadend', this.charonLoadEnd);

        // setup the readystatechange listener and functionality
        xhr.addEventListener('readystatechange', this.charonReadyStateChange);

        // we've set up all of the functionality we need, now send the actual form
        xhr.send(formData);
    }

    /**
     * Load start event functionality.
     * This contains the default functionality for handling the loadstart event.
     * Once the default functionality has ran, this will call the loadstart callback defined by the user in loadStartCallback
     * @param loadStartEvent
     */
    , charonLoadStart: function (loadStartEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running loadStart');

        // Check if the loadStart callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadStartCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadStartCallback);
            // Call the user defined loadstart function with the loadstart event
            Charon.prototype.debug(typeof Charon.prototype.loadStartCallback);
            if (typeof Charon.prototype.loadStartCallback === 'function')
            {
                Charon.prototype.loadStartCallback(loadStartEvent);
            }
        }
    }

    /**
     * Progress event functionality.
     * This contains the default functionality for handling the progress event.
     * Once the default functionality has ran, this will call the progress callback defined by the user in progressCallback
     * @param progressEvent
     */
    , charonProgress: function (progressEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running progress');

        // Check if the progress callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.progressCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.progressCallback);
            // Call the user defined progress function with the progress event
            Charon.prototype.debug(typeof Charon.prototype.progressCallback);
            if (typeof Charon.prototype.progressCallback === 'function')
            {
                Charon.prototype.progressCallback(progressEvent);
            }
        }
    }

    /**
     * Abort event functionality.
     * This contains the default functionality for handling the abort event.
     * Once the default functionality has ran, this will call the abort callback defined by the user in abortCallback
     * @param abortEvent
     */
    , charonAbort: function (abortEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running abort');

        // Check if the abort callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.abortCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.abortCallback);
            // Call the user defined abort function with the abort event
            //eval(this.abortCallback + "( " + abortEvent + ");");
            if (typeof Charon.prototype.abortCallback === 'function')
            {
                Charon.prototype.abortCallback(abortEvent);
            }
        }
    }

    /**
     * Error event functionality.
     * This contains the default functionality for handling the error event.
     * Once the default functionality has ran, this will call the error callback defined by the user in errorCallback
     * @param errorEvent
     */
    , charonError: function (errorEvent) {
        Charon.prototype.debug('running error');

        // output an error to the console.  We don't want this to be hidden
        console.log('An error occurred when transferring the file');
        // full dump of the error event
        console.log(errorEvent);

        // Check if the error callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.errorCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.errorCallback);
            // Call the user defined error function with the error event
            Charon.prototype.debug(typeof Charon.prototype.errorCallback);
            if (typeof Charon.prototype.errorCallback === 'function')
            {
                Charon.prototype.errorCallback(errorEvent);
            }
        }
    }

    /**
     * Load event functionality.
     * This contains the default functionality for handling the load event.
     * Once the default functionality has ran, this will call the load callback defined by the user in loadCallback
     * @param loadEvent
     */
    , charonLoad: function (loadEvent) {
        Charon.prototype.debug('running load');

        // Check if the load callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadCallback);
            // Call the user defined load function with the load event
            Charon.prototype.debug(typeof Charon.prototype.loadCallback);
            if (typeof Charon.prototype.loadCallback === 'function')
            {
                Charon.prototype.loadCallback(loadEvent);
            }
        }
    }

    /**
     * Timeout event functionality.
     * This contains the default functionality for handling the timeout event.
     * Once the default functionality has ran, this will call the timeout callback defined by the user in timeOutCallback
     * @param timeOutEvent
     */
    , charonTimeOut: function (timeOutEvent) {
        Charon.prototype.debug('running timeout');

        // Check if the timeout callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.timeoutCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.timeoutCallback);
            // Call the user defined timeout function with the timeOut event
            Charon.prototype.debug(typeof Charon.prototype.timeoutCallback);
            if (typeof Charon.prototype.timeoutCallback === 'function')
            {
                Charon.prototype.timeoutCallback(timeOutEvent);
            }
        }
    }

    /**
     * Loadend event functionality.
     * This contains the default functionality for handling the loadend event.
     * Once the default functionality has ran, this will call the loadend callback defined by the user in loadEndCallback
     * @param loadEndEvent
     */
    , charonLoadEnd: function (loadEndEvent) {
        Charon.prototype.debug('running loadend');

        // Check if the loadend callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadEndCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadEndCallback);
            // Call the user defined loadend function with the loadEnd event
            Charon.prototype.debug(typeof Charon.prototype.loadEndCallback);
            if (typeof Charon.prototype.loadEndCallback === 'function')
            {
                Charon.prototype.loadEndCallback(loadEndEvent);
            }
        }
    }

    /**
     * readystatechange event functionality.
     * This contains the default functionality for handling the readystatechange event.
     * Once the default functionality has ran, this will call the readystatechange callback defined by the user in readyStateChangeCallback
     * @param loadEndEvent
     */
    , charonReadyStateChange: function (readyStateChangeEvent) {
        Charon.prototype.debug('running readystatechange');

        // Check if the readystatechange callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.readyStateChangeCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.readyStateChangeCallback);
            // Call the user defined readystatechange function with the readystatechange event
            Charon.prototype.debug(typeof Charon.prototype.readyStateChangeCallback);
            if (typeof Charon.prototype.readyStateChangeCallback === 'function')
            {
                Charon.prototype.readyStateChangeCallback(readyStateChangeEvent);
            }
        }
    }

};<commit_msg>Standardise the default callback values to null.  Remove commented out code from the callbackIsSet function<commit_after>/******************************************************************************
 The MIT License (MIT)

 Copyright (c) 2016 Gary Bell

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 ******************************************************************************
 *
 * A library for uploading files and sending them to a server without
 * submitting a full page form page.
 *
 *****************************************************************************/

/**
 * Constructor for Charon
 * @param setupObject - An object with values to override the default Charon values
 */
var Charon = function (setupObject) {

    // Loop through each set object item and set it against the relevant item on the prototype object
    for (var key in setupObject)
    {
        //this.key = setupObject.key
        eval('Charon.prototype.' + key + ' = setupObject. ' + key);
    }

    return Charon.prototype;

};

/**
 * The prototype for the Charon object.
 * All functionality will be in here
 * @type {{url: string, file: string, additionalData: string}}
 */
Charon.prototype = {

    /**
     * Define variables for the upload sending
     */
    // URL to post the files to
    url: ''

    // file input field to upload
    , file: ''

    // other information to submit at the same time as the file
    , additionalData: ''

    // should we output debug to the console
    , outputDebugging: false

    /**
     * User defined callbacks for different events.
     * This will allow the using application to customise the way they handle each events.
     */
    // the callback to run when progress has begun
    , loadStartCallback: null

    // the callback to run when the operation is in progress
    , progressCallback: null

    // the callback to run when the loading of the file has been aborted
    , abortCallback: null

    // the callback to run when a resource failed to load
    , errorCallback: null

    // the callback to run when a resource and its dependents have finished loading
    , loadCallback: null

    // the callback to run when a resource has timed out
    , timeoutCallback: null

    // the callback to run when progression has stopped.  This is called after error, abort or load
    , loadEndCallback: null

    // the callback to run whenever the readyState of the resource load has changed
    , readyStateChangeCallback: null

    /**
     * Pass messages in to be shown on the console.  Will only output if outputDebugging is set to true
     * @param message - the message to output to the console log
     */
    , debug: function (message) {
        if (this.outputDebugging) {
            console.log(message);
        }
    }

    /**
     * Check to see is a particular user callback is set.  If so, we know we can make a function call
     * @param callbackName - the name of the callback to use.  This will be one of:
     *  - loadStartCallback
     *  - progressCallback
     *  - abortCallback
     *  - errorCallback
     *  - loadCallback
     *  - timeoutCallback
     *  - loadEndCallback
     *  - readyStateChangeCallback
     * @return boolean - true is the callback is set.  False if it is not.
     */
    , callbackIsSet: function (callbackName) {
        // going to assume the callback is not set.
        var callbackSet = false;

        /**
         * Check to see that the passed in callbackName is a valid callback reference
         * Whilst this makes painful reading, we're going to be using the eval function so don't want anything malicious to be called by this
         */
        if (callbackName !== undefined
            && callbackName !== ''
            && callbackName !== null
        ) {
            callbackSet = true;
        }

        return callbackSet;
    }

    /**
     * Check if a particular item is traversable by a for-key-in loop
     * @param objectToTest - the object/item to check when seeing if it is an array
     * @return boolean
     */
    , isTraversable: function (objectToTest) {
        this.debug(Object.prototype.toString(objectToTest));
        this.debug(objectToTest);
        return (Object.prototype.toString(objectToTest) === "[object Array]" ||
            Object.prototype.toString(objectToTest) === "[object Object]");
    }

    /**
     * Upload the file and any additional data which might be needed
     */
    , sendFile: function () {

        // check we have set the URL before we try and do anything
        if (this.url === '')
        {
            throw new Error('No URL set.  Cannot continue');
        }

        // setup a form data variable so we can build the form with the information we need rather than everything.
        var formData = new FormData();

        /**
         * Check that additionalData is an array
         * If it is, get each item and build the form data
         */
        if (this.isTraversable(this.additionalData)) {
            for (key in this.additionalData) {
                // to stop a blank row going in
                if (this.additionalData[key] !== undefined) {
                    // add the item to the form data in the form key, value
                    formData.append(key, this.additionalData[key]);
                }
            }
        }
        else
        {
            this.debug('additionaData is not an array');
        }

        try {
            // set the file to upload
            var uploadFile = this.file.files[0];
            formData.append('charonFile', uploadFile);
        }
        catch(e)
        {
            throw new Error('No file set for upload.  Cannot continue');
        }

        // create the XMLHttpRequest object for sending the information
        var xhr = new XMLHttpRequest();

        // open the request, set the URL from that was given to send the file to, and set the transport to be POST
        xhr.open('POST', this.url, true);

        /**
         * Set up the callback functionality for the different events which can be used
         */

        // setup the loadstart listener and functionality
        xhr.addEventListener('loadstart', this.charonLoadStart);

        // setup the progress listener and functionality
        xhr.addEventListener('progress', this.charonProgress);

        // setup the abort listener and functionality
        xhr.addEventListener('abort', this.charonAbort);

        // setup the error listener and functionality
        xhr.addEventListener('error', this.charonError);

        // setup the load listener and functionality
        xhr.addEventListener('load', this.charonLoad);

        // setup the timeout listener and functionality
        xhr.addEventListener('timeout', this.charonTimeOut);

        // setup the loadend listener and functionality
        xhr.addEventListener('loadend', this.charonLoadEnd);

        // setup the readystatechange listener and functionality
        xhr.addEventListener('readystatechange', this.charonReadyStateChange);

        // we've set up all of the functionality we need, now send the actual form
        xhr.send(formData);
    }

    /**
     * Load start event functionality.
     * This contains the default functionality for handling the loadstart event.
     * Once the default functionality has ran, this will call the loadstart callback defined by the user in loadStartCallback
     * @param loadStartEvent
     */
    , charonLoadStart: function (loadStartEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running loadStart');

        // Check if the loadStart callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadStartCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadStartCallback);
            // Call the user defined loadstart function with the loadstart event
            Charon.prototype.debug(typeof Charon.prototype.loadStartCallback);
            if (typeof Charon.prototype.loadStartCallback === 'function')
            {
                Charon.prototype.loadStartCallback(loadStartEvent);
            }
        }
    }

    /**
     * Progress event functionality.
     * This contains the default functionality for handling the progress event.
     * Once the default functionality has ran, this will call the progress callback defined by the user in progressCallback
     * @param progressEvent
     */
    , charonProgress: function (progressEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running progress');

        // Check if the progress callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.progressCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.progressCallback);
            // Call the user defined progress function with the progress event
            Charon.prototype.debug(typeof Charon.prototype.progressCallback);
            if (typeof Charon.prototype.progressCallback === 'function')
            {
                Charon.prototype.progressCallback(progressEvent);
            }
        }
    }

    /**
     * Abort event functionality.
     * This contains the default functionality for handling the abort event.
     * Once the default functionality has ran, this will call the abort callback defined by the user in abortCallback
     * @param abortEvent
     */
    , charonAbort: function (abortEvent) {
        // there is no default functionality for this built in
        Charon.prototype.debug('running abort');

        // Check if the abort callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.abortCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.abortCallback);
            // Call the user defined abort function with the abort event
            //eval(this.abortCallback + "( " + abortEvent + ");");
            if (typeof Charon.prototype.abortCallback === 'function')
            {
                Charon.prototype.abortCallback(abortEvent);
            }
        }
    }

    /**
     * Error event functionality.
     * This contains the default functionality for handling the error event.
     * Once the default functionality has ran, this will call the error callback defined by the user in errorCallback
     * @param errorEvent
     */
    , charonError: function (errorEvent) {
        Charon.prototype.debug('running error');

        // output an error to the console.  We don't want this to be hidden
        console.log('An error occurred when transferring the file');
        // full dump of the error event
        console.log(errorEvent);

        // Check if the error callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.errorCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.errorCallback);
            // Call the user defined error function with the error event
            Charon.prototype.debug(typeof Charon.prototype.errorCallback);
            if (typeof Charon.prototype.errorCallback === 'function')
            {
                Charon.prototype.errorCallback(errorEvent);
            }
        }
    }

    /**
     * Load event functionality.
     * This contains the default functionality for handling the load event.
     * Once the default functionality has ran, this will call the load callback defined by the user in loadCallback
     * @param loadEvent
     */
    , charonLoad: function (loadEvent) {
        Charon.prototype.debug('running load');

        // Check if the load callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadCallback);
            // Call the user defined load function with the load event
            Charon.prototype.debug(typeof Charon.prototype.loadCallback);
            if (typeof Charon.prototype.loadCallback === 'function')
            {
                Charon.prototype.loadCallback(loadEvent);
            }
        }
    }

    /**
     * Timeout event functionality.
     * This contains the default functionality for handling the timeout event.
     * Once the default functionality has ran, this will call the timeout callback defined by the user in timeOutCallback
     * @param timeOutEvent
     */
    , charonTimeOut: function (timeOutEvent) {
        Charon.prototype.debug('running timeout');

        // Check if the timeout callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.timeoutCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.timeoutCallback);
            // Call the user defined timeout function with the timeOut event
            Charon.prototype.debug(typeof Charon.prototype.timeoutCallback);
            if (typeof Charon.prototype.timeoutCallback === 'function')
            {
                Charon.prototype.timeoutCallback(timeOutEvent);
            }
        }
    }

    /**
     * Loadend event functionality.
     * This contains the default functionality for handling the loadend event.
     * Once the default functionality has ran, this will call the loadend callback defined by the user in loadEndCallback
     * @param loadEndEvent
     */
    , charonLoadEnd: function (loadEndEvent) {
        Charon.prototype.debug('running loadend');

        // Check if the loadend callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.loadEndCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.loadEndCallback);
            // Call the user defined loadend function with the loadEnd event
            Charon.prototype.debug(typeof Charon.prototype.loadEndCallback);
            if (typeof Charon.prototype.loadEndCallback === 'function')
            {
                Charon.prototype.loadEndCallback(loadEndEvent);
            }
        }
    }

    /**
     * readystatechange event functionality.
     * This contains the default functionality for handling the readystatechange event.
     * Once the default functionality has ran, this will call the readystatechange callback defined by the user in readyStateChangeCallback
     * @param loadEndEvent
     */
    , charonReadyStateChange: function (readyStateChangeEvent) {
        Charon.prototype.debug('running readystatechange');

        // Check if the readystatechange callback is set, and run the function if so
        if (Charon.prototype.callbackIsSet(Charon.prototype.readyStateChangeCallback)) {
            Charon.prototype.debug('Calling user defined function ' + Charon.prototype.readyStateChangeCallback);
            // Call the user defined readystatechange function with the readystatechange event
            Charon.prototype.debug(typeof Charon.prototype.readyStateChangeCallback);
            if (typeof Charon.prototype.readyStateChangeCallback === 'function')
            {
                Charon.prototype.readyStateChangeCallback(readyStateChangeEvent);
            }
        }
    }

};<|endoftext|>


<commit_before>import { BuildOverview } from '../../src/build-overview';

describe('the build overview', () => {
  it('activate function should ask the failedbuilds from buildservice with the baseurl from the parameters and set the result on the build overview', (done) => {
    let buildServiceStub = {
      getAllFailedBuilds: function getAllFailedBuilds (baseUrl) {
        expect(baseUrl).toEqual("baseUrl");
        return Promise.resolve(['a', 'b', 'c'])
      }
    }
    let buildOverview = new BuildOverview(buildServiceStub);
    buildOverview.activate({baseUrl: "baseUrl"});
    expectAtEndOfEventLoop(() => expect(buildOverview.builds).toEqual(['a', 'b', 'c']))

    function expectAtEndOfEventLoop(expectFunction) {
      setTimeout(() => {
        expectFunction();
        done();
      }, 0);
    }
  });
});

<commit_msg>cleanup test<commit_after>import { BuildOverview } from '../../src/build-overview';

describe('the build overview', () => {
  it('activate function should ask the failedbuilds from buildservice with the baseurl from the parameters and set the result on the build overview', (done) => {
    let buildServiceStub = {
      getAllFailedBuilds: function getAllFailedBuilds(baseUrl) {
        expect(baseUrl).toEqual("baseUrl");
        return Promise.resolve(['a', 'b', 'c'])
      }
    }
    let buildOverview = new BuildOverview(buildServiceStub);
    buildOverview.activate({ baseUrl: "baseUrl" });
    expectAtEndOfJobQueue(() => expect(buildOverview.builds).toEqual(['a', 'b', 'c']))

    function expectAtEndOfJobQueue(expectFunction) {
      Promise.resolve().then(expectFunction).finally(done);
    }
  });
});

<|endoftext|>


<commit_before>/* Copyright 2018 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { CharacterType, getCharacterType } from "../../web/pdf_find_utils.js";

describe("pdf_find_utils", function () {
  describe("getCharacterType", function () {
    it("gets expected character types", function () {
      const characters = {
        A: CharacterType.ALPHA_LETTER,
        a: CharacterType.ALPHA_LETTER,
        "0": CharacterType.ALPHA_LETTER,
        "5": CharacterType.ALPHA_LETTER,
        Ä: CharacterType.ALPHA_LETTER, // 'Ä'
        ä: CharacterType.ALPHA_LETTER, // 'ä'
        _: CharacterType.ALPHA_LETTER,
        " ": CharacterType.SPACE,
        "\t": CharacterType.SPACE,
        "\r": CharacterType.SPACE,
        "\n": CharacterType.SPACE,
        "\xA0": CharacterType.SPACE,
        "-": CharacterType.PUNCT,
        ",": CharacterType.PUNCT,
        ".": CharacterType.PUNCT,
        ";": CharacterType.PUNCT,
        ":": CharacterType.PUNCT,
        "\u2122": CharacterType.ALPHA_LETTER, // trademark
        ล: CharacterType.THAI_LETTER,
        䀀: CharacterType.HAN_LETTER,
        縷: CharacterType.HAN_LETTER,
        ダ: CharacterType.KATAKANA_LETTER,
        ぐ: CharacterType.HIRAGANA_LETTER,
        ﾀ: CharacterType.HALFWIDTH_KATAKANA_LETTER,
      };

      for (const character in characters) {
        const charCode = character.charCodeAt(0);
        const type = characters[character];

        expect(getCharacterType(charCode)).toEqual(type);
      }
    });
  });
});
<commit_msg>Restore the "gets expected character types" test, in `test/unit/pdf_find_utils_spec.js`, to its intended formatting<commit_after>/* Copyright 2018 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { CharacterType, getCharacterType } from "../../web/pdf_find_utils.js";

describe("pdf_find_utils", function () {
  describe("getCharacterType", function () {
    it("gets expected character types", function () {
      const characters = {
        A: CharacterType.ALPHA_LETTER,
        a: CharacterType.ALPHA_LETTER,
        "0": CharacterType.ALPHA_LETTER,
        "5": CharacterType.ALPHA_LETTER,
        "\xC4": CharacterType.ALPHA_LETTER, // "Ä"
        "\xE4": CharacterType.ALPHA_LETTER, // "ä"
        _: CharacterType.ALPHA_LETTER,
        " ": CharacterType.SPACE,
        "\t": CharacterType.SPACE,
        "\r": CharacterType.SPACE,
        "\n": CharacterType.SPACE,
        "\xA0": CharacterType.SPACE, // nbsp
        "-": CharacterType.PUNCT,
        ",": CharacterType.PUNCT,
        ".": CharacterType.PUNCT,
        ";": CharacterType.PUNCT,
        ":": CharacterType.PUNCT,
        "\u2122": CharacterType.ALPHA_LETTER, // trademark
        "\u0E25": CharacterType.THAI_LETTER,
        "\u4000": CharacterType.HAN_LETTER,
        "\uF950": CharacterType.HAN_LETTER,
        "\u30C0": CharacterType.KATAKANA_LETTER,
        "\u3050": CharacterType.HIRAGANA_LETTER,
        "\uFF80": CharacterType.HALFWIDTH_KATAKANA_LETTER,
      };

      for (const character in characters) {
        const charCode = character.charCodeAt(0);
        const type = characters[character];

        expect(getCharacterType(charCode)).toEqual(type);
      }
    });
  });
});
<|endoftext|>


<commit_before>/*jshint bitwise:true, indent:2, curly:true eqeqeq:true, immed:true,
latedef:true, newcap:true, noarg:true, regexp:true, undef:true,
trailing:true white:true*/
/*global XV:true, Backbone:true, enyo:true, XT:true */

(function () {
  "use strict";

  enyo.kind({
    name: "XV.ListTest",
    kind: "enyo.TestSuite",
    components: [
      { kind: "XV.List", name: "list" }
    ],
    /**
      Test for incident #18662.
      Makes two fetches to the model. The first call will take so long
      that the second one will have already been made by the time
      that it returns. This test is to make sure that the first
      query is not processen when it returns.
     */
    testQueryOrder: function () {
      var that = this,
        list = this.$.list,
        mockModel = {
          fetch: function (options) {
            setTimeout(options.success, options.waitTime);
          }
        },
        options = {};

      list.setValue(mockModel);

      // First call
      options.waitTime = 200;
      options.success = function () {
        that.finish("The first, late call should be suppressed.");
      };
      list.fetch(options);

      // Second call
      options.waitTime = 100;
      options.success = null;
      list.fetch(options);

      // if the success method of the first call hasn't complained within 300ms,
      // then it has been suppressed, and the test should pass
      setTimeout(that.finish, 300);
    }
  });
}());

<commit_msg>issue #19133: fixed list test<commit_after>/*jshint bitwise:true, indent:2, curly:true eqeqeq:true, immed:true,
latedef:true, newcap:true, noarg:true, regexp:true, undef:true,
trailing:true white:true*/
/*global XV:true, Backbone:true, enyo:true, XT:true */

(function () {
  "use strict";

  enyo.kind({
    name: "XV.ListTest",
    kind: "enyo.TestSuite",
    components: [
      { kind: "XV.List", name: "list" }
    ],
    /**
      Test for incident #18662.
      Makes two fetches to the model. The first call will take so long
      that the second one will have already been made by the time
      that it returns. This test is to make sure that the first
      query is not processen when it returns.
     */
    testQueryOrder: function () {
      var that = this,
        list = this.$.list,
        mockModel = {
          fetch: function (options) {
            setTimeout(enyo.bind(this, options.success), options.waitTime);
          }
        },
        options = {};

      list.setValue(mockModel);

      // First call
      options.waitTime = 200;
      options.success = function () {
        that.finish("The first, late call should be suppressed.");
      };
      list.fetch(options);

      // Second call
      options.waitTime = 100;
      options.success = null;
      list.fetch(options);

      // if the success method of the first call hasn't complained within 300ms,
      // then it has been suppressed, and the test should pass
      setTimeout(enyo.bind(this, this.finish), 300);
    }
  });
}());

<|endoftext|>


<commit_before>/*global unexpected:true*/
var proxyquire = require('proxyquire');
unexpected = require('unexpected').installPlugin(
  proxyquire('./lib/unexpectedResemble', {
    'magicpen-media': proxyquire('magicpen-media', {
      gettemporaryfilepath: function(options) {
        return '/tmp/image' + ((options && options.suffix) || '');
      }
    })
  })
);
unexpected.output.preferredWidth = 80;
<commit_msg>expect.clone() before installing plugins (to be compatible with Unexpected 11)<commit_after>/*global unexpected:true*/
var proxyquire = require('proxyquire');
unexpected = require('unexpected')
  .clone()
  .installPlugin(
    proxyquire('./lib/unexpectedResemble', {
      'magicpen-media': proxyquire('magicpen-media', {
        gettemporaryfilepath: function(options) {
          return '/tmp/image' + ((options && options.suffix) || '');
        }
      })
    })
  );
unexpected.output.preferredWidth = 80;
<|endoftext|>


<commit_before>/*global beforeEach, afterEach, describe, it, inject, expect, module, spyOn, fullcalendar, angular, $*/

describe('carousel', function () {
  'use strict';

  var scope, $compile, $sandbox;

  beforeEach(module('angular-carousel'));

  beforeEach(inject(function ($rootScope, _$compile_) {
      scope = $rootScope;
      $compile = _$compile_;
      $sandbox = $('

').appendTo($('body'));
  }));

  afterEach(function() {
    $sandbox.remove();
    scope.$destroy();
  });

 function compileTpl() {
    var sampleData = {
      scope: {
        items: [
          {text: '1st slide'},
          {text: '2nd slide'},
          {text: '3rd slide'}
        ]
      },
      template: '

{{ item.text }}

'
    };
    angular.extend(scope, sampleData.scope);
    var $element = $(sampleData.template).appendTo($sandbox);
    $element = $compile($element)(scope);
    scope.$digest();
    return $element;
  }

  describe('check directive compilation', function () {
    it('should add a wrapper div around the ul/li', function () {
        var elm = compileTpl();
        expect(elm.parent().hasClass('carousel-container')).toBe(true);
    });
    it('should add a class to the ul', function () {
        var elm = compileTpl();
        expect(elm.hasClass('carousel-slides')).toBe(true);
    });
    it('should add announcer attribute to each slide', function () {
        var elm = compileTpl();
        expect(elm.find('li[slide-announcer=true]').length).toBe(3);
    });
    it('should add announcer attribute to each slide dynamically', function () {
        var elm = compileTpl();
        scope.items.push({text:'4th slide'});
        scope.$digest();
        expect(elm.find('li[slide-announcer=true]').length).toBe(4);
    });
    it('should add announcer attribute to each slide 2', function () {
        var elm = compileTpl();
        expect(elm.find('li[slide-announcer=true]').length).toBe(3);
    });
  });

  // function compileDirective(template) {
  //   template = template ? templates[template] : templates['default'];
  //   angular.extend(scope, template.scope);
  //   var $element = $(template.element).appendTo($sandbox);
  //   $element = $compile($element)(scope);
  //   scope.$digest(); // evaluate $evalAsync queue used by $q
  //   $timeout.flush();
  //   return $element;
  // }

  // describe('default template', function() {

  //   var elm, select, menu;
  //   beforeEach(function() {
  //     elm = compileDirective();
  //     select = elm.next('.bootstrap-select');
  //     menu = select.find('ul[role=menu]');
  //   });

  //   it('initialises bootstrap select on the element', function () {
  //     expect(select.length).toBe(1);
  //   });

  //   it('adds every item to the bootstrap select menu', function () {
  //     expect(menu.children().length).toBe(scope.items.length);
  //   });

  //   it('updates the bootstrap select menu when items are changed', function () {
  //     scope.items.push({id: '4', name: 'qux'});
  //     scope.$digest();
  //     expect(menu.children().length).toBe(scope.items.length);
  //   });

  //   it('selects the correct item by default', function () {
  //     expect(menu.find('.selected').text()).toBe('bar');
  //   });

  //   it('updates the scope when a new item is selected', function () {
  //     menu.find('li a').first().click();
  //     expect(scope.selectedItem).toBe('1');
  //   });

  //   it('updates bootstrap select when the model changes', function () {
  //     scope.selectedItem = '3';
  //     scope.$digest();
  //     expect(menu.find('.selected').text()).toBe('baz');
  //   });

  //   it('does not add ng-scope class to bootstrap select element', function () {
  //     expect(select.hasClass('ng-scope')).toBe(false);
  //   });

    // it('adds new classes from original element when the model changes', function () {
    //   elm.addClass('dummy');
    //   scope.model.item = 1;
    //   scope.$digest();
    //   expect(select.hasClass('dummy')).toBe(true);
    // });

    // it('syncs classes removed from original element when the model changes', function () {
    //   element.addClass('dummy');
    //   scope.model.item = 1;
    //   scope.$digest();
    //   element.removeClass('dummy');
    //   scope.model.item = 2;
    //   scope.$digest();
    //   expect(select.hasClass('dummy')).toBe(false);
    // });

 // });

});
<commit_msg>style(tests): cleanup<commit_after>/*global beforeEach, afterEach, describe, it, inject, expect, module, angular, $*/

describe('carousel', function () {
  'use strict';

  var scope, $compile, $sandbox;

  beforeEach(module('angular-carousel'));

  beforeEach(inject(function ($rootScope, _$compile_) {
      scope = $rootScope;
      $compile = _$compile_;
      $sandbox = $('

').appendTo($('body'));
  }));

  afterEach(function() {
    $sandbox.remove();
    scope.$destroy();
  });

 function compileTpl() {
    var sampleData = {
      scope: {
        items: [
          {text: '1st slide'},
          {text: '2nd slide'},
          {text: '3rd slide'}
        ]
      },
      template: '

{{ item.text }}

'
    };
    angular.extend(scope, sampleData.scope);
    var $element = $(sampleData.template).appendTo($sandbox);
    $element = $compile($element)(scope);
    scope.$digest();
    return $element;
  }

  describe('check directive compilation', function () {
    it('should add a wrapper div around the ul/li', function () {
        var elm = compileTpl();
        expect(elm.parent().hasClass('carousel-container')).toBe(true);
    });
    it('should add a class to the ul', function () {
        var elm = compileTpl();
        expect(elm.hasClass('carousel-slides')).toBe(true);
    });
    it('should add announcer attribute to each slide', function () {
        var elm = compileTpl();
        expect(elm.find('li[slide-announcer=true]').length).toBe(3);
    });
    it('should add announcer attribute to each slide dynamically', function () {
        var elm = compileTpl();
        scope.items.push({text:'4th slide'});
        scope.$digest();
        expect(elm.find('li[slide-announcer=true]').length).toBe(4);
    });
  });
});
<|endoftext|>


<commit_before>
let amqp = require('amqplib');
let sinon = require('sinon');
let chai = require('chai');
let expect = chai.expect;
let Application = require('../../src/application');

describe('Application', () => {
  let app;
  let broker;
  let channel;
  let transport;

  beforeEach(() => {
    app = new Application({ name: 'test' });
  });

  beforeEach(() => {
    broker = {
      createChannel: () => channel,
      close: sinon.stub()
    };
  });

  beforeEach(() => {
    channel = {
      ack: sinon.stub(),
      assertExchange: sinon.stub(),
      assertQueue: sinon.stub(),
      bindExchange: sinon.stub(),
      bindQueue: sinon.stub(),
      close: sinon.stub(),
      consume: sinon.stub(),
      nack: sinon.stub(),
      prefetch: sinon.stub(),
      publish: sinon.stub(),
      sendToQueue: sinon.stub()
    };
    // we need to return the queue so that star works correctly
    channel.assertQueue.withArgs('', { exclusive: true }).returns({ queue: 'exclusive-queue' });
  });

  beforeEach(() => {
    // stub connect so that it returns our fake broker
    sinon.stub(amqp, 'connect').returns(broker);
  });

  beforeEach(() => {
    transport = {
      start: sinon.stub(),
      stop: sinon.stub(),
      prepEmission: sinon.stub().returns({ send: 'send', headers: { }}),
      requestData: sinon.stub()
    };
  });

  afterEach(() => {
    amqp.connect.restore();
  });

  describe('.start', () => {
    it('should assert the application exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertExchange.withArgs('app').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should assert the service exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertExchange.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should bind the service exchange to the application exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.bindExchange.withArgs('test', 'app').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should assert the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should add a 1 hour TTL for the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('test', { expires: 3600000 }).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should generate the exclusive queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('', { exclusive: true }).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should set prefetch for the channel', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.prefetch.withArgs(5).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should start consuming on the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.consume.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should start consuming on the exclusive queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.consume.withArgs('exclusive-queue').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
  });

  describe('.stop', () => {
    describe('when broker is connected', () => {
      it('should close the broker', (done) => {
        app
          .start({ brokerPath: 'broker' })
          .then(() => app.stop())
          .then(() => expect(broker.close.called).to.be.true)
          .then(() => done())
          .catch(done);
      });
    });
  });

  describe('.emit', () => {
    const start = async () => {
      await app.start({ brokerPath: 'broker' });
      await app.set('transport', transport);
      return start;
    };
    // describe('when sending to a queue directly', () => {
    //   it('should include the correlationId', (done) => {

    //   });
    //   it('should convert the data to a buffer', (done) => {

    //   });
    //   it('should merge user supplied headers', (done) => {

    //   });
    //   it('should apply content-type header based on the buffer', (done) => {

    //   });
    //   it('should apply transport headers', (done) => {

    //   });
    // });
    // describe('when broadcasting message', () => {
    //   it('should include the correlationId', (done) => {

    //   });
    //   it('should convert the data to a buffer', (done) => {

    //   });
    //   it('should merge user supplied headers', (done) => {

    //   });
    //   it('should apply content-type header based on the buffer', (done) => {

    //   });
    //   it('should apply transport headers', (done) => {

    //   });
    // });
  });

});
<commit_msg>Added application.emit tests<commit_after>
let amqp = require('amqplib');
let sinon = require('sinon');
let chai = require('chai');
let expect = chai.expect;
let Application = require('../../src/application');

describe('Application', () => {
  let app;
  let broker;
  let channel;

  beforeEach(() => {
    app = new Application({ name: 'test' });
  });

  beforeEach(() => {
    broker = {
      createChannel: () => channel,
      close: sinon.stub()
    };
  });

  beforeEach(() => {
    channel = {
      ack: sinon.stub(),
      assertExchange: sinon.stub(),
      assertQueue: sinon.stub(),
      bindExchange: sinon.stub(),
      bindQueue: sinon.stub(),
      close: sinon.stub(),
      consume: sinon.stub(),
      nack: sinon.stub(),
      prefetch: sinon.stub(),
      publish: sinon.stub(),
      sendToQueue: sinon.stub()
    };
    // we need to return the queue so that star works correctly
    channel.assertQueue.withArgs('', { exclusive: true }).returns({ queue: 'exclusive-queue' });
  });

  beforeEach(() => {
    // stub connect so that it returns our fake broker
    sinon.stub(amqp, 'connect').returns(broker);
  });

  afterEach(() => {
    amqp.connect.restore();
  });

  describe('.start', () => {
    it('should assert the application exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertExchange.withArgs('app').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should assert the service exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertExchange.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should bind the service exchange to the application exchange', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.bindExchange.withArgs('test', 'app').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should assert the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should add a 1 hour TTL for the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('test', { expires: 3600000 }).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should generate the exclusive queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.assertQueue.withArgs('', { exclusive: true }).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should set prefetch for the channel', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.prefetch.withArgs(5).called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should start consuming on the service queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.consume.withArgs('test').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
    it('should start consuming on the exclusive queue', (done) => {
      app
        .start({ brokerPath: 'broker' })
        .then(() => expect(channel.consume.withArgs('exclusive-queue').called).to.be.true)
        .then(() => done())
        .catch(done);
    });
  });

  describe('.stop', () => {
    describe('when broker is connected', () => {
      it('should close the broker', (done) => {
        app
          .start({ brokerPath: 'broker' })
          .then(() => app.stop())
          .then(() => expect(broker.close.called).to.be.true)
          .then(() => done())
          .catch(done);
      });
    });
  });

  describe('.emit', () => {
    const start = async () => {
      await app.start({ brokerPath: 'broker' });
      return app;
    };
    describe('when sending to a queue directly', () => {
      it('should call sendToQueue', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }, 'direct-queue'))
          .then(() => expect(channel.sendToQueue.withArgs('direct-queue').called).to.be.true)
          .then(() => done())
          .catch(done);
      });
      it('should convert the data to a buffer', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }, 'direct-queue'))
          .then(() => expect(channel.sendToQueue.args[0][1]).to.deep.equal(Buffer.from('data')))
          .then(() => done())
          .catch(done);
      });
      it('should include the correlationId', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }, 'direct-queue'))
          .then(() => expect(channel.sendToQueue.args[0][2].correlationId).is.not.undefined)
          .then(() => done())
          .catch(done);
      });
      it('should merge user supplied headers', (done) => {
        start()
          .then(() => app.emit('test', 'data', { headers: { test: 'header' } }, 'direct-queue'))
          .then(() => expect(channel.sendToQueue.args[0][2].headers.test).to.equal('header'))
          .then(() => done())
          .catch(done);
      });
      it('should apply content-type header based on the buffer', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }, 'direct-queue'))
          .then(() => expect(channel.sendToQueue.args[0][2].headers.contentType).to.equal('string'))
          .then(() => done())
          .catch(done);
      });
    });
    describe('when broadcasting message', () => {
      it('should call publish', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }))
          .then(() => expect(channel.publish.withArgs('app', 'test').called).to.be.true)
          .then(() => done())
          .catch(done);
      });
      it('should convert the data to a buffer', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }))
          .then(() => expect(channel.publish.args[0][2]).to.deep.equal(Buffer.from('data')))
          .then(() => done())
          .catch(done);
      });
      it('should include the correlationId', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }))
          .then(() => expect(channel.publish.args[0][3].correlationId).is.not.undefined)
          .then(() => done())
          .catch(done);
      });
      it('should merge user supplied headers', (done) => {
        start()
          .then(() => app.emit('test', 'data', { headers: { test: 'header' } }))
          .then(() => expect(channel.publish.args[0][3].headers.test).to.equal('header'))
          .then(() => done())
          .catch(done);
      });
      it('should apply content-type header based on the buffer', (done) => {
        start()
          .then(() => app.emit('test', 'data', { }))
          .then(() => expect(channel.publish.args[0][3].headers.contentType).to.equal('string'))
          .then(() => done())
          .catch(done);
      });
    });
  });

});
<|endoftext|>


<commit_before>var simpleInput = '<input type="text" name="firstName" placeholder="First name" />'
  , $input;

module("defaults", {
  setup: function () {
    $input = $(simpleInput);
    $('#qunit-fixture').append($input);
    $input.placeover(); // Initialize with defaults

  },
  teardown: function () {
    $input.remove();
    $input = null;
  }
});

test("displays text after initializing blank input", function () {
  ok(textVisible($input), "Text to be visible");
});

test("does not display after intializing filled input", function () {
  var $filledInput = $(simpleInput);
  $filledInput.val('value');
  $filledInput.placeover();

  ok(textNotVisible($filledInput));
});

test("hides text when setting value to input", function () {
  $input.val('value');
  ok(textNotVisible($input));
});

test("displays text on input focus", function () {
  $input.trigger('focus');
  ok(textVisible($input))
});

/*test("hides text when typing", function () {
  var e = $.Event('keydown');
  e.which = 65;
  ok(textVisible($input));
  $input.trigger(e);
  ok(textNotVisible($input));
});*/

test("displays text when input is empty", function () {
  $input.val('A').val('');
  ok(textVisible($input));
});

test("displays text on input blur", function () {

  $input.blur();
  ok(textVisible($input));

});

test("sets the input value", function () {

  ok(textVisible($input));
  $input.val('value');
  ok(textNotVisible($input));

});

test("updates the input value", function () {

  $input.val('value');
  ok(textNotVisible($input));
  $input.val('value2');
  ok(textNotVisible($input));

});

test("clears the input value", function () {

  $input.val('value');
  ok(textNotVisible($input));
  $input.val('');
  ok(textVisible($input));

});

test("updates the placeover text", function () {

  $input.placeover('text', 'new placeholder');
  strictEqual('new placeholder', getText($input).text(), "Text to be updated");

});

module("explicit invocation", {
  setup: function () {
    $input = $(simpleInput);
    $('#qunit-fixture').append($input);
    $input.placeover({ explicit: true });
  },
  teardown: function () {
    $input.remove();
    $input = null;
  }
});

test("appears on show", function () {
  $input.placeover('hide');
  ok(textNotVisible($input), "Text to be hidden");
  $input.placeover('show');
  ok(textVisible($input), "Text to be visible");
});

test("disappears on hide", function () {
  ok(textVisible($input), "Text to be visible");
  $input.placeover('hide');
  ok(textNotVisible($input), "Text to be hidden")
});

module("eventing", {
  setup: function () {
    $input = $('<input />');
    $('#qunit-fixture').append($input);
    $input.placeover({ explicit: true });
  },
  teardown: function() {
    $input.remove();
    $input = null;
  }
});

test("triggers show event before displaying text", function () {

  // Hide the placeover to start
  $input.placeover('hide');

  // Attach handler to show event
  $input.on('show.placeover', function () {
    ok(textNotVisible($input));
  });

  // Show placeover
  $input.placeover('show');

  ok(textVisible($input));

});

test("is not shown when prevented", function () {

  // Hide the placeover to start
  $input.placeover('hide');

  // Attach handler to event
  $input.on('show.placeover', function (e) {
    e.preventDefault();
  });

  // Show placeover
  $input.placeover('show');

  ok(textNotVisible($input), "Text to be prevented from showing");

});

test("is not hidden when prevented", function () {

  // Show the placeover to start
  $input.placeover('show');

  // Attache handler to event
  $input.on('hide.placeover', function (e) {
    e.preventDefault();
  });

  // Hide placeover
  $input.placeover('hide');

  ok(textVisible($input), "Text to still be visible");

});<commit_msg>Fix jshint issues.<commit_after>var simpleInput = '<input type="text" name="firstName" placeholder="First name" />'
  , $input;

module("defaults", {
  setup: function () {
    $input = $(simpleInput);
    $('#qunit-fixture').append($input);
    $input.placeover(); // Initialize with defaults

  },
  teardown: function () {
    $input.remove();
    $input = null;
  }
});

test("displays text after initializing blank input", function () {
  ok(textVisible($input), "Text to be visible");
});

test("does not display after intializing filled input", function () {
  var $filledInput = $(simpleInput);
  $filledInput.val('value');
  $filledInput.placeover();

  ok(textNotVisible($filledInput));
});

test("hides text when setting value to input", function () {
  $input.val('value');
  ok(textNotVisible($input));
});

test("displays text on input focus", function () {
  $input.trigger('focus');
  ok(textVisible($input));
});

/*test("hides text when typing", function () {
  var e = $.Event('keydown');
  e.which = 65;
  ok(textVisible($input));
  $input.trigger(e);
  ok(textNotVisible($input));
});*/

test("displays text when input is empty", function () {
  $input.val('A').val('');
  ok(textVisible($input));
});

test("displays text on input blur", function () {

  $input.blur();
  ok(textVisible($input));

});

test("sets the input value", function () {

  ok(textVisible($input));
  $input.val('value');
  ok(textNotVisible($input));

});

test("updates the input value", function () {

  $input.val('value');
  ok(textNotVisible($input));
  $input.val('value2');
  ok(textNotVisible($input));

});

test("clears the input value", function () {

  $input.val('value');
  ok(textNotVisible($input));
  $input.val('');
  ok(textVisible($input));

});

test("updates the placeover text", function () {

  $input.placeover('text', 'new placeholder');
  strictEqual('new placeholder', getText($input).text(), "Text to be updated");

});

module("explicit invocation", {
  setup: function () {
    $input = $(simpleInput);
    $('#qunit-fixture').append($input);
    $input.placeover({ explicit: true });
  },
  teardown: function () {
    $input.remove();
    $input = null;
  }
});

test("appears on show", function () {
  $input.placeover('hide');
  ok(textNotVisible($input), "Text to be hidden");
  $input.placeover('show');
  ok(textVisible($input), "Text to be visible");
});

test("disappears on hide", function () {
  ok(textVisible($input), "Text to be visible");
  $input.placeover('hide');
  ok(textNotVisible($input), "Text to be hidden");
});

module("eventing", {
  setup: function () {
    $input = $('<input />');
    $('#qunit-fixture').append($input);
    $input.placeover({ explicit: true });
  },
  teardown: function() {
    $input.remove();
    $input = null;
  }
});

test("triggers show event before displaying text", function () {

  // Hide the placeover to start
  $input.placeover('hide');

  // Attach handler to show event
  $input.on('show.placeover', function () {
    ok(textNotVisible($input));
  });

  // Show placeover
  $input.placeover('show');

  ok(textVisible($input));

});

test("is not shown when prevented", function () {

  // Hide the placeover to start
  $input.placeover('hide');

  // Attach handler to event
  $input.on('show.placeover', function (e) {
    e.preventDefault();
  });

  // Show placeover
  $input.placeover('show');

  ok(textNotVisible($input), "Text to be prevented from showing");

});

test("is not hidden when prevented", function () {

  // Show the placeover to start
  $input.placeover('show');

  // Attache handler to event
  $input.on('hide.placeover', function (e) {
    e.preventDefault();
  });

  // Hide placeover
  $input.placeover('hide');

  ok(textVisible($input), "Text to still be visible");

});<|endoftext|>


<commit_before>const chai = require('chai');
const fullUrlUtils = require('../../../app/lib/fullUrlUtils');

const expect = chai.expect;

describe('fullUrlUtils', () => {
  function host() { return 'beta.nhs.uk'; }
  const mockReturnUrl = 'https://beta.nhs.uk/find-a-pharmacy/results?location=ls';

  describe('url', () => {
    const reqMock = { protocol: 'https', get: host, originalUrl: '/find-a-pharmacy/results?location=ls' };
    it('should return the current URL', () => {
      const url = fullUrlUtils(reqMock).url;

      expect(url).to.equal(mockReturnUrl);
    });
  });
});
<commit_msg>:construction_worker: tweak tests<commit_after>const chai = require('chai');
const fullUrlUtils = require('../../../app/lib/fullUrlUtils');

const expect = chai.expect;

describe('fullUrlUtils', () => {
  function host() { return 'beta.nhs.uk'; }
  const mockReturnUrl = 'https://beta.nhs.uk/find-a-pharmacy/results?location=ls';

  describe('url', () => {
    const reqMock = { protocol: 'https://', get: host, originalUrl: '/find-a-pharmacy/results?location=ls' };
    it('should return the current URL', () => {
      const url = fullUrlUtils(reqMock).url;

      expect(url).to.equal(mockReturnUrl);
    });
  });
});
<|endoftext|>