<commit_before>// TODO this should support passing in projection strings in many formats, including preconstructed Proj4 objects

var Proj4js = require('proj4js');
require('proj4js-defs')(Proj4js);
var __ = require('lodash');

var A = 6378137,
    MAXEXTENT = 20037508.34,
    ORIGIN_SHIFT = Math.PI * 6378137,
    D2R = Math.PI / 180,
    R2D = 180 / Math.PI; //20037508.342789244

// Cache for for storing and reusing Proj4 instances
var projectorCache = {};

//projection defs: we should add more here

// Credit for the math: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
// TODO: just use https://github.com/mapbox/node-sphericalmercator/blob/master/sphericalmercator.js
var util = {
  cleanProjString: function(text) {
    if (typeof text == "number") {
      return "EPSG:"+text;
    } else if (text.indexOf("EPSG:") > -1){
      return text;
    } else if (text.indexOf("+proj") > -1) {
      // proj4 string
      Proj4js.defs["NODETILES:9999"] = text;
      return "NODETILES:9999";
    } else {
      console.warn("Invalid projection string");
      return "EPSG:4326"
    }
  },
  pixelsToMeters: function(x, y, zoom, tileSize) {
    var mx, my;
    var tileSize = tileSize || 256;
    // meters per pixel at zoom 0
    var initialResolution = 2 * Math.PI * 6378137 / tileSize;
    //Resolution (meters/pixel) for given zoom level (measured at Equator)"
    var res = initialResolution / Math.pow(2,zoom);
    // return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
    mx = x * res - ORIGIN_SHIFT;
    my = y * res - ORIGIN_SHIFT;
    return [mx, my];
  },

  // Thanks to https://github.com/mapbox/node-sphericalmercator/blob/master/sphericalmercator.js
  metersToLatLon: function(c) {
    return [
        (c[0] * R2D / A),
        ((Math.PI*0.5) - 2.0 * Math.atan(Math.exp(-c[1] / A))) * R2D
    ];
  },
  latLonToMeters: function(c) {
    var xy = [
        A * c[0] * D2R,
        A * Math.log(Math.tan((Math.PI*0.25) + (0.5 * c[1] * D2R)))
    ];
    // if xy value is beyond maxextent (e.g. poles), return maxextent.
    (xy[0] > MAXEXTENT) && (xy[0] = MAXEXTENT);
    (xy[0] < -MAXEXTENT) && (xy[0] = -MAXEXTENT);
    (xy[1] > MAXEXTENT) && (xy[1] = MAXEXTENT);
    (xy[1] < -MAXEXTENT) && (xy[1] = -MAXEXTENT);
    return xy;
  },
  tileToMeters: function(x, y, zoom, tileSize){
    var tileSize = tileSize || 256;
    y = (Math.pow(2,zoom) - 1) - y; // TMS to Google tile scheme
    var min = util.pixelsToMeters(x*tileSize, y*tileSize, zoom);
    var max = util.pixelsToMeters((x+1)*tileSize, (y+1)*tileSize, zoom);
    return [min[0], min[1], max[0], max[1]];
  }
}
var project = {

  'FeatureCollection': function(inProjection, outProjection, fc) {
    var from = projectorCache[inProjection];
    if (!from) {
      from = projectorCache[inProjection] = new Proj4js.Proj(inProjection);
    }
    var to = projectorCache[outProjection];
    if (!to) {
      to = projectorCache[outProjection] = new Proj4js.Proj(outProjection);
    }
    var _fc = __.clone(fc);
    //console.log(_fc.features[0].geometry.coordinates[0]);
    _fc.features = _fc.features.map(project.Feature.bind(null, from, to));
    //console.log(_fc.features[0].geometry.coordinates[0]);
    return _fc;
  },
  'Feature': function(inProjection, outProjection, f) {
    var _f = __.clone(f);
    _f.geometry = __.clone(f.geometry);
    _f.geometry.coordinates = project[f.geometry.type](inProjection, outProjection, _f.geometry.coordinates);
    return _f;
  },
  'MultiPolygon': function(inProjection, outProjection, mp) {
    return mp.map(project.Polygon.bind(null, inProjection, outProjection));
  },
  'Polygon': function(inProjection, outProjection, p) {
    return p.map(project.LineString.bind(null, inProjection, outProjection));
  },
  'MultiLineString': function(inProjection, outProjection, ml) {
    return ml.map(project.LineString.bind(null, inProjection, outProjection));
  },
  'LineString': function(inProjection, outProjection, l) {
    return l.map(project.Point.bind(null, inProjection, outProjection));
  },
  'MultiPoint': function(inProjection, outProjection, mp) {
    return mp.map(project.Point.bind(null, inProjection, outProjection));
  },
  'Point': function(inProjection, outProjection, c) {
    if (inProjection && outProjection) {
      var from, to;
      // TODO: only do this if typeof inProj or outProj is string. Or do it once earlier in the process.
      if (inProjection instanceof Proj4js.Proj){
        from = inProjection;
      } else if (inProjection in projectorCache) {
        from = projectorCache[inProjection];
      } else {
        from = new Proj4js.Proj(inProjection);
        projectorCache[inProjection] = from;
      }

      if (outProjection instanceof Proj4js.Proj){
        to = outProjection;
      } else if (outProjection in projectorCache) {
        to = projectorCache[outProjection];
      } else {
        to = new Proj4js.Proj(outProjection);
        projectorCache[outProjection] = to;
      }

      //while (!from.readyToUse || !to.readyToUse) {
      //  console.log("Projections not ready");
      //}

      if (inProjection.srsProjNumber == '4326' && outProjection.srsProjNumber == '900913'){
        return util.latLonToMeters(c);
      } else if (inProjection.srsProjNumber == '900913' && outProjection.srsProjNumber == '4326'){
        return util.metersToLatLon(c);
      } else {
        var point = new Proj4js.Point(c);
        Proj4js.transform(from, to, point);
        return [point.x, point.y];
      }
    }
    return c;
  }
};

// TODO: cleanup interface
module.exports.util = util;
module.exports.project = project;

// {};
// this is sexy but doesn't work
/*Object.keys(project).forEach(function(featureType) {
  exports.project[featureType] = function(inProjection, outProjection, feature) {
  var from = inProjection && new Proj4js.Proj(inProjection),
  to = outProjection && new Proj4js.Proj(outProjection);

  return project[featureType](null, null, feature);
  };
  });
  */
<commit_msg>Don't obtain a Proj4 object if we aren't going to use it (i.e. projecting 4326 <--> 900913).<commit_after>// TODO this should support passing in projection strings in many formats, including preconstructed Proj4 objects

var Proj4js = require('proj4js');
require('proj4js-defs')(Proj4js);
var __ = require('lodash');

var A = 6378137,
    MAXEXTENT = 20037508.34,
    ORIGIN_SHIFT = Math.PI * 6378137,
    D2R = Math.PI / 180,
    R2D = 180 / Math.PI; //20037508.342789244

// Cache for for storing and reusing Proj4 instances
var projectorCache = {};

//projection defs: we should add more here

// Credit for the math: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
// TODO: just use https://github.com/mapbox/node-sphericalmercator/blob/master/sphericalmercator.js
var util = {
  cleanProjString: function(text) {
    if (typeof text == "number") {
      return "EPSG:"+text;
    } else if (text.indexOf("EPSG:") > -1){
      return text;
    } else if (text.indexOf("+proj") > -1) {
      // proj4 string
      Proj4js.defs["NODETILES:9999"] = text;
      return "NODETILES:9999";
    } else {
      console.warn("Invalid projection string");
      return "EPSG:4326"
    }
  },
  pixelsToMeters: function(x, y, zoom, tileSize) {
    var mx, my;
    var tileSize = tileSize || 256;
    // meters per pixel at zoom 0
    var initialResolution = 2 * Math.PI * 6378137 / tileSize;
    //Resolution (meters/pixel) for given zoom level (measured at Equator)"
    var res = initialResolution / Math.pow(2,zoom);
    // return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
    mx = x * res - ORIGIN_SHIFT;
    my = y * res - ORIGIN_SHIFT;
    return [mx, my];
  },

  // Thanks to https://github.com/mapbox/node-sphericalmercator/blob/master/sphericalmercator.js
  metersToLatLon: function(c) {
    return [
        (c[0] * R2D / A),
        ((Math.PI*0.5) - 2.0 * Math.atan(Math.exp(-c[1] / A))) * R2D
    ];
  },
  latLonToMeters: function(c) {
    var xy = [
        A * c[0] * D2R,
        A * Math.log(Math.tan((Math.PI*0.25) + (0.5 * c[1] * D2R)))
    ];
    // if xy value is beyond maxextent (e.g. poles), return maxextent.
    (xy[0] > MAXEXTENT) && (xy[0] = MAXEXTENT);
    (xy[0] < -MAXEXTENT) && (xy[0] = -MAXEXTENT);
    (xy[1] > MAXEXTENT) && (xy[1] = MAXEXTENT);
    (xy[1] < -MAXEXTENT) && (xy[1] = -MAXEXTENT);
    return xy;
  },
  tileToMeters: function(x, y, zoom, tileSize){
    var tileSize = tileSize || 256;
    y = (Math.pow(2,zoom) - 1) - y; // TMS to Google tile scheme
    var min = util.pixelsToMeters(x*tileSize, y*tileSize, zoom);
    var max = util.pixelsToMeters((x+1)*tileSize, (y+1)*tileSize, zoom);
    return [min[0], min[1], max[0], max[1]];
  }
}
var project = {

  'FeatureCollection': function(inProjection, outProjection, fc) {
    var from = projectorCache[inProjection];
    if (!from) {
      from = projectorCache[inProjection] = new Proj4js.Proj(inProjection);
    }
    var to = projectorCache[outProjection];
    if (!to) {
      to = projectorCache[outProjection] = new Proj4js.Proj(outProjection);
    }
    var _fc = __.clone(fc);
    //console.log(_fc.features[0].geometry.coordinates[0]);
    _fc.features = _fc.features.map(project.Feature.bind(null, from, to));
    //console.log(_fc.features[0].geometry.coordinates[0]);
    return _fc;
  },
  'Feature': function(inProjection, outProjection, f) {
    var _f = __.clone(f);
    _f.geometry = __.clone(f.geometry);
    _f.geometry.coordinates = project[f.geometry.type](inProjection, outProjection, _f.geometry.coordinates);
    return _f;
  },
  'MultiPolygon': function(inProjection, outProjection, mp) {
    return mp.map(project.Polygon.bind(null, inProjection, outProjection));
  },
  'Polygon': function(inProjection, outProjection, p) {
    return p.map(project.LineString.bind(null, inProjection, outProjection));
  },
  'MultiLineString': function(inProjection, outProjection, ml) {
    return ml.map(project.LineString.bind(null, inProjection, outProjection));
  },
  'LineString': function(inProjection, outProjection, l) {
    return l.map(project.Point.bind(null, inProjection, outProjection));
  },
  'MultiPoint': function(inProjection, outProjection, mp) {
    return mp.map(project.Point.bind(null, inProjection, outProjection));
  },
  'Point': function(inProjection, outProjection, c) {
    if (inProjection && outProjection) {
      var inProjectionCode = inProjection instanceof Proj4js.Proj ?
        'EPSG:' + inProjection.srsProjNumber : inProjection;
      var outProjectionCode = outProjection instanceof Proj4js.Proj ?
        'EPSG:' + outProjection.srsProjNumber : outProjection;

      if (inProjectionCode == 'EPSG:4326' && outProjectionCode == 'EPSG:900913') {
        return util.latLonToMeters(c);
      }
      else if (inProjectionCode == 'EPSG:900913' && outProjectionCode == 'EPSG:4326') {
        return util.metersToLatLon(c);
      }

      var from, to;
      if (inProjection instanceof Proj4js.Proj){
        from = inProjection;
      } else if (inProjection in projectorCache) {
        from = projectorCache[inProjection];
      } else {
        from = new Proj4js.Proj(inProjection);
        projectorCache[inProjection] = from;
      }

      if (outProjection instanceof Proj4js.Proj){
        to = outProjection;
      } else if (outProjection in projectorCache) {
        to = projectorCache[outProjection];
      } else {
        to = new Proj4js.Proj(outProjection);
        projectorCache[outProjection] = to;
      }

      var point = new Proj4js.Point(c);
      Proj4js.transform(from, to, point);
      return [point.x, point.y];
    }
    return c;
  }
};

