All files / server/spec/fixtures geojson.js

100% Statements 40/40
100% Branches 26/26
100% Functions 5/5
100% Lines 39/39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104          1x 1x                                 1x 41x                                     1x   246x 246x 246x 246x   246x 120x 110x 110x 110x 110x     236x             120x 1x 119x 1x 118x 1x     117x 113x   110x       235x 1x 234x 1x     465x 233x 1x     232x 232x 2x     230x 230x 2x     228x    
/**
 * Test utilities to generate GeoJSON data.
 *
 * @module server/spec/fixtures/geojson
 */
const _ = require('lodash');
const chance = require('chance').Chance();
 
/**
 * Generates a GeoJSON point with random coordinates.
 *
 *     const geoJsonFixtures = require('../spec/fixtures/geojson');
 *
 *     geoJsonFixtures.point();  // { type: 'Point', coordinates: [ -76, 48 ] }
 *     geoJsonFixtures.point({ coordinates });  // { type: 'Point', coordinates: [ -76, 48 ] }
 *
 * @param {object} [data={}] - Custom point data.
 * @param {object} [data.bbox] - A bounding box within which the generated point should be.
 * @param {number[]} data.bbox.southWest - A longitude/latitude pair indicating the south-west corner of the bounding box.
 * @param {number[]} data.bbox.northEast - A longitude/latitude pair indicating the north-east corner of the bounding box.
 * @param {number[]} [data.coordinates] - The point's coordinates (longitude & latitude).
 * @returns {object} A GeoJSON point.
 */
exports.point = function(data = {}) {
  return {
    type: 'Point',
    coordinates: data.coordinates ? ensureCoordinates(data.coordinates) : exports.coordinates(_.pick(data, 'bbox'))
  };
};
 
/**
 * Generates a random pair of coordinates (longitude & latitude).
 *
 *     const geoJsonFixtures = require('../spec/fixtures/geojson');
 *
 *     geoJsonFixtures.coordinates();  // [ -76, 48 ]
 *
 * @param {object} [data={}] - Custom coordinates data.
 * @param {object} [data.bbox] - A bounding box within which the generated coordinates should be.
 * @param {number[]} data.bbox.southWest - A longitude/latitude pair indicating the south-west corner of the bounding box.
 * @param {number[]} data.bbox.northEast - A longitude/latitude pair indicating the north-east corner of the bounding box.
 * @returns {number[]} A GeoJSON coordinates pair.
 */
exports.coordinates = function(data = {}) {
 
  let minLatitude = -90;
  let maxLatitude = 90;
  let minLongitude = -180;
  let maxLongitude = 180;
 
  if (data.bbox) {
    const bbox = ensureBbox(data.bbox);
    minLatitude = bbox.southWest[1];
    maxLatitude = bbox.northEast[1];
    minLongitude = bbox.southWest[0];
    maxLongitude = bbox.northEast[0];
  }
 
  return [
    chance.floating({ min: minLongitude, max: maxLongitude }),
    chance.floating({ min: minLatitude, max: maxLatitude })
  ];
};
 
function ensureBbox(bbox) {
  if (!_.isObject(bbox)) {
    throw new Error('Bounding box must be an object');
  } else if (!bbox.southWest) {
    throw new Error('Bounding box must have a "southWest" property');
  } else if (!bbox.northEast) {
    throw new Error('Bounding box must have a "northEast" property');
  }
 
  ensureCoordinates(bbox.southWest);
  ensureCoordinates(bbox.northEast);
 
  return bbox;
}
 
function ensureCoordinates(coordinates) {
  if (!_.isArray(coordinates)) {
    throw new Error(`Coordinates must be an array, got ${typeof(coordinates)}`);
  } else if (coordinates.length != 2) {
    throw new Error(`Coordinates must be an array with 2 elements, but it has length ${coordinates.length}`);
  }
 
  const nan = coordinates.find(value => !_.isFinite(value))
  if (nan !== undefined) {
    throw new Error(`Coordinates must contain only numbers, got ${typeof(nan)}`);
  }
 
  const longitude = coordinates[0];
  if (longitude < -180 || longitude > 180) {
    throw new Error(`Longitude must be between -180 and 180, got ${longitude}`);
  }
 
  const latitude = coordinates[1];
  if (latitude < -90 || latitude > 90) {
    throw new Error(`Latitude must be between -90 and 90, got ${latitude}`);
  }
 
  return coordinates;
}