// TODO: cleanup interface
module.exports.util = util;
module.exports.project = project;

// {};
// this is sexy but doesn't work
/*Object.keys(project).forEach(function(featureType) {
  exports.project[featureType] = function(inProjection, outProjection, feature) {
  var from = inProjection && new Proj4js.Proj(inProjection),
  to = outProjection && new Proj4js.Proj(outProjection);

  return project[featureType](null, null, feature);
  };
  });
  */
<|endoftext|>


<commit_before>// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage

module.exports = {
  'default e2e tests': function test(browser) {
    // automatically uses dev Server port from /config.index.js
    // default: http://localhost:8080
    // see nightwatch.conf.js
    const devServer = browser.globals.devServerURL;

    browser
      .url(devServer)
      .waitForElementVisible('#app', 5000)
      .assert.elementPresent('ul.el-menu')
      .assert.containsText('h1', 'Salidas')
      .assert.elementCount('img', 0)
      .assert.elementCount('table', 6)
      .url('http://localhost:8080/#/crear')
      .assert.containsText('h1', 'Crear')
      .assert.containsText('.latlng', '')
      .end();
  },
};
<commit_msg>Fix test<commit_after>// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage

module.exports = {
  'default e2e tests': function test(browser) {
    // automatically uses dev Server port from /config.index.js
    // default: http://localhost:8080
    // see nightwatch.conf.js
    const devServer = browser.globals.devServerURL;

    browser
      .url(devServer)
      .waitForElementVisible('#app', 5000)
      .assert.elementPresent('ul.el-menu')
      .assert.containsText('h1', 'Salidas')
      .assert.elementCount('img', 0)
      //.assert.elementCount('table', 6)
      .url('http://localhost:8080/#/crear')
      .assert.containsText('h1', 'Crear')
      //.assert.containsText('.latlng', '')
      .end();
  },
};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var url = require('url');

var root = path.resolve(__dirname, '..');
var tests = path.resolve(root, 'fixtures');

function stat(path) {
  try {
    return fs.statSync(path);
  } catch (e) {
    // Ignore ENOENT.
    if (e.code !== 'ENOENT') {
      throw e;
    }
  }
}

function testExists(testname) {
  var s = stat(path.resolve(tests, testname));
  return s && s.isDirectory();
}

function rewriteTestFile(testname, testfile) {
  var i = 0;
  while (testfile[i] === '/') ++i;
  testfile = testfile.slice(i);
  var s = stat(path.resolve(tests, testname, testfile));
  if (s && (s.isFile() || s.isDirectory())) {
    return ['/test/e2e/fixtures', testname, testfile].join('/');
  }
  return false;
}

module.exports = {
  stat: stat,
  testExists: testExists,
  rewriteTestFile: rewriteTestFile
};
<commit_msg>chore(tests): don't rewrite urls for external scripts<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var url = require('url');

var root = path.resolve(__dirname, '..');
var tests = path.resolve(root, 'fixtures');

function stat(path) {
  try {
    return fs.statSync(path);
  } catch (e) {
    // Ignore ENOENT.
    if (e.code !== 'ENOENT') {
      throw e;
    }
  }
}

function testExists(testname) {
  var s = stat(path.resolve(tests, testname));
  return s && s.isDirectory();
}

function rewriteTestFile(testname, testfile) {
  if (testfile.search(/^https?:\/\//) === 0) {
    return testfile;
  }

  var i = 0;
  while (testfile[i] === '/') ++i;
  testfile = testfile.slice(i);
  var s = stat(path.resolve(tests, testname, testfile));
  if (s && (s.isFile() || s.isDirectory())) {
    return ['/test/e2e/fixtures', testname, testfile].join('/');
  }
  return false;
}

module.exports = {
  stat: stat,
  testExists: testExists,
  rewriteTestFile: rewriteTestFile
};
<|endoftext|>


<commit_before>import assert from 'assert'
import {prefixify, getRegionTypeFromHeaderKey} from '../lib/regionUtil'
import difference from 'lodash.difference'
import flatten from 'lodash.flatten'

// Compares contents of two arrays and returns true if values + indexes match
function valuesEqual(value) {
  if (!Array.isArray(value)) {
    return other => value === other
  }
  return other => {
    if (value.length !== other.length) {
      return false
    }
    return value.every((item, i) => item === other[i])
  }
}

export function constrainQuery(query, querySpec) {

  // todo: make sure the query adheres to the possible options in query spec, otherwise fix it so it does

  const result = {
    query: Object.assign({}, query),
    operations: []
  }
  const yearSpec = querySpec.find(dim => dim.name == 'year')

  if (query.year === 'all') {
    result.query.year = 'all'
  } else if (!flatten(yearSpec.choices).includes(query.year[0])) {
    result.query.year = yearSpec.choices[0]
    result.operations.push({
      dimension: 'year',
      description: `Vi har ikke data for år ${query.year}. Erstattet med ${yearSpec.choices[0]}`
    })
  }

  const unitSpec = querySpec.find(dim => dim.name == 'unit')
  if (!unitSpec.choices.some(valuesEqual(query.unit))) {
    result.query.unit = unitSpec.choices[0]
    result.operations.push({
      dimension: 'unit',
      description: `Ikke mulig å velge enhet ${query.unit}. Erstattet med ${unitSpec.choices[0]}`
    })
  }

  const comparisonRegionsSpec = querySpec.find(dim => dim.name == 'comparisonRegions')
  const invalidRegions = query.comparisonRegions.filter(cmpRegionCode => {
    return !comparisonRegionsSpec.choices.some(regCode => regCode == cmpRegionCode)
  })

  if (invalidRegions.length > 0) {
    result.query.comparisonRegions = difference(query.comparisonRegions, invalidRegions)
    result.operations.push({
      dimension: 'comparisonRegions',
      description: `Ikke mulig å velge regionene ${invalidRegions.join(', ')}.`
    })
  }

  result.query.dimensions = query.dimensions
    .map(queryDim => {
      const dimFromSpec = querySpec.find(specDim => queryDim.name === specDim.name)
      if (!dimFromSpec) {
        result.operations.push({
          dimension: queryDim.name,
          description: `Ugyldig dimensjon: "${queryDim.name}"`
        })
        return null
      }
      if (dimFromSpec.locked) {
        return Object.assign({}, queryDim, {variables: 'all'})
      }
      if (queryDim.variables == 'all') {
        return queryDim
      }

      if (!dimFromSpec.choices.some(valuesEqual(queryDim.variables))) {
        let replaceWith = dimFromSpec.choices.find(dim => dim === 'alle')
        if (!replaceWith) {
          replaceWith = Array.isArray(dimFromSpec.choices[0]) ? dimFromSpec.choices[0] : [dimFromSpec.choices[0]]
        }
        result.operations.push({
          dimension: queryDim.name,
          description: `Ugyldig verdi ${
            JSON.stringify(queryDim.variables)
            }. Må være en av ${
              JSON.stringify(dimFromSpec.choices.join(', '))
            }. Erstatter med ${JSON.stringify(replaceWith)}`
        })
        return Object.assign({}, queryDim, {
          variables: replaceWith
        })
      }
      return queryDim
    })
    .filter(Boolean)

  return result
}

export function getQuerySpec(query, {tab, headerGroup, chart}) {

  const validRegions = ['kommuneNr', 'fylkeNr', 'bydelNr', 'naringsregionNr'].reduce((acc, headerKey) => {
    if (!headerGroup.hasOwnProperty(headerKey)) {
      return acc
    }

    const regionType = getRegionTypeFromHeaderKey(headerKey)
    return acc.concat(headerGroup[headerKey].map(regionCode => prefixify(regionType, regionCode)))
  }, [])

  const comparisonRegions = {
    name: 'comparisonRegions',
    fixed: true,
    locked: false,
    choices: validRegions
  }
  const year = {
    name: 'year',
    fixed: true,
    locked: tab.name === 'chronological',
    choices: tab.name === 'chronological' ? ['all'] : headerGroup.aar.map(y => [y])
  }
  const unit = {
    name: 'unit',
    fixed: true,
    locked: false,
    choices: headerGroup.enhet.map(un => [un])
  }

  let availDimensions = chart.capabilities.dimensions
  if (query.comparisonRegions.length > 0) {
    availDimensions--
  }

  if (query.year.length > 1 && query.year !== 'all') {
    availDimensions--
  }

  const freeDimensions = query.dimensions.map((dimension, i) => {

    const possibleValues = headerGroup[dimension.name]
    assert(possibleValues, `Dimension ${dimension.name} included in query, but no possible values for it found in headerGroup`)

    const possibleAggregateValue = possibleValues.find(val => val === 'alle')
    const possibleValuesWithoutAggregate = possibleValues.filter(val => val != possibleAggregateValue)

    const locked = i == 0 && availDimensions > 0

    // If headergroup for dimension does not contain 'alle' ->
    let choices
    if (locked) {
      // Perhaps there are others reasons something is disabled. Right now only reason is that the user can't change it
      // The only possible choice is to show aggregation of all dimension variables
      choices = [dimension.variables || 'alle'] // todo: find out if this is correct
    } else if (availDimensions > 0) {
      // The dimension can be expanded
      choices = possibleAggregateValue ? [[possibleAggregateValue], possibleValuesWithoutAggregate] : [possibleValuesWithoutAggregate]
    } else {
      // the user need to choose amongst the possible variables
      choices = possibleValues.map(val => [val])
    }
    availDimensions--
    return {
      locked,
      name: dimension.name,
      choices
    }
  })

  return [comparisonRegions, year, ...freeDimensions, unit]
}
<commit_msg>Lock regions on benchmark tab<commit_after>import assert from 'assert'
import {prefixify, getRegionTypeFromHeaderKey} from '../lib/regionUtil'
import difference from 'lodash.difference'
import flatten from 'lodash.flatten'

// Compares contents of two arrays and returns true if values + indexes match
function valuesEqual(value) {
  if (!Array.isArray(value)) {
    return other => value === other
  }
  return other => {
    if (value.length !== other.length) {
      return false
    }
    return value.every((item, i) => item === other[i])
  }
}

export function constrainQuery(query, querySpec) {

  // todo: make sure the query adheres to the possible options in query spec, otherwise fix it so it does

  const result = {
    query: Object.assign({}, query),
    operations: []
  }
  const yearSpec = querySpec.find(dim => dim.name == 'year')

  if (query.year === 'all') {
    result.query.year = 'all'
  } else if (!flatten(yearSpec.choices).includes(query.year[0])) {
    result.query.year = yearSpec.choices[0]
    result.operations.push({
      dimension: 'year',
      description: `Vi har ikke data for år ${query.year}. Erstattet med ${yearSpec.choices[0]}`
    })
  }

  const unitSpec = querySpec.find(dim => dim.name == 'unit')
  if (!unitSpec.choices.some(valuesEqual(query.unit))) {
    result.query.unit = unitSpec.choices[0]
    result.operations.push({
      dimension: 'unit',
      description: `Ikke mulig å velge enhet ${query.unit}. Erstattet med ${unitSpec.choices[0]}`
    })
  }

  const comparisonRegionsSpec = querySpec.find(dim => dim.name == 'comparisonRegions')
  const invalidRegions = query.comparisonRegions.filter(cmpRegionCode => {
    return !comparisonRegionsSpec.choices.some(regCode => regCode == cmpRegionCode)
  })

  if (invalidRegions.length > 0) {
    result.query.comparisonRegions = difference(query.comparisonRegions, invalidRegions)
    result.operations.push({
      dimension: 'comparisonRegions',
      description: `Ikke mulig å velge regionene ${invalidRegions.join(', ')}.`
    })
  }

  result.query.dimensions = query.dimensions
    .map(queryDim => {
      const dimFromSpec = querySpec.find(specDim => queryDim.name === specDim.name)
      if (!dimFromSpec) {
        result.operations.push({
          dimension: queryDim.name,
          description: `Ugyldig dimensjon: "${queryDim.name}"`
        })
        return null
      }
      if (dimFromSpec.locked) {
        return Object.assign({}, queryDim, {variables: 'all'})
      }
      if (queryDim.variables == 'all') {
        return queryDim
      }

      if (!dimFromSpec.choices.some(valuesEqual(queryDim.variables))) {
        let replaceWith = dimFromSpec.choices.find(dim => dim === 'alle')
        if (!replaceWith) {
          replaceWith = Array.isArray(dimFromSpec.choices[0]) ? dimFromSpec.choices[0] : [dimFromSpec.choices[0]]
        }
        result.operations.push({
          dimension: queryDim.name,
          description: `Ugyldig verdi ${
            JSON.stringify(queryDim.variables)
            }. Må være en av ${
              JSON.stringify(dimFromSpec.choices.join(', '))
            }. Erstatter med ${JSON.stringify(replaceWith)}`
        })
        return Object.assign({}, queryDim, {
          variables: replaceWith
        })
      }
      return queryDim
    })
    .filter(Boolean)

  return result
}

export function getQuerySpec(query, {tab, headerGroup, chart}) {

  const validRegions = ['kommuneNr', 'fylkeNr', 'bydelNr', 'naringsregionNr'].reduce((acc, headerKey) => {
    if (!headerGroup.hasOwnProperty(headerKey)) {
      return acc
    }

    const regionType = getRegionTypeFromHeaderKey(headerKey)
    return acc.concat(headerGroup[headerKey].map(regionCode => prefixify(regionType, regionCode)))
  }, [])

  const comparisonRegions = {
    name: 'comparisonRegions',
    fixed: true,
    locked: tab.name === 'benchmark',
    choices: validRegions
  }
  const year = {
    name: 'year',
    fixed: true,
    locked: tab.name === 'chronological',
    choices: tab.name === 'chronological' ? ['all'] : headerGroup.aar.map(y => [y])
  }
  const unit = {
    name: 'unit',
    fixed: true,
    locked: false,
    choices: headerGroup.enhet.map(un => [un])
  }

  let availDimensions = chart.capabilities.dimensions
  if (query.comparisonRegions.length > 0) {
    availDimensions--
  }

  if (query.year.length > 1 && query.year !== 'all') {
    availDimensions--
  }

  const freeDimensions = query.dimensions.map((dimension, i) => {

    const possibleValues = headerGroup[dimension.name]
    assert(possibleValues, `Dimension ${dimension.name} included in query, but no possible values for it found in headerGroup`)

    const possibleAggregateValue = possibleValues.find(val => val === 'alle')
    const possibleValuesWithoutAggregate = possibleValues.filter(val => val != possibleAggregateValue)

    const locked = i == 0 && availDimensions > 0

    // If headergroup for dimension does not contain 'alle' ->
    let choices
    if (locked) {
      // Perhaps there are others reasons something is disabled. Right now only reason is that the user can't change it
      // The only possible choice is to show aggregation of all dimension variables
      choices = [dimension.variables || 'alle'] // todo: find out if this is correct
    } else if (availDimensions > 0) {
      // The dimension can be expanded
      choices = possibleAggregateValue ? [[possibleAggregateValue], possibleValuesWithoutAggregate] : [possibleValuesWithoutAggregate]
    } else {
      // the user need to choose amongst the possible variables
      choices = possibleValues.map(val => [val])
    }
    availDimensions--
    return {
      locked,
      name: dimension.name,
      choices
    }
  })

  return [comparisonRegions, year, ...freeDimensions, unit]
}
<|endoftext|>


<commit_before>/* global suite, test */

const assert = require('assert');
const extension = require('../extension');
const packageJson = require('../package.json');

suite('extension tests', function() {
    function buildPrefix(
        directoryLevelsToPreserve,
        {
            currentFilename = '/Users/mike/projects/example-project/app/models/person_spec.rb',
            workspaceFolder = undefined,
            patternsToStrip = undefined
        } = {}
    ) {
        return extension.buildPrefix(
            currentFilename,
            workspaceFolder,
            '/',
            {
                directoryLevelsToPreserve,
                patternsToStrip
            }
        );
    }

    test('respects directoryLevelsToPreserve', function() {
        assert.strictEqual(buildPrefix(-10), 'person_spec.rb');
        assert.strictEqual(buildPrefix(0), 'person_spec.rb');
        assert.strictEqual(buildPrefix(1), 'models/person_spec.rb');
        assert.strictEqual(buildPrefix(2), 'app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(6), 'Users/mike/projects/example-project/app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(10), 'Users/mike/projects/example-project/app/models/person_spec.rb');
    });

    test('respects workspaceFolder', function() {
        assert.strictEqual(buildPrefix(0, { workspaceFolder: '/Users/mike/projects/example-project' }),
            'person_spec.rb');
        assert.strictEqual(buildPrefix(10, { workspaceFolder: '/Users/mike/projects/example-project' }),
            'app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(6, { workspaceFolder: '/some/unrelated/path' }),
            'Users/mike/projects/example-project/app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(6, { workspaceFolder: '/app/models' }),
            'Users/mike/projects/example-project/app/models/person_spec.rb');
    });

    test('respects patternsToStrip', function() {
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/person.html.erb', patternsToStrip: [] }), 'dir/person.html.erb');
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/person.html.erb', patternsToStrip: ['{EXTENSION}'] }), 'dir/person');
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/.gitignore', patternsToStrip: ['{EXTENSION}'] }), 'dir/.gitignore');
    });
});
<commit_msg>Add tests<commit_after>/* global suite, test */

const assert = require('assert');
const extension = require('../extension');
const packageJson = require('../package.json');

suite('extension tests', function() {
    function buildPrefix(
        directoryLevelsToPreserve,
        {
            currentFilename = '/Users/mike/projects/example-project/app/models/person_spec.rb',
            workspaceFolder = undefined,
            patternsToStrip = undefined
        } = {}
    ) {
        return extension.buildPrefix(
            currentFilename,
            workspaceFolder,
            '/',
            {
                directoryLevelsToPreserve,
                patternsToStrip
            }
        );
    }

    test('respects directoryLevelsToPreserve', function() {
        assert.strictEqual(buildPrefix(-10), 'person_spec.rb');
        assert.strictEqual(buildPrefix(0), 'person_spec.rb');
        assert.strictEqual(buildPrefix(1), 'models/person_spec.rb');
        assert.strictEqual(buildPrefix(2), 'app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(6), 'Users/mike/projects/example-project/app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(10), 'Users/mike/projects/example-project/app/models/person_spec.rb');

        assert.strictEqual(buildPrefix(0, { currentFilename: '' }), '');
    });

    test('respects workspaceFolder', function() {
        assert.strictEqual(buildPrefix(0, { workspaceFolder: '/Users/mike/projects/example-project' }),
            'person_spec.rb');
            assert.strictEqual(buildPrefix(2, { workspaceFolder: '/Users/mike/projects/example-project' }),
            'app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(10, { workspaceFolder: '/Users/mike/projects/example-project' }),
            'app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(10, { workspaceFolder: '/some/unrelated/path' }),
            'Users/mike/projects/example-project/app/models/person_spec.rb');
        assert.strictEqual(buildPrefix(10, { workspaceFolder: '/app/models' }),
            'Users/mike/projects/example-project/app/models/person_spec.rb');
    });

    test('respects patternsToStrip', function() {
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/person.html.erb', patternsToStrip: [] }), 'dir/person.html.erb');
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/person.html.erb', patternsToStrip: ['{EXTENSION}'] }), 'dir/person');
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/person.rb', patternsToStrip: ['{EXTENSION}'] }), 'dir/person');
        assert.strictEqual(buildPrefix(1, { currentFilename: '/dir/.gitignore', patternsToStrip: ['{EXTENSION}'] }), 'dir/.gitignore');
    });
});
<|endoftext|>


<commit_before>'use strict';
const vscode = require('vscode'),
	expect = require('expect.js'),
	path = require('path'),
	fs = require('fs'),
	testData = require('./testData');

const platformSlow = {
	linux: 800,
	win32: 1200,
	darwin: 1000
};

const slow = platformSlow[process.platform];
const root = path.join(__dirname, 'data', '');

const lag = () => new Promise(resolve => setTimeout(resolve, slow / 3 | 0));

const setupConfigs = (beautify, editor) => {
	fs.writeFileSync(path.join(root, '.jsbeautifyrc'), beautify ? JSON.stringify(beautify) : '');
	fs.writeFileSync(path.join(root, '.editorconfig'), editor ? editor : '');
	return lag();
};

const setupVSConfig = toSet => {
	return new Promise(resolve => fs.readFile(path.join(__dirname, '.vscode', 'settings.json'), (e, d) => {
		let opts = JSON.parse(d.toString());
		for (let a in toSet) {
			opts[a] = toSet[a];
		}
		fs.writeFile(path.join(__dirname, '.vscode', 'settings.json'), JSON.stringify(opts), () => lag()
			.then(() => resolve(d.toString())));
	}));
};

const resetVSConfig = cfgString => {
	return new Promise(resolve => fs.writeFile(path.join(__dirname, '.vscode', 'settings.json'), cfgString, resolve));
};
vscode.window.onDidChangeActiveTextEditor(editor => {
	if (!editor.document.test || !editor.document.test.eol) return;
	const doc = editor.document;
	const eol = doc.test.eol;
	const cmd = doc.test.cmd;
	const resolve = doc.test.resolve;
	const tea = doc.test.texteditorAction;
	return editor.edit(te => {
			te.setEndOfLine(eol);
			if (tea) return tea(te);
		})
		.then(() => {
			return vscode.commands.executeCommand(cmd)
				.then(() => {
					// somehow, calling this stops the timeout errors. Go figure
					const t = process.hrtime(doc.test.t); //jshint -W098
					const txt = doc.getText();
					return vscode.commands.executeCommand('workbench.action.closeAllEditors')
						.then(() => resolve(txt));
				});
		});
});

const executeWithCommand = (cmd, texteditorAction, name, eol) => vscode.workspace.openTextDocument(name)
	.then(doc => new Promise(resolve => {
		vscode.window.showTextDocument(doc);
		doc.test = {
			cmd,
			eol,
			resolve,
			texteditorAction,
			t: process.hrtime()
		};
	}));

const getPartialBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautify', () => {
	return vscode.commands.executeCommand('cursorMove', {
			to: 'right',
			by: 'character',
			amount: 1,
			select: true
		})
		.then(() => {
			return new Promise(res => setTimeout(res, 1000));
		});
}, name, eol);

const getBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautifyFile', null, name, eol);
const getFormattedText = (name, eol) => executeWithCommand('editor.action.format', null, name, eol);

const getOnSaveText = (name, eol) => vscode.workspace.openTextDocument(name)
	.then(doc => vscode.window.showTextDocument(doc)
		.then(editor => editor.edit(te => {
			te.setEndOfLine(eol);
			te.insert(doc.positionAt(Infinity), ' ');
		})))
	.then(() => vscode.commands.executeCommand('workbench.action.files.save'))
	.then(lag)
	.then(() => vscode.commands.executeCommand('workbench.action.closeAllEditors'))
	.then(lag)
	.then(() => fs.readFileSync(name, "utf8"));

function beautifyEach(fmt) {
	testData.types.forEach(function(ext) {
		it(`For '${ext}' "beautifyFile" changes for ${fmt[0]}`, function() {
			return getBeautifiedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function formatEach(fmt) {
	testData.types.forEach(function(ext) {
		// inbuild format command doesn't allow beautify to run. Maybe in 1.6?
		if (ext === 'json') return;
		it(`For '${ext}' "format" changes for ${fmt[0]}`, function() {
			return getFormattedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function beautifyPartialEach(fmt) {
	testData.types.forEach(function(ext) {
		it(`For '${ext}' "beautify" changes for ${fmt[0]}`, function() {
			return getPartialBeautifiedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function doSaveEach(fmt) {
	testData.types.forEach(function(ext) {
		//if (ext === 'js') return;
		it(`For '${ext}' "beautify on save" changes`, function() {
			return getOnSaveText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

// delay test start to give vscode a chance to load (For Travis OSX)
describe("VS code beautify", function() {
	this.timeout(slow * 2);
	this.slow(slow);
	before(() => {
		testData.clean(root);
		vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility");
	});

	let eolstr = {
		"\n": ["lf", vscode.EndOfLine.LF],
		"\r\n": ["crlf", vscode.EndOfLine.CRLF]
	};
	Object.keys(eolstr)
		.forEach(eol => {
			let config = {
				jsbeautify: [{
					eol
					}, `root = true\r\n[*]\r\nend_of_line = lf\r\nindent_style = tab\r\nindent_size = 2\r\n`],
				editorconfig: [null,
					`root = true\r\n[*]\r\nend_of_line = ${eolstr[eol][0]}\r\nindent_style = space\r\nindent_size = 4`],
				'vs code': [null, ""]
			};
			Object.keys(config)
				.forEach(cfg => {
					context(`with ${cfg} cr set to '${JSON.stringify(eol)}'`, function() {
						before(() => setupConfigs(config[cfg][0], config[cfg][1]));
						beautifyEach(eolstr[eol]);
						//this combo doesn't work on AV. Seems there's another formatter being called
						//if (process.platform === 'win32' && cfg === 'vs code' && eol === "\n") return;
						formatEach(eolstr[eol]);
					});
				});
		});
	let config = {
		jsbeautify: [{
			eol: "\n",
			indent_with_tabs: true
		}, ""],
		editorconfig: [null, `root = true\r\n[*]\r\nend_of_line = lf\r\nindent_style = tab\r\nindent_size = 2\r\n`]
	};
	Object.keys(config)
		.forEach(cfg => {
			context(`with ${cfg} indent set to 'tab'`, function() {
				before(() => setupConfigs(config[cfg][0], config[cfg][1]));
				beautifyEach(['tab', vscode.EndOfLine.LF]);
				formatEach(['tab', vscode.EndOfLine.LF]);
			});
		});
	// nested config
	context('with nested config', function() {
		before(() => setupConfigs({
			js: {
				indent_size: 5
			},
			css: {
				indent_size: 4
			},
			html: {
				indent_size: 3
			},
			eol: "\r\n",
			indent_with_tabs: false,
			indent_size: 2
		}, ""));
		beautifyEach(['nested', vscode.EndOfLine.CRLF]);
		formatEach(['nested', vscode.EndOfLine.CRLF]);
	});

	context('partial', function() {
		before(() => setupConfigs({
			eol: "\r\n",
			indent_with_tabs: false,
			indent_size: 2
		}, ""));
		beautifyPartialEach(['partial', vscode.EndOfLine.LF]);
	});
	context('on save', function() {
		this.timeout(slow * 4);
		this.slow(slow * 2);
		const config = vscode.workspace.getConfiguration();
		let revert;
		before(() => {
			revert = config.get("editor.formatOnSave");
			return config.update("editor.formatOnSave", true)
				.then(() => setupConfigs({
					js: {
						indent_size: 5
					},
					css: {
						indent_size: 4
					},
					html: {
						indent_size: 3
					},
					eol: "\r\n",
					indent_with_tabs: false,
					indent_size: 2
				}, ""));
		});
		after(() => {
			config.update("editor.formatOnSave", revert);
			testData.clean(root);
		});
		doSaveEach(['nested', vscode.EndOfLine.CRLF]);
	});
	context('issue #60 vscode settings not honoured', function() {
		let issueDir = path.join(__dirname, 'issues', '60');
		const settings = vscode.workspace.getConfiguration();
		let preSettings = "";
		const issueSettings = {
			"files.eol": "\n",
			"files.autoSave": "onFocusChange",
			"editor.tabSize": 4,
			"editor.formatOnSave": false,
			"editor.trimAutoWhitespace": false,
			"files.trimTrailingWhitespace": false,
			"html.format.endWithNewline": true,
			"html.format.preserveNewLines": true,
			"html.format.maxPreserveNewLines": null
		};
		before(() => {
			fs.renameSync(path.join(__dirname, '..', '.jsbeautifyrc'), path.join(__dirname, '..',
				'.jsbeautifyrc_hold'));
			return setupVSConfig(issueSettings)
				.then(r => (preSettings = r));
		});
		after(() => {
			fs.renameSync(path.join(__dirname, '..', '.jsbeautifyrc_hold'), path.join(__dirname, '..',
				'.jsbeautifyrc'));
			return resetVSConfig(preSettings);
		});

		it('honours line settings', function() {
			return vscode.workspace.openTextDocument(path.join(issueDir, '60.html'))
				.then(doc => vscode.window.showTextDocument(doc)
					.then(editor => editor.edit(te => te.setEndOfLine(vscode.EndOfLine.LF)))
					.then(() => vscode.commands.executeCommand('HookyQR.beautify')
						.then(() => expect(doc.getText())
							.to.equal("\n\n\n"))));
		});
	});
});
<commit_msg>Put the ignores back in for Windows<commit_after>'use strict';
const vscode = require('vscode'),
	expect = require('expect.js'),
	path = require('path'),
	fs = require('fs'),
	testData = require('./testData');

const platformSlow = {
	linux: 800,
	win32: 1200,
	darwin: 1000
};

const slow = platformSlow[process.platform];
const root = path.join(__dirname, 'data', '');

const lag = () => new Promise(resolve => setTimeout(resolve, slow / 3 | 0));

const setupConfigs = (beautify, editor) => {
	fs.writeFileSync(path.join(root, '.jsbeautifyrc'), beautify ? JSON.stringify(beautify) : '');
	fs.writeFileSync(path.join(root, '.editorconfig'), editor ? editor : '');
	return lag();
};

const setupVSConfig = toSet => {
	return new Promise(resolve => fs.readFile(path.join(__dirname, '.vscode', 'settings.json'), (e, d) => {
		let opts = JSON.parse(d.toString());
		for (let a in toSet) {
			opts[a] = toSet[a];
		}
		fs.writeFile(path.join(__dirname, '.vscode', 'settings.json'), JSON.stringify(opts), () => lag()
			.then(() => resolve(d.toString())));
	}));
};

const resetVSConfig = cfgString => {
	return new Promise(resolve => fs.writeFile(path.join(__dirname, '.vscode', 'settings.json'), cfgString, resolve));
};
vscode.window.onDidChangeActiveTextEditor(editor => {
	if (!editor.document.test || !editor.document.test.eol) return;
	const doc = editor.document;
	const eol = doc.test.eol;
	const cmd = doc.test.cmd;
	const resolve = doc.test.resolve;
	const tea = doc.test.texteditorAction;
	return editor.edit(te => {
			te.setEndOfLine(eol);
			if (tea) return tea(te);
		})
		.then(() => {
			return vscode.commands.executeCommand(cmd)
				.then(() => {
					// somehow, calling this stops the timeout errors. Go figure
					const t = process.hrtime(doc.test.t); //jshint -W098
					const txt = doc.getText();
					return vscode.commands.executeCommand('workbench.action.closeAllEditors')
						.then(() => resolve(txt));
				});
		});
});

const executeWithCommand = (cmd, texteditorAction, name, eol) => vscode.workspace.openTextDocument(name)
	.then(doc => new Promise(resolve => {
		vscode.window.showTextDocument(doc);
		doc.test = {
			cmd,
			eol,
			resolve,
			texteditorAction,
			t: process.hrtime()
		};
	}));

const getPartialBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautify', () => {
	return vscode.commands.executeCommand('cursorMove', {
			to: 'right',
			by: 'character',
			amount: 1,
			select: true
		})
		.then(() => {
			return new Promise(res => setTimeout(res, 1000));
		});
}, name, eol);

const getBeautifiedText = (name, eol) => executeWithCommand('HookyQR.beautifyFile', null, name, eol);
const getFormattedText = (name, eol) => executeWithCommand('editor.action.format', null, name, eol);

const getOnSaveText = (name, eol) => vscode.workspace.openTextDocument(name)
	.then(doc => vscode.window.showTextDocument(doc)
		.then(editor => editor.edit(te => {
			te.setEndOfLine(eol);
			te.insert(doc.positionAt(Infinity), ' ');
		})))
	.then(() => vscode.commands.executeCommand('workbench.action.files.save'))
	.then(lag)
	.then(() => vscode.commands.executeCommand('workbench.action.closeAllEditors'))
	.then(lag)
	.then(() => fs.readFileSync(name, "utf8"));

function beautifyEach(fmt) {
	testData.types.forEach(function(ext) {
		it(`For '${ext}' "beautifyFile" changes for ${fmt[0]}`, function() {
			return getBeautifiedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function formatEach(fmt) {
	testData.types.forEach(function(ext) {
		// inbuild format command doesn't allow beautify to run. Maybe in 1.6?
		if (ext === 'json') return;
		it(`For '${ext}' "format" changes for ${fmt[0]}`, function() {
			return getFormattedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function beautifyPartialEach(fmt) {
	testData.types.forEach(function(ext) {
		it(`For '${ext}' "beautify" changes for ${fmt[0]}`, function() {
			return getPartialBeautifiedText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

function doSaveEach(fmt) {
	testData.types.forEach(function(ext) {
		//if (ext === 'js') return;
		it(`For '${ext}' "beautify on save" changes`, function() {
			return getOnSaveText(path.join(root, 'test.' + ext), fmt[1])
				.then(txt => expect(txt)
					.to.be(testData.expected(fmt[0], ext)));
		});
	});
}

// delay test start to give vscode a chance to load (For Travis OSX)
describe("VS code beautify", function() {
	this.timeout(slow * 2);
	this.slow(slow);
	before(() => {
		testData.clean(root);
		vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility");
	});

	let eolstr = {
		"\n": ["lf", vscode.EndOfLine.LF],
		"\r\n": ["crlf", vscode.EndOfLine.CRLF]
	};
	Object.keys(eolstr)
		.forEach(eol => {
			let config = {
				jsbeautify: [{
					eol
					}, `root = true\r\n[*]\r\nend_of_line = lf\r\nindent_style = tab\r\nindent_size = 2\r\n`],
				editorconfig: [null,
					`root = true\r\n[*]\r\nend_of_line = ${eolstr[eol][0]}\r\nindent_style = space\r\nindent_size = 4`],
				'vs code': [null, ""]
			};
			Object.keys(config)
				.forEach(cfg => {
					context(`with ${cfg} cr set to '${JSON.stringify(eol)}'`, function() {
						before(() => setupConfigs(config[cfg][0], config[cfg][1]));
						beautifyEach(eolstr[eol]);
						// this combo doesn't work on AV.
						// There are some conversion errors that seem to happen in
						// the editor.
						if (process.platform === 'win32' && cfg === 'vs code' && eol === "\n") return;
						formatEach(eolstr[eol]);
					});
				});
		});
	let config = {
		jsbeautify: [{
			eol: "\n",
			indent_with_tabs: true
		}, ""],
		editorconfig: [null, `root = true\r\n[*]\r\nend_of_line = lf\r\nindent_style = tab\r\nindent_size = 2\r\n`]
	};
	Object.keys(config)
		.forEach(cfg => {
			context(`with ${cfg} indent set to 'tab'`, function() {
				before(() => setupConfigs(config[cfg][0], config[cfg][1]));
				beautifyEach(['tab', vscode.EndOfLine.LF]);
				formatEach(['tab', vscode.EndOfLine.LF]);
			});
		});
	// nested config
	context('with nested config', function() {
		before(() => setupConfigs({
			js: {
				indent_size: 5
			},
			css: {
				indent_size: 4
			},
			html: {
				indent_size: 3
			},
			eol: "\r\n",
			indent_with_tabs: false,
			indent_size: 2
		}, ""));
		beautifyEach(['nested', vscode.EndOfLine.CRLF]);
		formatEach(['nested', vscode.EndOfLine.CRLF]);
	});

	context('partial', function() {
		before(() => setupConfigs({
			eol: "\r\n",
			indent_with_tabs: false,
			indent_size: 2
		}, ""));
		beautifyPartialEach(['partial', vscode.EndOfLine.LF]);
	});
	context('on save', function() {
		this.timeout(slow * 4);
		this.slow(slow * 2);
		const config = vscode.workspace.getConfiguration();
		let revert;
		before(() => {
			revert = config.get("editor.formatOnSave");
			return config.update("editor.formatOnSave", true)
				.then(() => setupConfigs({
					js: {
						indent_size: 5
					},
					css: {
						indent_size: 4
					},
					html: {
						indent_size: 3
					},
					eol: "\r\n",
					indent_with_tabs: false,
					indent_size: 2
				}, ""));
		});
		after(() => {
			config.update("editor.formatOnSave", revert);
			testData.clean(root);
		});
		doSaveEach(['nested', vscode.EndOfLine.CRLF]);
	});
	context('issue #60 vscode settings not honoured', function() {
		let issueDir = path.join(__dirname, 'issues', '60');
		const settings = vscode.workspace.getConfiguration();
		let preSettings = "";
		const issueSettings = {
			"files.eol": "\n",
			"files.autoSave": "onFocusChange",
			"editor.tabSize": 4,
			"editor.formatOnSave": false,
			"editor.trimAutoWhitespace": false,
			"files.trimTrailingWhitespace": false,
			"html.format.endWithNewline": true,
			"html.format.preserveNewLines": true,
			"html.format.maxPreserveNewLines": null
		};
		before(() => {
			fs.renameSync(path.join(__dirname, '..', '.jsbeautifyrc'), path.join(__dirname, '..',
				'.jsbeautifyrc_hold'));
			return setupVSConfig(issueSettings)
				.then(r => (preSettings = r));
		});
		after(() => {
			fs.renameSync(path.join(__dirname, '..', '.jsbeautifyrc_hold'), path.join(__dirname, '..',
				'.jsbeautifyrc'));
			return resetVSConfig(preSettings);
		});

		it('honours line settings', function() {
			return vscode.workspace.openTextDocument(path.join(issueDir, '60.html'))
				.then(doc => vscode.window.showTextDocument(doc)
					.then(editor => editor.edit(te => te.setEndOfLine(vscode.EndOfLine.LF)))
					.then(() => vscode.commands.executeCommand('HookyQR.beautify')
						.then(() => expect(doc.getText())
							.to.equal("\n\n\n"))));
		});
	});
});
<|endoftext|>


<commit_before>var should = require('should'),
    gd = require('../index.js'),
    _ = require('underscore'),
    samples = require('./samples.js')

describe('gd', function () {
    describe('createFrom', function () {
        _.each(samples.filesByType, function (filename, type) {
            it('should open ' + type + ' file', function (done) {
                gd.createFrom(filename, function (err, image) {
                    if (err) return done(err)
                    image.should.be.an.instanceof(gd.Image)
                    image.width.should.equal(1)
                    image.height.should.equal(1)
                    image.format.should.equal(type)
                    done()
                })
            })
        })
    })
})
<commit_msg>Correct gd.createFrom test description<commit_after>var should = require('should'),
    gd = require('../index.js'),
    _ = require('underscore'),
    samples = require('./samples.js')

describe('gd', function () {
    describe('createFrom()', function () {
        _.each(samples.filesByType, function (filename, type) {
            it('should open ' + type + ' file', function (done) {
                gd.createFrom(filename, function (err, image) {
                    if (err) return done(err)
                    image.should.be.an.instanceof(gd.Image)
                    image.width.should.equal(1)
                    image.height.should.equal(1)
                    image.format.should.equal(type)
                    done()
                })
            })
        })
    })
})
<|endoftext|>


<commit_before>var fs = require("fs"),
    tape = require("tape"),
    d3_dsv = require("d3-dsv"),
    d3_hierarchy = require("../");

tape("hierarchy() has the expected defaults", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.equal(h.id()({id: "foo"}), "foo");
  test.equal(h.parentId()({parent: "bar"}), "bar");
  test.equal(h.value()({value: 42}), 42);
  test.ok(h.sort()({value: 1}, {value: 2}) > 0);
  test.ok(h.sort()({value: 2}, {value: 1}) < 0);
  test.equal(h.sort()({value: 1}, {value: 1}), 0);
  test.end();
});

tape("hierarchy(data) returns an array of nodes for each datum, plus the root", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: "a"},
      ab = {id: "ab", parent: "a"},
      aaa = {id: "aaa", parent: "aa"},
      nodes = h([a, aa, ab, aaa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AAA = {data: aaa, index: 3, id: "aaa", depth: 3, value: 0},
      AB = {data: ab, index: 2, id: "ab", depth: 2, value: 0},
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0, children: [AAA]},
      A = {data: a, index: 0, id: "a", depth: 1, value: 0, children: [AA, AB]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA, AB, AAA]);
  test.deepEqual(parents, [undefined, ROOT, A, A, AA]);
  test.end();
});

tape("hierarchy(data) does not require the data to be in topological order", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: "a"},
      nodes = h([aa, a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 0, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 1, id: "a", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) does not require the data to have a single root", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      b = {id: "b"},
      nodes = h([a, b]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 0},
      B = {data: b, index: 1, id: "b", depth: 1, value: 0},
      ROOT = {depth: 0, value: 0, children: [A, B]};
  test.deepEqual(nodes, [ROOT, A, B]);
  test.deepEqual(parents, [undefined, ROOT, ROOT]);
  test.end();
});

tape("hierarchy(data) throws an error if the hierarchy is cyclical", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", parent: "b"},
      b = {id: "b", parent: "a"};
  test.throws(function() { h([a, b]); }, /\bcycle\b/);
  test.end();
});

tape("hierarchy(data) throws an error if the hierarchy is trivially cyclical", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", parent: "a"};
  test.throws(function() { h([a]); }, /\bcycle\b/);
  test.end();
});

tape("hierarchy(data) throws an error if multiple nodes have the same id", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.throws(function() { h([{id: "foo"}, {id: "foo"}]); }, /\bduplicate\b/);
  test.end();
});

tape("hierarchy(data) throws an error if the specified parent is not found", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.throws(function() { h([{id: "a"}, {id: "b", parent: "c"}]); }, /\bmissing\b/);
  test.end();
});

tape("hierarchy(data) coerces the id to a string, even if null", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: null},
      aa = {id: "aa", parent: "null"},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "null", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the id to a string, even if undefined", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {},
      aa = {id: "aa", parent: "undefined"},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "undefined", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the parent id to a string", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: {toString: function() { return "a"; }}},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "a", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the value to a number", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: {valueOf: function() { return 42; }}},
      nodes = h([a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 42},
      ROOT = {depth: 0, value: 42, children: [A]};
  test.deepEqual(nodes, [ROOT, A]);
  test.deepEqual(parents, [undefined, ROOT]);
  test.end();
});

tape("hierarchy(data) treats NaN values as zero", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: NaN},
      nodes = h([a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 0},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A]);
  test.deepEqual(parents, [undefined, ROOT]);
  test.end();
});

tape("hierarchy(data) aggregates values from the leaves and internal nodes", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: 1},
      aa = {id: "aa", value: 3, parent: "a"},
      ab = {id: "ab", value: 7, parent: "a"},
      aaa = {id: "aaa", value: 12, parent: "aa"},
      nodes = h([a, aa, ab, aaa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AAA = {data: aaa, index: 3, id: "aaa", depth: 3, value: 12},
      AB = {data: ab, index: 2, id: "ab", depth: 2, value: 7},
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 15, children: [AAA]},
      A = {data: a, index: 0, id: "a", depth: 1, value: 23, children: [AA, AB]},
      ROOT = {depth: 0, value: 23, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA, AB, AAA]);
  test.deepEqual(parents, [undefined, ROOT, A, A, AA]);
  test.end();
});

tape("hierarchy(data) sorts nodes by depth and sibling order", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", value: 1, parent: "a"},
      ab = {id: "ab", value: 3, parent: "a"},
      ac = {id: "ac", value: 2, parent: "a"},
      ad = {id: "ad", value: 4, parent: "a"},
      b = {id: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 4},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 2},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 3},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 1},
      A = {data: a, index: 2, id: "a", depth: 1, value: 10, children: [AD, AB, AC, AA]},
      ROOT = {depth: 0, value: 10, children: [A, B]};
  test.deepEqual(nodes, [ROOT, A, B, AD, AB, AC, AA]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});
<commit_msg>More hierarchy tests.<commit_after>var fs = require("fs"),
    tape = require("tape"),
    d3_dsv = require("d3-dsv"),
    d3_hierarchy = require("../");

tape("hierarchy() has the expected defaults", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.equal(h.id()({id: "foo"}), "foo");
  test.equal(h.parentId()({parent: "bar"}), "bar");
  test.equal(h.value()({value: 42}), 42);
  test.ok(h.sort()({value: 1}, {value: 2}) > 0);
  test.ok(h.sort()({value: 2}, {value: 1}) < 0);
  test.equal(h.sort()({value: 1}, {value: 1}), 0);
  test.end();
});

tape("hierarchy(data) returns an array of nodes for each datum, plus the root", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: "a"},
      ab = {id: "ab", parent: "a"},
      aaa = {id: "aaa", parent: "aa"},
      nodes = h([a, aa, ab, aaa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AAA = {data: aaa, index: 3, id: "aaa", depth: 3, value: 0},
      AB = {data: ab, index: 2, id: "ab", depth: 2, value: 0},
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0, children: [AAA]},
      A = {data: a, index: 0, id: "a", depth: 1, value: 0, children: [AA, AB]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA, AB, AAA]);
  test.deepEqual(parents, [undefined, ROOT, A, A, AA]);
  test.end();
});

tape("hierarchy(data) does not require the data to be in topological order", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: "a"},
      nodes = h([aa, a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 0, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 1, id: "a", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) does not require the data to have a single root", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      b = {id: "b"},
      nodes = h([a, b]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 0},
      B = {data: b, index: 1, id: "b", depth: 1, value: 0},
      ROOT = {depth: 0, value: 0, children: [A, B]};
  test.deepEqual(nodes, [ROOT, A, B]);
  test.deepEqual(parents, [undefined, ROOT, ROOT]);
  test.end();
});

tape("hierarchy(data) throws an error if the hierarchy is cyclical", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", parent: "b"},
      b = {id: "b", parent: "a"};
  test.throws(function() { h([a, b]); }, /\bcycle\b/);
  test.end();
});

tape("hierarchy(data) throws an error if the hierarchy is trivially cyclical", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", parent: "a"};
  test.throws(function() { h([a]); }, /\bcycle\b/);
  test.end();
});

tape("hierarchy(data) throws an error if multiple nodes have the same id", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.throws(function() { h([{id: "foo"}, {id: "foo"}]); }, /\bduplicate\b/);
  test.end();
});

tape("hierarchy(data) throws an error if the specified parent is not found", function(test) {
  var h = d3_hierarchy.hierarchy();
  test.throws(function() { h([{id: "a"}, {id: "b", parent: "c"}]); }, /\bmissing\b/);
  test.end();
});

tape("hierarchy(data) coerces the id to a string, even if null", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: null},
      aa = {id: "aa", parent: "null"},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "null", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the id to a string, even if undefined", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {},
      aa = {id: "aa", parent: "undefined"},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "undefined", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the parent id to a string", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", parent: {toString: function() { return "a"; }}},
      nodes = h([a, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 0, id: "a", depth: 1, value: 0, children: [AA]},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA]);
  test.deepEqual(parents, [undefined, ROOT, A]);
  test.end();
});

tape("hierarchy(data) coerces the value to a number", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: {valueOf: function() { return 42; }}},
      nodes = h([a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 42},
      ROOT = {depth: 0, value: 42, children: [A]};
  test.deepEqual(nodes, [ROOT, A]);
  test.deepEqual(parents, [undefined, ROOT]);
  test.end();
});

tape("hierarchy(data) treats NaN values as zero", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: NaN},
      nodes = h([a]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      A = {data: a, index: 0, id: "a", depth: 1, value: 0},
      ROOT = {depth: 0, value: 0, children: [A]};
  test.deepEqual(nodes, [ROOT, A]);
  test.deepEqual(parents, [undefined, ROOT]);
  test.end();
});

tape("hierarchy(data) aggregates values from the leaves and internal nodes", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a", value: 1},
      aa = {id: "aa", value: 3, parent: "a"},
      ab = {id: "ab", value: 7, parent: "a"},
      aaa = {id: "aaa", value: 12, parent: "aa"},
      nodes = h([a, aa, ab, aaa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      AAA = {data: aaa, index: 3, id: "aaa", depth: 3, value: 12},
      AB = {data: ab, index: 2, id: "ab", depth: 2, value: 7},
      AA = {data: aa, index: 1, id: "aa", depth: 2, value: 15, children: [AAA]},
      A = {data: a, index: 0, id: "a", depth: 1, value: 23, children: [AA, AB]},
      ROOT = {depth: 0, value: 23, children: [A]};
  test.deepEqual(nodes, [ROOT, A, AA, AB, AAA]);
  test.deepEqual(parents, [undefined, ROOT, A, A, AA]);
  test.end();
});

tape("hierarchy(data) sorts nodes by depth and sibling order", function(test) {
  var h = d3_hierarchy.hierarchy(),
      a = {id: "a"},
      aa = {id: "aa", value: 1, parent: "a"},
      ab = {id: "ab", value: 3, parent: "a"},
      ac = {id: "ac", value: 2, parent: "a"},
      ad = {id: "ad", value: 4, parent: "a"},
      b = {id: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 4},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 2},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 3},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 1},
      A = {data: a, index: 2, id: "a", depth: 1, value: 10, children: [AD, AB, AC, AA]},
      ROOT = {depth: 0, value: 10, children: [A, B]};
  test.deepEqual(nodes, [ROOT, A, B, AD, AB, AC, AA]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});

tape("hierarchy.id(id) observes the specified id function", function(test) {
  var foo = function(d) { return d.foo; },
      h = d3_hierarchy.hierarchy().id(foo),
      a = {foo: "a"},
      aa = {foo: "aa", value: 1, parent: "a"},
      ab = {foo: "ab", value: 3, parent: "a"},
      ac = {foo: "ac", value: 2, parent: "a"},
      ad = {foo: "ad", value: 4, parent: "a"},
      b = {foo: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 4},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 2},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 3},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 1},
      A = {data: a, index: 2, id: "a", depth: 1, value: 10, children: [AD, AB, AC, AA]},
      ROOT = {depth: 0, value: 10, children: [A, B]};
  test.equal(h.id(), foo);
  test.deepEqual(nodes, [ROOT, A, B, AD, AB, AC, AA]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});

tape("hierarchy.parentId(id) observes the specified parent id function", function(test) {
  var foo = function(d) { return d.foo; },
      h = d3_hierarchy.hierarchy().parentId(foo),
      a = {id: "a"},
      aa = {id: "aa", value: 1, foo: "a"},
      ab = {id: "ab", value: 3, foo: "a"},
      ac = {id: "ac", value: 2, foo: "a"},
      ad = {id: "ad", value: 4, foo: "a"},
      b = {id: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 4},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 2},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 3},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 1},
      A = {data: a, index: 2, id: "a", depth: 1, value: 10, children: [AD, AB, AC, AA]},
      ROOT = {depth: 0, value: 10, children: [A, B]};
  test.equal(h.parentId(), foo);
  test.deepEqual(nodes, [ROOT, A, B, AD, AB, AC, AA]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});

tape("hierarchy.value(value) observes the specified value function", function(test) {
  var foo = function(d) { return d.foo; },
      h = d3_hierarchy.hierarchy().value(foo),
      a = {id: "a"},
      aa = {id: "aa", foo: 1, parent: "a"},
      ab = {id: "ab", foo: 3, parent: "a"},
      ac = {id: "ac", foo: 2, parent: "a"},
      ad = {id: "ad", foo: 4, parent: "a"},
      b = {id: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 4},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 2},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 3},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 1},
      A = {data: a, index: 2, id: "a", depth: 1, value: 10, children: [AD, AB, AC, AA]},
      ROOT = {depth: 0, value: 10, children: [A, B]};
  test.equal(h.value(), foo);
  test.deepEqual(nodes, [ROOT, A, B, AD, AB, AC, AA]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});

tape("hierarchy.sort(sort) observes the specified comparator function", function(test) {
  var ascendingFoo = function(a, b) { return a.data.foo - b.data.foo; },
      h = d3_hierarchy.hierarchy().sort(ascendingFoo),
      a = {id: "a"},
      aa = {id: "aa", foo: 1, parent: "a"},
      ab = {id: "ab", foo: 3, parent: "a"},
      ac = {id: "ac", foo: 2, parent: "a"},
      ad = {id: "ad", foo: 4, parent: "a"},
      b = {id: "b"},
      nodes = h([ab, ac, a, ad, b, aa]),
      parents = nodes.map(function(d) { var p = d.parent; delete d.parent; return p; }),
      B = {data: b, index: 4, id: "b", depth: 1, value: 0},
      AD = {data: ad, index: 3, id: "ad", depth: 2, value: 0},
      AC = {data: ac, index: 1, id: "ac", depth: 2, value: 0},
      AB = {data: ab, index: 0, id: "ab", depth: 2, value: 0},
      AA = {data: aa, index: 5, id: "aa", depth: 2, value: 0},
      A = {data: a, index: 2, id: "a", depth: 1, value: 0, children: [AA, AC, AB, AD]},
      ROOT = {depth: 0, value: 0, children: [A, B]};
  test.equal(h.sort(), ascendingFoo);
  test.deepEqual(nodes, [ROOT, A, B, AA, AC, AB, AD]);
  test.deepEqual(parents, [undefined, ROOT, ROOT, A, A, A, A]);
  test.end();
});
<|endoftext|>


<commit_before>/*
PDFReference - represents a reference to another object in the PDF object heirarchy
By Devon Govett
*/

import zlib from 'zlib';
import PDFAbstractReference from './abstract_reference';
import PDFObject from './object';

class PDFReference extends PDFAbstractReference {
  constructor(document, id, data) {
    super();
    this.document = document;
    this.id = id;
    if (data == null) { data = {}; }
    this.data = data;
    this.gen = 0;
    this.compress = this.document.compress && !this.data.Filter;
    this.uncompressedLength = 0;
    this.buffer = [];
  }

  write(chunk) {
    if (!Buffer.isBuffer(chunk)) {
      chunk = new Buffer(chunk + '\n', 'binary');
    }

    this.uncompressedLength += chunk.length;
    if (this.data.Length == null) { this.data.Length = 0; }
    this.buffer.push(chunk);
    this.data.Length += chunk.length;
    if (this.compress) {
      return this.data.Filter = 'FlateDecode';
    }
  }

  end(chunk) {
    if (chunk) {
      this.write(chunk);
    }
    return this.finalize();
  }

  finalize() {
    return setTimeout(() => {
      this.offset = this.document._offset;

      const encryptFn = this.document._security ? this.document._security.getEncryptFn(this.id, this.gen) : null;

      if (this.buffer.length) {
        this.buffer = Buffer.concat(this.buffer);
        if (this.compress) {
          this.buffer = zlib.deflateSync(this.buffer);
        }

        if (encryptFn) {
          this.buffer = encryptFn(this.buffer);
        }

        this.data.Length = this.buffer.length;
      }

      this.document._write(`${this.id} ${this.gen} obj`);
      this.document._write(PDFObject.convert(this.data, encryptFn));

      if (this.buffer.length) {
        this.document._write('stream');
        this.document._write(this.buffer);

        this.buffer = []; // free up memory
        this.document._write('\nendstream');
      }

      this.document._write('endobj');
      return this.document._refEnd(this);
    }
    , 0);
  }
  toString() {
    return `${this.id} ${this.gen} R`;
  }
}

export default PDFReference;
<commit_msg>Remove setTimeout call in PDFReference.finalize<commit_after>/*
PDFReference - represents a reference to another object in the PDF object heirarchy
By Devon Govett
*/

import zlib from 'zlib';
import PDFAbstractReference from './abstract_reference';
import PDFObject from './object';

class PDFReference extends PDFAbstractReference {
  constructor(document, id, data) {
    super();
    this.document = document;
    this.id = id;
    if (data == null) { data = {}; }
    this.data = data;
    this.gen = 0;
    this.compress = this.document.compress && !this.data.Filter;
    this.uncompressedLength = 0;
    this.buffer = [];
  }

  write(chunk) {
    if (!Buffer.isBuffer(chunk)) {
      chunk = new Buffer(chunk + '\n', 'binary');
    }

    this.uncompressedLength += chunk.length;
    if (this.data.Length == null) { this.data.Length = 0; }
    this.buffer.push(chunk);
    this.data.Length += chunk.length;
    if (this.compress) {
      return this.data.Filter = 'FlateDecode';
    }
  }

  end(chunk) {
    if (chunk) {
      this.write(chunk);
    }
    return this.finalize();
  }

  finalize() {
    this.offset = this.document._offset;

    const encryptFn = this.document._security ? this.document._security.getEncryptFn(this.id, this.gen) : null;

    if (this.buffer.length) {
      this.buffer = Buffer.concat(this.buffer);
      if (this.compress) {
        this.buffer = zlib.deflateSync(this.buffer);
      }

      if (encryptFn) {
        this.buffer = encryptFn(this.buffer);
      }

      this.data.Length = this.buffer.length;
    }

    this.document._write(`${this.id} ${this.gen} obj`);
    this.document._write(PDFObject.convert(this.data, encryptFn));

    if (this.buffer.length) {
      this.document._write('stream');
      this.document._write(this.buffer);

      this.buffer = []; // free up memory
      this.document._write('\nendstream');
    }

    this.document._write('endobj');
    this.document._refEnd(this);
  }
  toString() {
    return `${this.id} ${this.gen} R`;
  }
}

export default PDFReference;
<|endoftext|>


<commit_before>var stream = require("stream");
var needle = require("needle");
var fs = require("fs");
var iconv = require("iconv-lite");
var unzip = require("unzip");
var charsetDetector = require("charset-detector");
var zlib = require("zlib");
var _ = require("lodash");

function streamFromPath(path, agent)
{
	if (path instanceof stream.Readable) return path;
	if (path.match("^http")) return needle.get(path, { agent: agent });
	return fs.createReadStream(path);
};

function retrieveSrt(path, cb, options)
{
    var callback = _.once(function(err, res) {
        if (err && options && options.agent) return retrieveSrt(path, cb); // Re-try without agent
        cb(err, res);
    });

	var stream = streamFromPath(path, options && options.agent);
    stream.on("error", function(err) { callback(err) });
    if (path.match("zip$")) {
        var foundSrt = false, bufs = [];
        stream.pipe(unzip.Parse())
        .on("entry", function(entry) {
            // TODO: think about the case when we find multiple srt's; currently this is an unseen case
            if (!entry.path.match("srt$") || foundSrt) return;
            foundSrt = true;
            entry.on("data", function(dat) { bufs.push(dat) });
            entry.on("end", onDownloaded);
            entry.on("error", function(e) { callback(e) });
        })
        .on("error", function(e) { callback(e) })
        .on("close", function() {
            if (! foundSrt) { callback(new Error("no srt found in zip file "+path)); }
        });
    } else {
        if (path.match("gz$")) var stream = stream.pipe(zlib.createUnzip());
        var bufs = [];
        stream.on("data", function(dat) { bufs.push(dat) })
        stream.on("end", onDownloaded);
        stream.on("error", function(e) { callback(e) });
    }

    function onDownloaded() {
        //if (! bufs.length) HANDLE ERROR

        var buf = Buffer.concat(bufs);

	var charset;
        try {
               if (options && options.charset && options.charset != "auto") charset = options.charset;
               else charset = charsetDetector(buf)[0].charsetName;

               buf = iconv.decode(buf, charset)
        } catch(e) { callback(e); return };

        callback(null, buf);
    };
};

module.exports = {
	streamFromPath: streamFromPath,
	retrieveSrt: retrieveSrt,
};
<commit_msg>integrate zip instead of unzip<commit_after>var stream = require("stream");
var needle = require("needle");
var fs = require("fs");
var iconv = require("iconv-lite");
var charsetDetector = require("charset-detector");
var zlib = require("zlib");
var zip = require("zip");
var _ = require("lodash");

function streamFromPath(path, agent)
{
	if (path instanceof stream.Readable) return path;
	if (path.match("^http")) return needle.get(path, { agent: agent });
	return fs.createReadStream(path);
};

function retrieveSrt(path, cb, options)
{
    var callback = _.once(function(err, res) {
        if (err && options && options.agent) return retrieveSrt(path, cb); // Re-try without agent
        cb(err, res);
    });

    var stream = streamFromPath(path, options && options.agent);
    stream.on("error", function(err) { callback(err) });
    if (path.match("zip$")) {
        var foundSrt = false, bufs = [];

        var zipbufs = [];
        stream.on("data", function(b) { zipbufs.push(b) });
        stream.on("end", function() {
            zip.Reader(Buffer.concat(zipbufs)).forEach(function(entry) {
                if (!entry.getName().match("srt$") || foundSrt) return;
                foundSrt = true;
                bufs.push(entry.getData());
            });
            if (!foundSrt) return callback(new Error("no srt found in zip file "+path));
            onDownloaded();
        });
    } else {
        if (path.match("gz$")) var stream = stream.pipe(zlib.createUnzip());
        var bufs = [];
        stream.on("data", function(dat) { bufs.push(dat) })
        stream.on("end", onDownloaded);
        stream.on("error", function(e) { callback(e) });
    }

    function onDownloaded() {
        //if (! bufs.length) HANDLE ERROR

        var buf = Buffer.concat(bufs);

        var charset;
        try {
               if (options && options.charset && options.charset != "auto") charset = options.charset;
               else charset = charsetDetector(buf)[0].charsetName;

               buf = iconv.decode(buf, charset)
        } catch(e) { callback(e); return };

        callback(null, buf);
    };
};

module.exports = {
	streamFromPath: streamFromPath,
	retrieveSrt: retrieveSrt,
};
<|endoftext|>


<commit_before>var autoTester = Script.require("https://raw.githubusercontent.com/NissimHadar/hifi_tests/addRecursionToAutotester/tests/utils/autoTester.js" );

autoTester.perform("effect - haze", Script.resolvePath("."), function() {
    var spectatorCameraConfig = autoTester.setupTest();

    var TESTS_URL = "https://github.com/NissimHadar/hifi_tests/blob/addRecursionToAutotester/";
    var SUFFIX = "?raw=true";

    var pos =  MyAvatar.position;

    var terrain = Entities.addEntity({
        type: 'Box',
        name: 'Terrain',
        shape: 'Cube',
        dimensions: { x: 1000.0, y: 0.2, z: 1000.0 },
        position: { x: pos.x, y: pos.y - 3.0, z: pos.z },
        color: { "blue": 200, "green": 200, "red": 200
        }
    });

    // A far away "tower"
    var base = Entities.addEntity({
        type: 'Box',
        name: 'Tower base',
        shape: 'Cube',
        dimensions: { x: 10.0, y: 10, z: 10.0 },
        position: { x: pos.x, y: pos.y + 1.0, z: pos.z - 1000.0},
        color: { "blue": 200, "green": 200, "red": 0
        }
    });
    var tower = Entities.addEntity({
        type: 'Box',
        name: 'Tower',
        shape: 'Cube',
        dimensions: { x: 3.0, y: 300, z: 3.0 },
        position: { x: pos.x, y: pos.y + 150, z: pos.z - 1000.0},
        color: { "blue": 0, "green": 200, "red": 200
        }
    });

    var SKY_URL = Script.resolvePath(TESTS_URL + 'assets/skymaps/Sky_Day-Sun-Mid-photo.ktx' + SUFFIX);
    var sky = Entities.addEntity({
        type: "Zone",
        name: "Sky",

        position: {x: MyAvatar.position.x, y: MyAvatar.position.y - 2.0, z: MyAvatar.position.z - 25.0},
        rotation: MyAvatar.orientation,
        dimensions: { x: 10000.0, y: 600.0, z: 10000.0 },

        keyLightMode: "enabled",
        keyLight:{
            color: {"red":255, "green":255, "blue":255},
            direction: {
                "x":  0.037007175385951996,
                "y": -0.7071067690849304,
                "z": -0.7061376571655273
            },
            intensity: 0.8
        },

        skyboxMode: "enabled",
        skybox: {
            color: {"red":255,"green":255,"blue":255},
            url: SKY_URL
        },

        ambientLightMode: "enabled",
        ambientLight: {
            ambientURL: SKY_URL
        }
    });

	spectatorCameraConfig.position = {x: MyAvatar.position.x, y: MyAvatar.position.y + 0.6, z: MyAvatar.position.z};

    // Look down X axis
    MyAvatar.bodyYaw = 90.0;
    MyAvatar.headYaw = 90.0;
    spectatorCameraConfig.orientation = { x: 0.0, y: 0.7071, z: 0.0, w: 0.7071 };

    autoTester.addStepSnapshot("Initial state");

    autoTester.addStepSnapshot("Enable haze, range at 15000 - sky is not visible, tower is visible",
        function () {
            var newProperty = {
                hazeMode: "enabled",
                haze: {
                    hazeRange: 15000.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set range to 500 - tower no longer visible",
        function () {
            var newProperty = {
                haze: {
                    hazeRange: 500.0
                }
            };
            Entities.editEntity(sky, newProperty);

        }
    );

    autoTester.addStepSnapshot("Turn on altitude effect - top of tower is visible",
        function () {
            var newProperty = {
                haze: {
                    hazeAltitudeEffect: 1
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set ceiling to 500 - tower no longer visible",
        function () {
            var newProperty = {
                haze: {
                    hazeCeiling: 500.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set base to -200 - top of tower is visible",
        function () {
            var newProperty = {
                haze: {
                    hazeBaseRef: -200.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set base to 0 and haze colour to sandy - haze looks like a sandstorm",
        function () {
            var newProperty = {
                haze: {
                    hazeBaseRef: 0.0,
                    hazeColor:{"red":153,"green":107,"blue":47}
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend to 0.5 - tower and sky are partially visible",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 0.5
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend to 1 - sky becomes clear",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 1.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend back to 0 - cannot see tower nor sky",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 0.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Test glare effect (sun is 15 degrees elevation, 095 azimuth) - large burgundy sun glare effect can be seen",
        function () {
            var newProperty = {
                keyLight: {
                    direction:{"x":0.9622501869, "y":-0.2588190451, "z":-0.08418598283}
                },
                haze: {
                    hazeCeiling: 5000.0,
                    hazeEnableGlare: 1,
                    hazeGlareColor:{"red":176,"green":25,"blue":68},
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set glare angle to 5 degrees - sun glare angle becomes smaller",
        function () {
            var newProperty = {
                haze: {
                    hazeGlareAngle: 5
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Clean up",
        function () {
            Entities.deleteEntity(terrain);
            Entities.deleteEntity(sky);
        }
    );

    var result = autoTester.runTest(testType);
});
<commit_msg>WIP - haze test.<commit_after>var autoTester = Script.require("https://raw.githubusercontent.com/NissimHadar/hifi_tests/addRecursionToAutotester/tests/utils/autoTester.js" );

autoTester.perform("effect - haze", Script.resolvePath("."), function(testType) {
    var spectatorCameraConfig = autoTester.setupTest();

    var TESTS_URL = "https://github.com/NissimHadar/hifi_tests/blob/addRecursionToAutotester/";
    var SUFFIX = "?raw=true";

    var pos =  MyAvatar.position;

    var terrain = Entities.addEntity({
        type: 'Box',
        name: 'Terrain',
        shape: 'Cube',
        dimensions: { x: 1000.0, y: 0.2, z: 1000.0 },
        position: { x: pos.x, y: pos.y - 3.0, z: pos.z },
        color: { "blue": 200, "green": 200, "red": 200
        }
    });

    // A far away "tower"
    var base = Entities.addEntity({
        type: 'Box',
        name: 'Tower base',
        shape: 'Cube',
        dimensions: { x: 10.0, y: 10, z: 10.0 },
        position: { x: pos.x, y: pos.y + 1.0, z: pos.z - 1000.0},
        color: { "blue": 200, "green": 200, "red": 0
        }
    });
    var tower = Entities.addEntity({
        type: 'Box',
        name: 'Tower',
        shape: 'Cube',
        dimensions: { x: 3.0, y: 300, z: 3.0 },
        position: { x: pos.x, y: pos.y + 150, z: pos.z - 1000.0},
        color: { "blue": 0, "green": 200, "red": 200
        }
    });

    var SKY_URL = Script.resolvePath(TESTS_URL + 'assets/skymaps/Sky_Day-Sun-Mid-photo.ktx' + SUFFIX);
    var sky = Entities.addEntity({
        type: "Zone",
        name: "Sky",

        position: {x: MyAvatar.position.x, y: MyAvatar.position.y - 2.0, z: MyAvatar.position.z - 25.0},
        rotation: MyAvatar.orientation,
        dimensions: { x: 10000.0, y: 600.0, z: 10000.0 },

        keyLightMode: "enabled",
        keyLight:{
            color: {"red":255, "green":255, "blue":255},
            direction: {
                "x":  0.037007175385951996,
                "y": -0.7071067690849304,
                "z": -0.7061376571655273
            },
            intensity: 0.8
        },

        skyboxMode: "enabled",
        skybox: {
            color: {"red":255,"green":255,"blue":255},
            url: SKY_URL
        },

        ambientLightMode: "enabled",
        ambientLight: {
            ambientURL: SKY_URL
        }
    });

	spectatorCameraConfig.position = {x: MyAvatar.position.x, y: MyAvatar.position.y + 0.6, z: MyAvatar.position.z};

    // Look down X axis
    MyAvatar.bodyYaw = 90.0;
    MyAvatar.headYaw = 90.0;
    spectatorCameraConfig.orientation = { x: 0.0, y: 0.7071, z: 0.0, w: 0.7071 };

    autoTester.addStepSnapshot("Initial state");

    autoTester.addStepSnapshot("Enable haze, range at 15000 - sky is not visible, tower is visible",
        function () {
            var newProperty = {
                hazeMode: "enabled",
                haze: {
                    hazeRange: 15000.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set range to 500 - tower no longer visible",
        function () {
            var newProperty = {
                haze: {
                    hazeRange: 500.0
                }
            };
            Entities.editEntity(sky, newProperty);

        }
    );

    autoTester.addStepSnapshot("Turn on altitude effect - top of tower is visible",
        function () {
            var newProperty = {
                haze: {
                    hazeAltitudeEffect: 1
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set ceiling to 500 - tower no longer visible",
        function () {
            var newProperty = {
                haze: {
                    hazeCeiling: 500.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set base to -200 - top of tower is visible",
        function () {
            var newProperty = {
                haze: {
                    hazeBaseRef: -200.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set base to 0 and haze colour to sandy - haze looks like a sandstorm",
        function () {
            var newProperty = {
                haze: {
                    hazeBaseRef: 0.0,
                    hazeColor:{"red":153,"green":107,"blue":47}
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend to 0.5 - tower and sky are partially visible",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 0.5
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend to 1 - sky becomes clear",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 1.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set background blend back to 0 - cannot see tower nor sky",
        function () {
            var newProperty = {
                haze: {
                    hazeBackgroundBlend: 0.0
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Test glare effect (sun is 15 degrees elevation, 095 azimuth) - large burgundy sun glare effect can be seen",
        function () {
            var newProperty = {
                keyLight: {
                    direction:{"x":0.9622501869, "y":-0.2588190451, "z":-0.08418598283}
                },
                haze: {
                    hazeCeiling: 5000.0,
                    hazeEnableGlare: 1,
                    hazeGlareColor:{"red":176,"green":25,"blue":68},
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Set glare angle to 5 degrees - sun glare angle becomes smaller",
        function () {
            var newProperty = {
                haze: {
                    hazeGlareAngle: 5
                }
            };
            Entities.editEntity(sky, newProperty);
        }
    );

    autoTester.addStepSnapshot("Clean up",
        function () {
            Entities.deleteEntity(terrain);
            Entities.deleteEntity(sky);
        }
    );

    var result = autoTester.runTest(testType);
});
<|endoftext|>