<commit_before>import Debug from 'debug';
import fetchJsonp from 'fetch-jsonp';

const debug = Debug('chase:util');
const CHASE_S3_BASE_URL = 'https://s3.amazonaws.com/syon-chase';

function pickFallback(a, b, c) {
  if (a) { return a; }
  if (b) { return b; }
  if (c) { return c; }
  return null;
}

function makeCatalog(pocketItemSet, libraSet, hatebuCntSet) {
  const arr = Object.keys(pocketItemSet).map((eid) => {
    const item = pocketItemSet[eid];
    const libra = libraSet[eid];
    const ready = !!libra;
    if (!ready) return item;
    const hatebuCnt = hatebuCntSet[eid];
    const override = {
      ready,
      title: pickFallback(libra.title, item.title, item.url),
      site_name: pickFallback(libra.site_name, item.fqdn),
      hatebuCnt: hatebuCnt > 0 ? hatebuCnt : '',
    };
    return { ...item, ...override };
  });
  const sortedItems = arr.sort((a, b) => {
    if (a.time_added < b.time_added) return 1;
    if (a.time_added > b.time_added) return -1;
    return 0;
  });
  return sortedItems;
}

function getDate(time10) {
  const dt = new Date(time10 * 1000);
  const y = dt.getFullYear();
  const m = dt.getMonth() + 1;
  const d = dt.getDate();
  return `${y}.${m}.${d}`;
}

function moldRawItem(pocketRawItem) {
  const m = pocketRawItem;
  const url = m.resolved_url ? m.resolved_url : m.given_url;
  const title = m.resolved_title ? m.resolved_title : m.given_title;
  const item10Id = `0000000000${m.item_id}`.substr(-10, 10);
  const itemId3 = item10Id.slice(0, 3);
  const s3path = `items/thumbs/${itemId3}/${item10Id}.jpg`;
  return {
    eid: m.item_id,
    ready: false,
    url,
    image_suggested: (m.has_image === '1') ? m.image.src : '',
    image_s3_url: `${CHASE_S3_BASE_URL}/${s3path}`,
    title,
    excerpt: m.excerpt,
    fqdn: `${url}/`.match(/\/\/(.*?)\//)[1],
    sortId: m.sort_id,
    favorite: m.favorite === '1',
    tags: m.tags || {},
    added: getDate(m.time_added),
    updated: getDate(m.time_updated),
    time_added: m.time_added,
    time_updated: m.time_updated,
  };
}

function makeEntries(listFromPocket) {
  const newEntries = {};
  Object.keys(listFromPocket).forEach((key) => {
    newEntries[key] = moldRawItem(listFromPocket[key]);
  });
  return newEntries;
}

function makeS3Path(pocketId) {
  if (!pocketId) return null;
  const item10Id = `0000000000${pocketId}`.substr(-10, 10);
  const itemId3 = item10Id.slice(0, 3);
  return `items/libra/${itemId3}/${item10Id}.json`;
}

async function fetchLibraS3(pocketId) {
  debug('[fetchLibraS3]>>>>');
  const s3Path = makeS3Path(pocketId);
  const result = await fetch(`${CHASE_S3_BASE_URL}/${s3Path}`, {
    method: 'GET',
  })
    .then((response) => {
      if (response.ok) {
        return response.json();
      }
      throw response;
    }).catch((e) => {
      debug(pocketId, e);
      throw e;
    });
  debug('[fetchLibraS3]<<<<', result);
  return result;
}

async function fetchHatebuCnt(url) {
  const encodedUrl = encodeURI(url);
  let apiHost;
  if (window.location.protocol === 'https:') {
    apiHost = 'https://b.hatena.ne.jp';
  } else {
    apiHost = 'http://api.b.st-hatena.com';
  }
  const apiUrl = `${apiHost}/entry.count?url=${encodedUrl}`;
  const cnt = await fetchJsonp(apiUrl).then(r => r.json());
  return cnt;
}

export default {
  makeCatalog,
  makeEntries,
  fetchLibraS3,
  fetchHatebuCnt,
};
<commit_msg>:cyclone: exerpt and desc fallback<commit_after>import Debug from 'debug';
import fetchJsonp from 'fetch-jsonp';

const debug = Debug('chase:util');
const CHASE_S3_BASE_URL = 'https://s3.amazonaws.com/syon-chase';

function pickFallback(a, b, c) {
  if (a) { return a; }
  if (b) { return b; }
  if (c) { return c; }
  return null;
}

function makeCatalog(pocketItemSet, libraSet, hatebuCntSet) {
  const arr = Object.keys(pocketItemSet).map((eid) => {
    const item = pocketItemSet[eid];
    const libra = libraSet[eid];
    const ready = !!libra;
    if (!ready) return item;
    const hatebuCnt = hatebuCntSet[eid];
    const override = {
      ready,
      title: pickFallback(libra.title, item.title, item.url),
      site_name: pickFallback(libra.site_name, item.fqdn),
      excerpt: pickFallback(item.excerpt, libra.description),
      description: pickFallback(libra.description, item.excerpt),
      hatebuCnt: hatebuCnt > 0 ? hatebuCnt : '',
    };
    return { ...item, ...override };
  });
  const sortedItems = arr.sort((a, b) => {
    if (a.time_added < b.time_added) return 1;
    if (a.time_added > b.time_added) return -1;
    return 0;
  });
  return sortedItems;
}

function getDate(time10) {
  const dt = new Date(time10 * 1000);
  const y = dt.getFullYear();
  const m = dt.getMonth() + 1;
  const d = dt.getDate();
  return `${y}.${m}.${d}`;
}

function moldRawItem(pocketRawItem) {
  const m = pocketRawItem;
  const url = m.resolved_url ? m.resolved_url : m.given_url;
  const title = m.resolved_title ? m.resolved_title : m.given_title;
  const item10Id = `0000000000${m.item_id}`.substr(-10, 10);
  const itemId3 = item10Id.slice(0, 3);
  const s3path = `items/thumbs/${itemId3}/${item10Id}.jpg`;
  return {
    eid: m.item_id,
    ready: false,
    url,
    image_suggested: (m.has_image === '1') ? m.image.src : '',
    image_s3_url: `${CHASE_S3_BASE_URL}/${s3path}`,
    title,
    excerpt: m.excerpt,
    fqdn: `${url}/`.match(/\/\/(.*?)\//)[1],
    sortId: m.sort_id,
    favorite: m.favorite === '1',
    tags: m.tags || {},
    added: getDate(m.time_added),
    updated: getDate(m.time_updated),
    time_added: m.time_added,
    time_updated: m.time_updated,
  };
}

function makeEntries(listFromPocket) {
  const newEntries = {};
  Object.keys(listFromPocket).forEach((key) => {
    newEntries[key] = moldRawItem(listFromPocket[key]);
  });
  return newEntries;
}

function makeS3Path(pocketId) {
  if (!pocketId) return null;
  const item10Id = `0000000000${pocketId}`.substr(-10, 10);
  const itemId3 = item10Id.slice(0, 3);
  return `items/libra/${itemId3}/${item10Id}.json`;
}

async function fetchLibraS3(pocketId) {
  debug('[fetchLibraS3]>>>>');
  const s3Path = makeS3Path(pocketId);
  const result = await fetch(`${CHASE_S3_BASE_URL}/${s3Path}`, {
    method: 'GET',
  })
    .then((response) => {
      if (response.ok) {
        return response.json();
      }
      throw response;
    }).catch((e) => {
      debug(pocketId, e);
      throw e;
    });
  debug('[fetchLibraS3]<<<<', result);
  return result;
}

async function fetchHatebuCnt(url) {
  const encodedUrl = encodeURI(url);
  let apiHost;
  if (window.location.protocol === 'https:') {
    apiHost = 'https://b.hatena.ne.jp';
  } else {
    apiHost = 'http://api.b.st-hatena.com';
  }
  const apiUrl = `${apiHost}/entry.count?url=${encodedUrl}`;
  const cnt = await fetchJsonp(apiUrl).then(r => r.json());
  return cnt;
}

export default {
  makeCatalog,
  makeEntries,
  fetchLibraS3,
  fetchHatebuCnt,
};
<|endoftext|>


<commit_before>import $ from 'jquery';
import {extend, isString} from '../util/index';

var uid = 0, containers = {}, messages = {};

var notify = function(options){

    if (isString(options)) {
        options = { message: options };
    }

    if (arguments[1]) {
        options = extend(options, isString(arguments[1]) ? {status:arguments[1]} : arguments[1]);
    }

    return (new Message(options)).show();
};

var closeAll  = function(group, instantly){

    if (group) {
        for(var id in messages) { if (group===messages[id].group) messages[id].close(instantly); }
    } else {
        for(var id in messages) { messages[id].close(instantly); }
    }
};

class Message {

    constructor(options) {

        this.options = extend({
            message: '',
            status: '',
            timeout: 5000,
            group: null,
            pos: 'top-center',
            onClose: function() {}
        }, options);

        this.uuid    = `notifymsg-${++uid}`;
        this.element = $(`

        `).on('click', () => {
            this.element.trigger('close', [this]);
            this.close();
        });

        this.content(this.options.message);

        // status
        if (this.options.status) {
            this.element.addClass(`uk-notify-message-${this.options.status}`);
            this.currentstatus = this.options.status;
        }

        this.group = this.options.group;

        messages[this.uuid] = this;

        if (!containers[this.options.pos]) {
            containers[this.options.pos] = $(`<div class="uk-notify uk-notify-${this.options.pos}"></div>`).appendTo('body');
        }
    }

    show() {

        if (this.element.is(":visible")) {
            return;
        }

        containers[this.options.pos].show().prepend(this.element);

        var marginbottom = parseInt(this.element.css('margin-bottom'), 10);

        this.element.css({opacity:0, marginTop: -1*this.element.outerHeight(), marginBottom:0}).animate({opacity:1, marginTop: 0, marginBottom: marginbottom}, () => {

            if (this.options.timeout) {

                this.timeout = setTimeout(() => { this.close(); }, this.options.timeout);

                this.element.hover(
                    () => { clearTimeout(this.timeout); },
                    () => { this.timeout = setTimeout(() => { this.close(); }, this.options.timeout);  }
                );
            }

        });

        return this;
    }

    close(instantly) {

        var finalize = () => {

            this.element.remove();

            if (!containers[this.options.pos].children().length) {
                containers[this.options.pos].hide();
            }

            this.options.onClose.apply(this, []);
            this.element.trigger('close.uk.notify', [this]);

            delete messages[this.uuid];
        };

        if (this.timeout) {
            clearTimeout(this.timeout);
        }

        if (instantly) {
            finalize();
        } else {
            this.element.animate({"opacity":0, "margin-top": -1* this.element.outerHeight(), "margin-bottom":0}, function(){
                finalize();
            });
        }
    }

    content(html){

        var container = this.element.find(">div");

        if (!html) {
            return container.html();
        }

        container.html(html);

        return this;
    }

    status(status) {

        if (!status) {
            return this.currentstatus;
        }

        this.element.removeClass('uk-notify-message-'+this.currentstatus).addClass('uk-notify-message-'+status);
        this.currentstatus = status;

        return this;
    }
}

UIkit.notify          = notify;
UIkit.notify.message  = Message;
UIkit.notify.closeAll = closeAll;
<commit_msg>notify cleanup<commit_after>import $ from 'jquery';
import {extend, isString} from '../util/index';

var uid = 0, containers = {}, messages = {};

var notify = function(options){

    if (isString(options)) {
        options = { message: options };
    }

    if (arguments[1]) {
        options = extend(options, isString(arguments[1]) ? {status:arguments[1]} : arguments[1]);
    }

    return (new Message(options)).show();
};

var closeAll  = function(group, instantly){

    if (group) {
        for(var id in messages) { if (group===messages[id].group) messages[id].close(instantly); }
    } else {
        for(var id in messages) { messages[id].close(instantly); }
    }
};

class Message {

    constructor(options) {

        this.options = extend({
            message: '',
            status: '',
            timeout: 5000,
            group: null,
            pos: 'top-center',
            onClose: function() {}
        }, options);

        this.uuid    = `notifymsg-${++uid}`;
        this.element = $(`

        `).on('click', () => {
            this.element.trigger('close', [this]);
            this.close();
        });

        this.content(this.options.message);

        // status
        if (this.options.status) {
            this.element.addClass(`uk-notify-message-${this.options.status}`);
            this.currentstatus = this.options.status;
        }

        this.group = this.options.group;

        messages[this.uuid] = this;

        if (!containers[this.options.pos]) {
            containers[this.options.pos] = $(`<div class="uk-notify uk-notify-${this.options.pos}"></div>`).appendTo('body');
        }
    }

    show() {

        if (this.element.is(':visible')) {
            return;
        }

        containers[this.options.pos].show().prepend(this.element);

        var marginbottom = parseInt(this.element.css('margin-bottom'), 10);

        this.element.css({opacity:0, marginTop: -1*this.element.outerHeight(), marginBottom:0}).animate({opacity:1, marginTop: 0, marginBottom: marginbottom}, () => {

            if (this.options.timeout) {

                this.timeout = setTimeout(() => { this.close(); }, this.options.timeout);

                this.element.hover(
                    () => { clearTimeout(this.timeout); },
                    () => { this.timeout = setTimeout(() => { this.close(); }, this.options.timeout);  }
                );
            }

        });

        return this;
    }

    close(instantly) {

        var finalize = () => {

            this.element.remove();

            if (!containers[this.options.pos].children().length) {
                containers[this.options.pos].hide();
            }

            this.options.onClose.apply(this, []);
            this.element.trigger('close.uk.notify', [this]);

            delete messages[this.uuid];
        };

        if (this.timeout) {
            clearTimeout(this.timeout);
        }

        if (instantly) {
            finalize();
        } else {
            this.element.animate({opacity:0, marginTop: -1* this.element.outerHeight(), marginBottom:0}, function(){
                finalize();
            });
        }
    }

    content(html){

        var container = this.element.find(">div");

        if (!html) {
            return container.html();
        }

        container.html(html);

        return this;
    }

    status(status) {

        if (!status) {
            return this.currentstatus;
        }

        this.element.removeClass(`uk-notify-message-${this.currentstatus}`).addClass(`uk-notify-message-${status}`);
        this.currentstatus = status;

        return this;
    }
}

UIkit.notify          = notify;
UIkit.notify.message  = Message;
UIkit.notify.closeAll = closeAll;
<|endoftext|>


<commit_before>'use strict';
var path = require('path'),
  examplePath = path.join(__dirname, '/../../examples'),
  assert = require('assert'),
  fs = require('fs'),
  bundler = require('../../index'),
  gulp = require('gulp'),
  through = require('through2'),
  rimraf = require('rimraf'),
  should = require('should'),
  helpers = require('../helpers');

describe('integration tests', function () {

  var fileCount,
    staticFileCount;

  beforeEach(function () {
    fileCount = 0;
    staticFileCount = 0;
  });

  describe('simple', function () {
    var appPath = path.join(examplePath, 'simple'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], 'function logFoo(){console.log("foo")}function logBaz(){console.log("baz")}logFoo(),logBaz();');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), 'body {\n' +
            '  background-color:red;\n' +
            '}\n' +
            '.test {\n' +
            '  background-color: blue;\n' +
            '}\n');
        } else if (file.relative === 'content/images/logo.png' ||
          file.relative === 'content/fonts/awesome.svg') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(4);
        (staticFileCount).should.eql(2);
      });

    });
  });

  describe('bower', function () {
    var appPath = path.join(examplePath, 'bower'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], 'console.log("one"),console.log("two");');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'),
              'body {\n' +
              '  background-color:red;\n' +
              '}\n' +
              'body {\n' +
              '  font-weight: bold;\n' +
              '}\n');
        } else if (file.relative === 'vendor.js') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapJs(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), 'console.log("jquery.min");\nconsole.log("angular.min");\n');
        } else if (file.relative === 'vendor.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'),
              '.bootstrap {\n' +
              '  background-color: red;\n' +
              '}\n' +
              '.bootstrap-theme {\n' +
              '  background-color: red;\n' +
              '}\n');
        } else if (file.relative === 'bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot' ||
          file.relative === 'bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg' ||
          file.relative === 'bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf' ||
          file.relative === 'bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(8);
        (staticFileCount).should.eql(4);
      });

    });
  });

  describe('express-app-using-result-json', function () {
    var appPath = path.join(examplePath, 'express-app-using-result-json'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], '!function(e){e.parentNode.removeChild(e)}(document.getElementById("error-message")),console.log("foo");');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), '.success-text {\n' +
            '  color: green;\n' +
            '}\n');
        } else if (file.relative === 'content/images/gulp.png') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;
      }, function () {
        (fileCount).should.eql(3);
        (staticFileCount).should.eql(1);
      });

    });

    describe('result.json', function () {

      var testDest = path.join(__dirname, '.public');

      it('should read example bundle.config, create bundles and create bundle.result.json', function (done) {

        gulp.src(bundleConfigPath)
          .pipe(bundler({
            base: appPath
          }))
          .pipe(bundler.results(testDest))
          .pipe(gulp.dest(testDest))
          .pipe(through.obj(function (file, enc, cb) {

            var lines;

            if (file.relative === 'main.js') {
              lines = file.contents.toString().split(/\r?\n/);
              assert.equal(lines[0], '!function(e){e.parentNode.removeChild(e)}(document.getElementById("error-message")),console.log("foo");');
              helpers.assertStringStartsWithSourceMapJs(lines[1]);
            } else if (file.relative === 'main.css') {
              lines = file.contents.toString().split(/\r?\n/);
              helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
              delete lines[lines.length - 1];
              assert.equal(lines.join('\n'), '.success-text {\n' +
                '  color: green;\n' +
                '}\n');
            } else if (file.relative === 'content/images/gulp.png') {
              staticFileCount++;
            } else {
              helpers.errorUnexpectedFileInStream(file);
            }
            fileCount++;
            this.push(file);
            cb();
          }))
          .on('data', function () {
          }) // noop
          .on('end', function () {
            fs.readFile(path.join(testDest, 'bundle.result.json'), function (err, data) {
              if (err) {
                throw err;
              }

              var resultsJson = JSON.parse(data);
              assert.deepEqual(resultsJson, {
                "main": {
                  "styles": "<link href='main.css' media='screen' rel='stylesheet' type='text/css'/>",
                  "scripts": "<script src='main.js' type='text/javascript'></script>"
                }
              });

              (fileCount).should.eql(3);
              (staticFileCount).should.eql(1);

              done();
            });
          });

      });

      afterEach(function (done) {
        rimraf(testDest, function (err) {
          if (err) {
            done(err);
          }
          done();
        });
      });

    });

  });

  describe('result-json', function () {
    var appPath = path.join(examplePath, 'result-json'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js'),
      testDest = path.join(__dirname, '.public');

    it('should read bundle.config and create result json', function (done) {

      gulp.src(bundleConfigPath)
        .pipe(bundler({
          base: appPath
        }))
        .pipe(bundler.results(testDest))
        .pipe(gulp.dest(testDest))
        .on('data', function () {
        }) // noop
        .on('end', function () {
          fs.readFile(path.join(testDest, 'bundle.result.json'), function (err, data) {
            if (err) {
              throw err;
            }

            var resultsJson = JSON.parse(data);
            assert.deepEqual(resultsJson, {
              "customJs": {
                "scripts": "<script src='customJs.js' type='text/javascript'></script>"
              },
              "lessBundle": {
                "styles": "<link href='lessBundle.css' media='screen' rel='stylesheet' type='text/css'/>"
              },
              "main": {
                "styles": "<link href='main.css' media='screen' rel='stylesheet' type='text/css'/>",
                "scripts": "<script src='main.js' type='text/javascript'></script>"
              },
              "vendor": {
                "scripts": "<script src='vendor.js' type='text/javascript'></script>",
                "styles": "<link href='vendor.css' media='screen' rel='stylesheet' type='text/css'/>"
              }
            });

            done();
          });
        });

    });

    afterEach(function (done) {
      rimraf(testDest, function (err) {
        if (err) {
          done(err);
        }
        done();
      });
    });

  });

  describe('copy', function () {
    var appPath = path.join(examplePath, 'copy'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and copy files', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {

        if (file.relative === 'include_path/content/car_icon.png' ||
          file.relative === 'include_path/content/lifering_icon.png' ||
          file.relative === 'content/empire_icon.png' ||
          file.relative === 'content/rebel_icon.png' ||
          file.relative === 'bomb_icon.png' ||
          file.relative === 'content/extinguisher_icon.png') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(6);
        (staticFileCount).should.eql(6);
      });

    });
  });

  // -----------------------
  // helpers
  // -----------------------

  function testBundleStream(bundleConfigPath, appPath, done, testFunc, beforeEnd) {
    gulp.src(bundleConfigPath)
      .pipe(bundler({
        base: appPath
      }))
      .pipe(through.obj(function (file, enc, cb) {
        testFunc(file);
        this.push(file);
        cb();
      }))
      .on('data', function () {
      }) // noop
      .on('error', function (err) {
        done(err);
      })
      .on('end', function () {
        if (beforeEnd) {
          beforeEnd();
        }
        done();
      });
  }

});
<commit_msg>fix test based on new pathing in bower example<commit_after>'use strict';
var path = require('path'),
  examplePath = path.join(__dirname, '/../../examples'),
  assert = require('assert'),
  fs = require('fs'),
  bundler = require('../../index'),
  gulp = require('gulp'),
  through = require('through2'),
  rimraf = require('rimraf'),
  should = require('should'),
  helpers = require('../helpers');

describe('integration tests', function () {

  var fileCount,
    staticFileCount;

  beforeEach(function () {
    fileCount = 0;
    staticFileCount = 0;
  });

  describe('simple', function () {
    var appPath = path.join(examplePath, 'simple'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], 'function logFoo(){console.log("foo")}function logBaz(){console.log("baz")}logFoo(),logBaz();');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), 'body {\n' +
            '  background-color:red;\n' +
            '}\n' +
            '.test {\n' +
            '  background-color: blue;\n' +
            '}\n');
        } else if (file.relative === 'content/images/logo.png' ||
          file.relative === 'content/fonts/awesome.svg') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(4);
        (staticFileCount).should.eql(2);
      });

    });
  });

  describe('bower', function () {
    var appPath = path.join(examplePath, 'bower'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], 'console.log("one"),console.log("two");');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'),
              'body {\n' +
              '  background-color:red;\n' +
              '}\n' +
              'body {\n' +
              '  font-weight: bold;\n' +
              '}\n');
        } else if (file.relative === 'vendor.js') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapJs(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), 'console.log("jquery.min");\nconsole.log("angular.min");\n');
        } else if (file.relative === 'vendor.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'),
              '.bootstrap {\n' +
              '  background-color: red;\n' +
              '}\n' +
              '.bootstrap-theme {\n' +
              '  background-color: red;\n' +
              '}\n');
        } else if (file.relative === 'dist/fonts/glyphicons-halflings-regular.eot' ||
          file.relative === 'dist/fonts/glyphicons-halflings-regular.svg' ||
          file.relative === 'dist/fonts/glyphicons-halflings-regular.ttf' ||
          file.relative === 'dist/fonts/glyphicons-halflings-regular.woff') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(8);
        (staticFileCount).should.eql(4);
      });

    });
  });

  describe('express-app-using-result-json', function () {
    var appPath = path.join(examplePath, 'express-app-using-result-json'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and create bundles', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {
        var lines;

        if (file.relative === 'main.js') {
          lines = file.contents.toString().split(/\r?\n/);
          assert.equal(lines[0], '!function(e){e.parentNode.removeChild(e)}(document.getElementById("error-message")),console.log("foo");');
          helpers.assertStringStartsWithSourceMapJs(lines[1]);
        } else if (file.relative === 'main.css') {
          lines = file.contents.toString().split(/\r?\n/);
          helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
          delete lines[lines.length - 1];
          assert.equal(lines.join('\n'), '.success-text {\n' +
            '  color: green;\n' +
            '}\n');
        } else if (file.relative === 'content/images/gulp.png') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;
      }, function () {
        (fileCount).should.eql(3);
        (staticFileCount).should.eql(1);
      });

    });

    describe('result.json', function () {

      var testDest = path.join(__dirname, '.public');

      it('should read example bundle.config, create bundles and create bundle.result.json', function (done) {

        gulp.src(bundleConfigPath)
          .pipe(bundler({
            base: appPath
          }))
          .pipe(bundler.results(testDest))
          .pipe(gulp.dest(testDest))
          .pipe(through.obj(function (file, enc, cb) {

            var lines;

            if (file.relative === 'main.js') {
              lines = file.contents.toString().split(/\r?\n/);
              assert.equal(lines[0], '!function(e){e.parentNode.removeChild(e)}(document.getElementById("error-message")),console.log("foo");');
              helpers.assertStringStartsWithSourceMapJs(lines[1]);
            } else if (file.relative === 'main.css') {
              lines = file.contents.toString().split(/\r?\n/);
              helpers.assertStringStartsWithSourceMapCss(lines[lines.length - 1]);
              delete lines[lines.length - 1];
              assert.equal(lines.join('\n'), '.success-text {\n' +
                '  color: green;\n' +
                '}\n');
            } else if (file.relative === 'content/images/gulp.png') {
              staticFileCount++;
            } else {
              helpers.errorUnexpectedFileInStream(file);
            }
            fileCount++;
            this.push(file);
            cb();
          }))
          .on('data', function () {
          }) // noop
          .on('end', function () {
            fs.readFile(path.join(testDest, 'bundle.result.json'), function (err, data) {
              if (err) {
                throw err;
              }

              var resultsJson = JSON.parse(data);
              assert.deepEqual(resultsJson, {
                "main": {
                  "styles": "<link href='main.css' media='screen' rel='stylesheet' type='text/css'/>",
                  "scripts": "<script src='main.js' type='text/javascript'></script>"
                }
              });

              (fileCount).should.eql(3);
              (staticFileCount).should.eql(1);

              done();
            });
          });

      });

      afterEach(function (done) {
        rimraf(testDest, function (err) {
          if (err) {
            done(err);
          }
          done();
        });
      });

    });

  });

  describe('result-json', function () {
    var appPath = path.join(examplePath, 'result-json'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js'),
      testDest = path.join(__dirname, '.public');

    it('should read bundle.config and create result json', function (done) {

      gulp.src(bundleConfigPath)
        .pipe(bundler({
          base: appPath
        }))
        .pipe(bundler.results(testDest))
        .pipe(gulp.dest(testDest))
        .on('data', function () {
        }) // noop
        .on('end', function () {
          fs.readFile(path.join(testDest, 'bundle.result.json'), function (err, data) {
            if (err) {
              throw err;
            }

            var resultsJson = JSON.parse(data);
            assert.deepEqual(resultsJson, {
              "customJs": {
                "scripts": "<script src='customJs.js' type='text/javascript'></script>"
              },
              "lessBundle": {
                "styles": "<link href='lessBundle.css' media='screen' rel='stylesheet' type='text/css'/>"
              },
              "main": {
                "styles": "<link href='main.css' media='screen' rel='stylesheet' type='text/css'/>",
                "scripts": "<script src='main.js' type='text/javascript'></script>"
              },
              "vendor": {
                "scripts": "<script src='vendor.js' type='text/javascript'></script>",
                "styles": "<link href='vendor.css' media='screen' rel='stylesheet' type='text/css'/>"
              }
            });

            done();
          });
        });

    });

    afterEach(function (done) {
      rimraf(testDest, function (err) {
        if (err) {
          done(err);
        }
        done();
      });
    });

  });

  describe('copy', function () {
    var appPath = path.join(examplePath, 'copy'),
      bundleConfigPath = path.join(appPath, 'bundle.config.js');

    it('should read example bundle.config and copy files', function (done) {

      testBundleStream(bundleConfigPath, appPath, done, function (file) {

        if (file.relative === 'include_path/content/car_icon.png' ||
          file.relative === 'include_path/content/lifering_icon.png' ||
          file.relative === 'content/empire_icon.png' ||
          file.relative === 'content/rebel_icon.png' ||
          file.relative === 'bomb_icon.png' ||
          file.relative === 'content/extinguisher_icon.png') {
          staticFileCount++;
        } else {
          helpers.errorUnexpectedFileInStream(file);
        }
        fileCount++;

      }, function () {
        (fileCount).should.eql(6);
        (staticFileCount).should.eql(6);
      });

    });
  });

  // -----------------------
  // helpers
  // -----------------------

  function testBundleStream(bundleConfigPath, appPath, done, testFunc, beforeEnd) {
    gulp.src(bundleConfigPath)
      .pipe(bundler({
        base: appPath
      }))
      .pipe(through.obj(function (file, enc, cb) {
        testFunc(file);
        this.push(file);
        cb();
      }))
      .on('data', function () {
      }) // noop
      .on('error', function (err) {
        done(err);
      })
      .on('end', function () {
        if (beforeEnd) {
          beforeEnd();
        }
        done();
      });
  }

});
<|endoftext|>


<commit_before>/* Integration tests to ensure random number generators produce the correct
 * distributions.
 * This likely does not check for "proper" "pseudo-random" behavior.
 *
 * Simply uses chi-squared test to compare the distribution produced by
 * the random variate generators to the theoretical one.
 */
var main = require('..');
var chai = require('chai');
var expect = chai.expect;
var utils = require('../panthrMath/utils');
var chisq = main.chisq;
var precision = 1e-8;

var n = 10000;    // Number of random variates generated for each test
var nks = 1500;
var reps = 100;    // Number of times to repeat test

// Returns the array [a, a+1, ..., b]
function seq(a, b) {
   var ret;
   ret = [];
   while (a <= b) {
      ret.push(a);
      a += 1;
   }
   return ret;
}

// Remove the x values that are have low expected frequencies and also low actual
// requencies
function cleanUp(xs, d) {
   return xs.filter(function(x) {
      return d(x) > 1e-3;
   });
}

function getPvalue(observed, predicted, dfs) {
   var testStat;

   testStat = predicted.reduce(function(acc, p, i) {
      var ratio = ((observed[i] / n) - p) / p;
      return acc + p * ratio * ratio;
   }, 0);
   testStat *= n;
   return chisq(dfs).p(testStat, false);
}
/*
   * Returns the array of `reps` many p-values from the test
   * `distrObj` is the distribution object (with r, p, q, d properties)
   * `xs` is the array of possible values for the distribution.
   * The function will filter these to something closer to the
   * distribution's "support" before applying the chi.sq test.
*/
function testDiscrete(distrObj, xs, nparams) {
   var pvalues, observed, predicted, rep, i, variate, filterFun;

   pvalues = [];
   predicted = xs.map(function(x) { return distrObj.d(x); });

   for (rep = 0; rep < reps; rep += 1) {
      observed = xs.map(function(x) { return 0; });

      for (i = 0; i < n; i += 1) {
         variate = distrObj.r();
         xs.forEach(function(x, i) {
            if (variate == x) { observed[i] += 1; }
         });
      }
      filterFun = function(v, i) {
         return observed[i] > 4 && predicted[i] > 4 / n;
      };
      pvalues.push(getPvalue(observed.filter(filterFun),
                             predicted.filter(filterFun),
                             xs.filter(filterFun).length - nparams - 1));
   }

   // Return proportion of small p-values. On a properly calibrated r-distr
   // this should be 0-20%.
   return pvalues.reduce(function(acc, v) {
         return v < 0.05 ? (acc + 1) : acc;
      }, 0) / reps;
}

/*
 * This will do a Kolmogorov-Smirnov goodness-of-fit test.
 */
function testCont(distrObj) {
   var pvalues, rep, observed, ksdiffs, dstat, i;

   pvalues = [];

   for (rep = 0; rep < reps; rep += 1) {
      observed = [];
      for (i = 0; i < nks; i += 1) {
         observed.push(distrObj.r());
      }
      observed.sort(function(x, y) { return x - y; });
      ksdiffs = observed.map(function(x, i) {
         return distrObj.p(x) - i / nks;
      });
      dstat = ksdiffs.reduce(function(acc, x) {
         return Math.max(acc, Math.abs(x), Math.abs(1 / nks - x));
      }, -1);

      pvalues.push(ks(nks, dstat));
   }

   return pvalues.reduce(function(acc, v) {
      return v < 0.05 ? (acc + 1) : acc;
   }, 0) / reps;

}

// BEGIN KS IMPLEMENTATION

 /* Compute Kolmogorov's distribution.
    Code published in
 George Marsaglia and Wai Wan Tsang and Jingbo Wang (2003),
 "Evaluating Kolmogorov's distribution".
 Journal of Statistical Software, Volume 8, 2003, Issue 18.
 URL: http://www.jstatsoft.org/v08/i18/.

 We are returning the upper-tail p-value
 */
function ks(n, d)
{
   var k, m, i, j, g, h, s, H, Q, basicArr;

   /*
      The faster right-tail approximation is omitted here.
   */
   s = d * d * n;
   if (s > 7.24 || (s > 3.76 && n > 99)) {
      return 2 * Math.exp(-(2.000071+.331/Math.sqrt(n)+1.409/n)*s);
   }
   k = Math.floor(n * d) + 1;
   m = 2 * k - 1;
   h = k - n * d;
   basicArr = seq(1, m * m);
   H = basicArr.map(function() { return 0; });
   Q = basicArr.map(function() { return 0; });
   for (i = 0; i < m; i++) {
       for (j = 0; j < m; j++) {
         H[i * m + j] = i - j + 1 < 0 ? 0 : 1;
       }
   }
   // Fixing "numerators"
   for (i = 0; i < m; i++) {
       H[i * m] -= Math.pow(h, i + 1);
       H[(m - 1) * m + i] -= Math.pow(h, m - i);
   }
   // Adjust the bottom left corner if h > 1/2
   H[(m - 1) * m] += 2 * h - 1 > 0 ? Math.pow(2 * h - 1, m) : 0;
   // Fix "denominators"
   // TODO: Maybe can do better?
   for (i = 0; i < m; i++) {
       for (j = 0; j < i + 1; j++) {
            for (g = 1; g <= i - j + 1; g++) {
               H[i * m + j] /= g;
            }
       }
   }

   // Q will be an object with "arr" and "exp" properties
   Q = m_power({ arr: H, exp: 0 }, m, n);

   s = Q.arr[(k - 1) * m + k - 1];
   for(i = 1; i <= n; i++) {
       s = s * i / n;
       if (s < 1e-140) {
         s *= 1e140;
         Q.exp -= 140;
       }
   }
   return 1 - s * Math.pow(10, Q.exp);
}

// Multiplication of two mxm matrices.
function m_multiply(A, B, m) {
   var i, j, k, C;
   C = [];
   for (i = 0; i < m; i++) {
      for (j = 0; j < m; j++) {
         C[i * m + j] = 0;
         for(k = 0; k < m; k++) {
            C[i * m + j] += A[i * m + k] * B[k * m + j];
         }
      }
   }
   return C;
}

// Computes the "n"-th power of an mxm matrix
// arrObj is an object with properties arr and exp
// Returns an object with the same properties.
function m_power(arrObj, m, n) {

   var halfObj, retObj, i;

   if(n == 1) {
      return arrObj;
   }

   halfObj = m_power(arrObj, m, Math.floor(n / 2));

   retObj = { arr: m_multiply(halfObj.arr, halfObj.arr, m),
              exp: 2 * halfObj.exp };

   if (n % 2 == 1) {
      retObj = { arr: m_multiply(arrObj.arr, retObj.arr, m),
                 exp: arrObj.exp + retObj.exp };
    }

    if (retObj.arr[(m / 2) * m + (m / 2)] > 1e140) {
      for(i = 0; i < m * m; i++) {
         retObj.arr[i] *= 1e-140;
      }
      retObj.exp += 140;
    }

    return retObj;
}

// END KS IMPLEMENTATION

describe("(slow) Integration test", function() {
   describe("for binomial", function() {
      seq(1, 20).forEach(function() {
         it("repeated test", function() {
            var n, p, pvalues, xs, obj;
            n = 20 + Math.floor(Math.random() * 30);
            p = main.runif(0.1, 0.9)();
            expect(testDiscrete(main.binom(n, p), seq(0, n), 2)).to.be.below(0.2);
            // Providing a "closeby" distribution
            obj = main.binom(n, p);
            obj.r = main.binom(n, p * 1.01).r;
            expect(testDiscrete(obj, seq(0, n), 2)).to.be.above(0.2);
         });
      });
   });
   describe("for Poisson", function() {
      seq(1, 20).forEach(function() {
         it("repeated test", function() {
            var lambda, range, pvalues, xs, obj;
            lambda = main.runif(0.2, 4)();
            range = seq(0, lambda + 10 * Math.sqrt(lambda));
            expect(testDiscrete(main.pois(lambda), range, 1)).to.be.below(0.2);
            // Providing a "closeby" distribution
            obj = main.pois(lambda);
            obj.r = main.pois(lambda * 1.02).r;
            expect(testDiscrete(obj, range, 1)).to.be.above(0.2);
         });
      });
   });
   describe("for finite", function() {
      it("repeated test", function() {
         var setObj, dObj, pvalues, xs, obj;
         setObj = {
            xs: [1, 5, 7, 10],
            ws: [0.1, 0.2, 0.3, 0.4]
         };
         dObj = main.finite(setObj);
         expect(testDiscrete(dObj, setObj.xs, 0)).to.be.below(0.2);
         // Providing a "closeby" distribution
         setObj.ws[3] = 0.43;
         dObj.r = main.finite(setObj).r;
         expect(testDiscrete(dObj, setObj.xs, 0)).to.be.above(0.2);
      });
   });
   describe("for normal", function() {
      it("repeated test", function() {
         var mu = Math.random() * 5;
         var sigma = 1 + Math.random() * 3;
         var distr = main.normal(mu, sigma);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.normal(mu, 1.1 * sigma).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.normal(mu + 0.1 * sigma, sigma).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for uniform", function() {
      it("repeated test", function() {
         var min = Math.random() * 10;
         var max = min + Math.random() * 20;
         var distr = main.unif(min, max);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.unif(min, 1.1 * max).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.unif(1.1 * min, max).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for t", function() {
      it("repeated test", function() {
         var df = Math.random() * 30;
         var distr = main.tdistr(df);
         expect(testCont(distr)).to.be.below(0.2);
      });
   });
   describe("for gamma", function() {
      it("repeated test", function() {
         var s = 1 + Math.random() * 4;
         var a = 1 + Math.random() * 4;
         var distr = main.gammadistr(a, s);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.gammadistr(a, 1.1 * s).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.gammadistr(1.1 * a, s).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for beta", function() {
      it("a param > 1 but close to 1", function() {
         var a = 1 + Math.random() * 0.1;
         var b = 2 + Math.random() * 6;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.betadistr(a, 1.1 * b).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.betadistr(1.1 * a, b).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
      it("both params > 1", function() {
         var a = 2 + Math.random() * 6;
         var b = 2 + Math.random() * 6;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.betadistr(a, 1.1 * b).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.betadistr(1.1 * a, b).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
      it("one param < 1", function() {
         var a = Math.random();
         var b = 1 + Math.random() * 6;
         distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
      it("both params < 1", function() {
         // Values between (0,1) have different algorithm
         var a = 0.5 + Math.random() * 0.5;
         var b = 0.5 + Math.random() * 0.5;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
      it("one param close to 0", function() {
         // Values between (0,1) have different algorithm
         var a = Math.random() * 0.1;
         var b = Math.random() * 0.5 + 0.5;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
   });
});
<commit_msg>Add chi-squared integration test. Close #70<commit_after>/* Integration tests to ensure random number generators produce the correct
 * distributions.
 * This likely does not check for "proper" "pseudo-random" behavior.
 *
 * Simply uses chi-squared test to compare the distribution produced by
 * the random variate generators to the theoretical one.
 */
var main = require('..');
var chai = require('chai');
var expect = chai.expect;
var utils = require('../panthrMath/utils');
var chisq = main.chisq;
var precision = 1e-8;

var n = 10000;    // Number of random variates generated for each test
var nks = 1500;
var reps = 100;    // Number of times to repeat test

// Returns the array [a, a+1, ..., b]
function seq(a, b) {
   var ret;
   ret = [];
   while (a <= b) {
      ret.push(a);
      a += 1;
   }
   return ret;
}

// Remove the x values that are have low expected frequencies and also low actual
// requencies
function cleanUp(xs, d) {
   return xs.filter(function(x) {
      return d(x) > 1e-3;
   });
}

function getPvalue(observed, predicted, dfs) {
   var testStat;

   testStat = predicted.reduce(function(acc, p, i) {
      var ratio = ((observed[i] / n) - p) / p;
      return acc + p * ratio * ratio;
   }, 0);
   testStat *= n;
   return chisq(dfs).p(testStat, false);
}
/*
   * Returns the array of `reps` many p-values from the test
   * `distrObj` is the distribution object (with r, p, q, d properties)
   * `xs` is the array of possible values for the distribution.
   * The function will filter these to something closer to the
   * distribution's "support" before applying the chi.sq test.
*/
function testDiscrete(distrObj, xs, nparams) {
   var pvalues, observed, predicted, rep, i, variate, filterFun;

   pvalues = [];
   predicted = xs.map(function(x) { return distrObj.d(x); });

   for (rep = 0; rep < reps; rep += 1) {
      observed = xs.map(function(x) { return 0; });

      for (i = 0; i < n; i += 1) {
         variate = distrObj.r();
         xs.forEach(function(x, i) {
            if (variate == x) { observed[i] += 1; }
         });
      }
      filterFun = function(v, i) {
         return observed[i] > 4 && predicted[i] > 4 / n;
      };
      pvalues.push(getPvalue(observed.filter(filterFun),
                             predicted.filter(filterFun),
                             xs.filter(filterFun).length - nparams - 1));
   }

   // Return proportion of small p-values. On a properly calibrated r-distr
   // this should be 0-20%.
   return pvalues.reduce(function(acc, v) {
         return v < 0.05 ? (acc + 1) : acc;
      }, 0) / reps;
}

/*
 * This will do a Kolmogorov-Smirnov goodness-of-fit test.
 */
function testCont(distrObj) {
   var pvalues, rep, observed, ksdiffs, dstat, i;

   pvalues = [];

   for (rep = 0; rep < reps; rep += 1) {
      observed = [];
      for (i = 0; i < nks; i += 1) {
         observed.push(distrObj.r());
      }
      observed.sort(function(x, y) { return x - y; });
      ksdiffs = observed.map(function(x, i) {
         return distrObj.p(x) - i / nks;
      });
      dstat = ksdiffs.reduce(function(acc, x) {
         return Math.max(acc, Math.abs(x), Math.abs(1 / nks - x));
      }, -1);

      pvalues.push(ks(nks, dstat));
   }

   return pvalues.reduce(function(acc, v) {
      return v < 0.05 ? (acc + 1) : acc;
   }, 0) / reps;

}

// BEGIN KS IMPLEMENTATION

 /* Compute Kolmogorov's distribution.
    Code published in
 George Marsaglia and Wai Wan Tsang and Jingbo Wang (2003),
 "Evaluating Kolmogorov's distribution".
 Journal of Statistical Software, Volume 8, 2003, Issue 18.
 URL: http://www.jstatsoft.org/v08/i18/.

 We are returning the upper-tail p-value
 */
function ks(n, d)
{
   var k, m, i, j, g, h, s, H, Q, basicArr;

   /*
      The faster right-tail approximation is omitted here.
   */
   s = d * d * n;
   if (s > 7.24 || (s > 3.76 && n > 99)) {
      return 2 * Math.exp(-(2.000071+.331/Math.sqrt(n)+1.409/n)*s);
   }
   k = Math.floor(n * d) + 1;
   m = 2 * k - 1;
   h = k - n * d;
   basicArr = seq(1, m * m);
   H = basicArr.map(function() { return 0; });
   Q = basicArr.map(function() { return 0; });
   for (i = 0; i < m; i++) {
       for (j = 0; j < m; j++) {
         H[i * m + j] = i - j + 1 < 0 ? 0 : 1;
       }
   }
   // Fixing "numerators"
   for (i = 0; i < m; i++) {
       H[i * m] -= Math.pow(h, i + 1);
       H[(m - 1) * m + i] -= Math.pow(h, m - i);
   }
   // Adjust the bottom left corner if h > 1/2
   H[(m - 1) * m] += 2 * h - 1 > 0 ? Math.pow(2 * h - 1, m) : 0;
   // Fix "denominators"
   // TODO: Maybe can do better?
   for (i = 0; i < m; i++) {
       for (j = 0; j < i + 1; j++) {
            for (g = 1; g <= i - j + 1; g++) {
               H[i * m + j] /= g;
            }
       }
   }

   // Q will be an object with "arr" and "exp" properties
   Q = m_power({ arr: H, exp: 0 }, m, n);

   s = Q.arr[(k - 1) * m + k - 1];
   for(i = 1; i <= n; i++) {
       s = s * i / n;
       if (s < 1e-140) {
         s *= 1e140;
         Q.exp -= 140;
       }
   }
   return 1 - s * Math.pow(10, Q.exp);
}

// Multiplication of two mxm matrices.
function m_multiply(A, B, m) {
   var i, j, k, C;
   C = [];
   for (i = 0; i < m; i++) {
      for (j = 0; j < m; j++) {
         C[i * m + j] = 0;
         for(k = 0; k < m; k++) {
            C[i * m + j] += A[i * m + k] * B[k * m + j];
         }
      }
   }
   return C;
}

// Computes the "n"-th power of an mxm matrix
// arrObj is an object with properties arr and exp
// Returns an object with the same properties.
function m_power(arrObj, m, n) {

   var halfObj, retObj, i;

   if(n == 1) {
      return arrObj;
   }

   halfObj = m_power(arrObj, m, Math.floor(n / 2));

   retObj = { arr: m_multiply(halfObj.arr, halfObj.arr, m),
              exp: 2 * halfObj.exp };

   if (n % 2 == 1) {
      retObj = { arr: m_multiply(arrObj.arr, retObj.arr, m),
                 exp: arrObj.exp + retObj.exp };
    }

    if (retObj.arr[(m / 2) * m + (m / 2)] > 1e140) {
      for(i = 0; i < m * m; i++) {
         retObj.arr[i] *= 1e-140;
      }
      retObj.exp += 140;
    }

    return retObj;
}

// END KS IMPLEMENTATION

describe("(slow) Integration test", function() {
   describe("for binomial", function() {
      seq(1, 20).forEach(function() {
         it("repeated test", function() {
            var n, p, pvalues, xs, obj;
            n = 20 + Math.floor(Math.random() * 30);
            p = main.runif(0.1, 0.9)();
            expect(testDiscrete(main.binom(n, p), seq(0, n), 2)).to.be.below(0.2);
            // Providing a "closeby" distribution
            obj = main.binom(n, p);
            obj.r = main.binom(n, p * 1.01).r;
            expect(testDiscrete(obj, seq(0, n), 2)).to.be.above(0.2);
         });
      });
   });
   describe("for Poisson", function() {
      seq(1, 20).forEach(function() {
         it("repeated test", function() {
            var lambda, range, pvalues, xs, obj;
            lambda = main.runif(0.2, 4)();
            range = seq(0, lambda + 10 * Math.sqrt(lambda));
            expect(testDiscrete(main.pois(lambda), range, 1)).to.be.below(0.2);
            // Providing a "closeby" distribution
            obj = main.pois(lambda);
            obj.r = main.pois(lambda * 1.02).r;
            expect(testDiscrete(obj, range, 1)).to.be.above(0.2);
         });
      });
   });
   describe("for finite", function() {
      it("repeated test", function() {
         var setObj, dObj, pvalues, xs, obj;
         setObj = {
            xs: [1, 5, 7, 10],
            ws: [0.1, 0.2, 0.3, 0.4]
         };
         dObj = main.finite(setObj);
         expect(testDiscrete(dObj, setObj.xs, 0)).to.be.below(0.2);
         // Providing a "closeby" distribution
         setObj.ws[3] = 0.43;
         dObj.r = main.finite(setObj).r;
         expect(testDiscrete(dObj, setObj.xs, 0)).to.be.above(0.2);
      });
   });
   describe("for normal", function() {
      it("repeated test", function() {
         var mu = Math.random() * 5;
         var sigma = 1 + Math.random() * 3;
         var distr = main.normal(mu, sigma);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.normal(mu, 1.1 * sigma).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.normal(mu + 0.1 * sigma, sigma).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for uniform", function() {
      it("repeated test", function() {
         var min = Math.random() * 10;
         var max = min + Math.random() * 20;
         var distr = main.unif(min, max);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.unif(min, 1.1 * max).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.unif(1.1 * min, max).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for t", function() {
      it("repeated test", function() {
         var df = Math.random() * 30;
         var distr = main.tdistr(df);
         expect(testCont(distr)).to.be.below(0.2);
      });
   });
   describe("for gamma", function() {
      it("repeated test", function() {
         var s = 1 + Math.random() * 4;
         var a = 1 + Math.random() * 4;
         var distr = main.gammadistr(a, s);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.gammadistr(a, 1.1 * s).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.gammadistr(1.1 * a, s).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
   });
   describe("for beta", function() {
      it("a param > 1 but close to 1", function() {
         var a = 1 + Math.random() * 0.1;
         var b = 2 + Math.random() * 6;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.betadistr(a, 1.1 * b).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.betadistr(1.1 * a, b).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
      it("both params > 1", function() {
         var a = 2 + Math.random() * 6;
         var b = 2 + Math.random() * 6;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
         distr.r = main.betadistr(a, 1.1 * b).r;
         expect(testCont(distr)).to.be.above(0.2);
         distr.r = main.betadistr(1.1 * a, b).r;
         expect(testCont(distr)).to.be.above(0.2);
      });
      it("one param < 1", function() {
         var a = Math.random();
         var b = 1 + Math.random() * 6;
         distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
      it("both params < 1", function() {
         // Values between (0,1) have different algorithm
         var a = 0.5 + Math.random() * 0.5;
         var b = 0.5 + Math.random() * 0.5;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
      it("one param close to 0", function() {
         // Values between (0,1) have different algorithm
         var a = Math.random() * 0.1;
         var b = Math.random() * 0.5 + 0.5;
         var distr = main.betadistr(a, b);
         expect(testCont(distr)).to.be.below(0.2);
      });
   });
   describe("for chi-squared", function() {
      it("repeated test", function() {
         var df, distr;
         for (var i = 0; i < 5; i += 1) {
            df = Math.random() * 60;
            distr = main.chisq(df);
            expect(testCont(distr)).to.be.below(0.2);
         }
      });
   });
});
<|endoftext|>


<commit_before>(function(){
	var pim = util.isObject("Widget.PIM") ? Widget.PIM : {};

	dohx.add({name:"setupHelper",
		tests:[
			//
			// Preconditions
			//
			{
				id:1,
				name:"Helper Widget",
				instructions:[
					"This widget will show some relevant information which you might need to configure your test widget(s) properly.",
				],
				test:function(t){
					t.success(true);
				}
			},
			{
				id:2,
				name:"config info",
				test:function(t){
					if (config._meta.isCustomConfiguration){
						t.success(config._meta);
					}else{
						t.failure("Unconfigured, userAgent: " + window.navigator.userAgent);
					}
				}
			},

			//
			//
			//
			{
				id:100,
				name:"config.validAddressBookItemId - possible value (fullName=null)",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", null);
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					pim.onAddressBookItemsFound = null;
				}
			},
			{
				id:105,
				name:"config.validAddressBookItemId - possible value (fullName=*)",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", "*");
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					pim.onAddressBookItemsFound = null;
				}
			},
			{
				id:110,
				name:"config.validAddressBookItemId - current value",
				test:function(t){
					var val = config.validAddressBookItemId;
					t[val ? "success" : "failure"](val);
				}
			},
			{
				id:120,
				name:"config.validAddressBookItemId - Item is an instance of AddressBookItem?",
				test:function(t){
					var item = Widget.PIM.getAddressBookItem(config.validAddressBookItemId);
					t.assertTrue(item instanceof Widget.PIM.AddressBookItem);
				}
			},
			{
				id:200,
				name:"config.validCalendarItemId - possible value (eventName=null)",
				timeout: 60*1000, // some devices are slooooow E5-00 ;)
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = null;
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					pim.onCalendarItemsFound = null;
				}
			},
			{
				id:205,
				name:"config.validCalendarItemId - possible value (eventName=*)",
				timeout: 60*1000, // some devices are slooooow E5-00 ;)
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = "*";
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					pim.onCalendarItemsFound = null;
				}
			},
			{
				id:210,
				name:"config.validCalendarItemId - current value",
				test:function(t){
					var val = config.validCalendarItemId;
					t[val ? "success" : "failure"](val);
				}
			},
			{
				id:220,
				name:"config.validCalendarItemId - Item is an instance of CalendarItem?",
				test:function(t){
					var item = Widget.PIM.getCalendarItem(config.validCalendarItemId);
					t.assertTrue(item instanceof Widget.PIM.CalendarItem);
				}
			},
//*/
		]
	});

})();<commit_msg>Added some more precondition info<commit_after>(function(){
	var pim = util.isObject("Widget.PIM") ? Widget.PIM : {};

	dohx.add({name:"setupHelper",
		tests:[
			//
			// Preconditions
			//
			{
				id:1,
				name:"Helper Widget",
				instructions:[
					"This widget will show some relevant information which you might need to configure your test widget(s) properly.",
					"Please make sure you have at least one AddressBook item available.",
					"Please make sure you have at least one Calendar item available."
				],
				test:function(t){
					t.success(true);
				}
			},
			{
				id:2,
				name:"config info",
				test:function(t){
					if (config._meta.isCustomConfiguration){
						t.success(config._meta);
					}else{
						t.failure("Unconfigured, userAgent: " + window.navigator.userAgent);
					}
				}
			},

			//
			//
			//
			{
				id:100,
				name:"config.validAddressBookItemId - possible value (fullName=null)",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", null);
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					pim.onAddressBookItemsFound = null;
				}
			},
			{
				id:105,
				name:"config.validAddressBookItemId - possible value (fullName=*)",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", "*");
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					pim.onAddressBookItemsFound = null;
				}
			},
			{
				id:110,
				name:"config.validAddressBookItemId - current value",
				test:function(t){
					var val = config.validAddressBookItemId;
					t[val ? "success" : "failure"](val);
				}
			},
			{
				id:120,
				name:"config.validAddressBookItemId - Item is an instance of AddressBookItem?",
				test:function(t){
					var item = Widget.PIM.getAddressBookItem(config.validAddressBookItemId);
					t.assertTrue(item instanceof Widget.PIM.AddressBookItem);
				}
			},
			{
				id:200,
				name:"config.validCalendarItemId - possible value (eventName=null)",
				timeout: 60*1000, // some devices are slooooow E5-00 ;)
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = null;
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					pim.onCalendarItemsFound = null;
				}
			},
			{
				id:205,
				name:"config.validCalendarItemId - possible value (eventName=*)",
				timeout: 60*1000, // some devices are slooooow E5-00 ;)
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = "*";
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					pim.onCalendarItemsFound = null;
				}
			},
			{
				id:210,
				name:"config.validCalendarItemId - current value",
				test:function(t){
					var val = config.validCalendarItemId;
					t[val ? "success" : "failure"](val);
				}
			},
			{
				id:220,
				name:"config.validCalendarItemId - Item is an instance of CalendarItem?",
				test:function(t){
					var item = Widget.PIM.getCalendarItem(config.validCalendarItemId);
					t.assertTrue(item instanceof Widget.PIM.CalendarItem);
				}
			},
//*/
		]
	});

})();<|endoftext|>


<commit_before>const selectors = require('../../../selectors')

describe('Layout', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  describe('Navigation', () => {
    it('should display navigation items', () => {
      cy.get(selectors.nav.contact).should('contain', 'Contacts')
      cy.get(selectors.nav.investment).should('contain', 'Investments')
    })
  })

  describe('Search', () => {
    it('should display search form', () => {
      cy.get('input[type="search"]')
        .should('have.attr', 'placeholder', 'Enter your search term(s)')
        .next()
        .should('match', 'button')
        .and('have.text', 'Search')
    })
  })

  describe('React Colours', () => {
    it('should use the same colour palette as the rest of the site', () => {
      cy.contains('Edit list name')
        .focus()
        .should('have.css', 'outline-color', 'rgb(255, 191, 71)')
    })
  })

  describe('Footer', () => {
    it('should display footer', () => {
      cy.get('footer a').should('have.length', 4)
    })
  })
})
<commit_msg>add extra item to test<commit_after>const selectors = require('../../../selectors')

describe('Layout', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  describe('Navigation', () => {
    it('should display navigation items', () => {
      cy.get(selectors.nav.contact).should('contain', 'Contacts')
      cy.get(selectors.nav.investment).should('contain', 'Investments')
    })
  })

  describe('Search', () => {
    it('should display search form', () => {
      cy.get('input[type="search"]')
        .should('have.attr', 'placeholder', 'Enter your search term(s)')
        .next()
        .should('match', 'button')
        .and('have.text', 'Search')
    })
  })

  describe('React Colours', () => {
    it('should use the same colour palette as the rest of the site', () => {
      cy.contains('Edit list name')
        .focus()
        .should('have.css', 'outline-color', 'rgb(255, 221, 0)')
    })
  })

  describe('Footer', () => {
    it('should display footer', () => {
      cy.get('footer a').should('have.length', 5)
    })
  })
})
<|endoftext|>


<commit_before>$(document).ready(function() {
	$('#group-bi').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.IRL').css({'fill' : 'CCCCCC'});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});

		$('.subunit.GGA').css({"fill" : "FFFFFF"});
		$('.subunit.GGG').css({"fill" : "FFFFFF"});
		$('.subunit.GGS').css({"fill" : "FFFFFF"});
		$('.subunit.JEY').css({"fill" : "FFFFFF"});
		return false;
	});

	$('#island-gbr').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "CCFFCC"});
		$('.subunit.SCT').css({"fill" : "CCFFCC"});
		$('.subunit.WLS').css({"fill" : "CCFFCC"});

		$('.subunit.IRL').css({'fill' : 'CCCCCC'});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});
		return false;
	});

	$('#island-irl').mouseenter(function() {
		$('.subunit.IRL').css({'fill' : 'CCFFCC'});
		$('.subunit.NIR').css({"fill" : "CCFFCC"});

		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});
		return false;
	});

	$('#island-imn').mouseenter(function() {
		$('.subunit.IMN').css({'fill' : 'CCFFCC'});

		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#island-chl').mouseenter(function() {
		$('.subunit.GGA').css({"fill" : "CCFFCC"});
		$('.subunit.GGG').css({"fill" : "CCFFCC"});
		$('.subunit.GGS').css({"fill" : "CCFFCC"});
		$('.subunit.JEY').css({"fill" : "CCFFCC"});

		$('.subunit.IMN').css({'fill' : 'CCCCCC'});
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IRL').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#state-gbr').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "CC3333"});
		$('.subunit.SCT').css({"fill" : "CC3333"});
		$('.subunit.WLS').css({"fill" : "CC3333"});
		$('.subunit.NIR').css({"fill" : "CC3333"});

		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#state-irl').mouseenter(function() {
		$('.subunit.IRL').css({"fill" : "CC3333"});

		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#country-eng').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "FFFF99"});

		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#country-sct').mouseenter(function() {
		$('.subunit.SCT').css({"fill" : "FFFF99"});

		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#country-wls').mouseenter(function() {
		$('.subunit.WLS').css({"fill" : "FFFF99"});

		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#country-nir').mouseenter(function() {
		$('.subunit.NIR').css({"fill" : "FFFF99"});

		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.IMN').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#cd-imn').mouseenter(function() {
		$('.subunit.IMN').css({'fill' : '9999FF'});

		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IRL').css({"fill" : "CCCCCC"});
		$('.subunit.GGA').css({"fill" : "CCCCCC"});
		$('.subunit.GGG').css({"fill" : "CCCCCC"});
		$('.subunit.GGS').css({"fill" : "CCCCCC"});
		$('.subunit.JEY').css({"fill" : "CCCCCC"});

		return false;
	});

	$('#cd-chl').mouseenter(function() {
		$('.subunit.GGA').css({"fill" : "9999FF"});
		$('.subunit.GGG').css({"fill" : "9999FF"});
		$('.subunit.GGS').css({"fill" : "9999FF"});
		$('.subunit.JEY').css({"fill" : "9999FF"});

		$('.subunit.IMN').css({'fill' : 'CCCCCC'});
		$('.subunit.ENG').css({"fill" : "CCCCCC"});
		$('.subunit.SCT').css({"fill" : "CCCCCC"});
		$('.subunit.WLS').css({"fill" : "CCCCCC"});
		$('.subunit.NIR').css({"fill" : "CCCCCC"});
		$('.subunit.IRL').css({"fill" : "CCCCCC"});

		return false;
	});
});
<commit_msg>Fix colours to explicitly use # notation. Chrome/Safari are tolerant of a lack of #, FF is not<commit_after>$(document).ready(function() {
	$('#group-bi').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.IRL').css({'fill' : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});

		$('.subunit.GGA').css({"fill" : "#FFFFFF"});
		$('.subunit.GGG').css({"fill" : "#FFFFFF"});
		$('.subunit.GGS').css({"fill" : "#FFFFFF"});
		$('.subunit.JEY').css({"fill" : "#FFFFFF"});
		return false;
	});

	$('#island-gbr').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "#CCFFCC"});
		$('.subunit.SCT').css({"fill" : "#CCFFCC"});
		$('.subunit.WLS').css({"fill" : "#CCFFCC"});

		$('.subunit.IRL').css({'fill' : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});
		return false;
	});

	$('#island-irl').mouseenter(function() {
		$('.subunit.IRL').css({'fill' : "#CCFFCC"});
		$('.subunit.NIR').css({"fill" : "#CCFFCC"});

		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});
		return false;
	});

	$('#island-imn').mouseenter(function() {
		$('.subunit.IMN').css({'fill' : "#CCFFCC"});

		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#island-chl').mouseenter(function() {
		$('.subunit.GGA').css({"fill" : "#CCFFCC"});
		$('.subunit.GGG').css({"fill" : "#CCFFCC"});
		$('.subunit.GGS').css({"fill" : "#CCFFCC"});
		$('.subunit.JEY').css({"fill" : "#CCFFCC"});

		$('.subunit.IMN').css({'fill' : "#CCCCCC"});
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IRL').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#state-gbr').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "#CC3333"});
		$('.subunit.SCT').css({"fill" : "#CC3333"});
		$('.subunit.WLS').css({"fill" : "#CC3333"});
		$('.subunit.NIR').css({"fill" : "#CC3333"});

		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#state-irl').mouseenter(function() {
		$('.subunit.IRL').css({"fill" : "#CC3333"});

		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#country-eng').mouseenter(function() {
		$('.subunit.ENG').css({"fill" : "#FFFF99"});

		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#country-sct').mouseenter(function() {
		$('.subunit.SCT').css({"fill" : "#FFFF99"});

		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#country-wls').mouseenter(function() {
		$('.subunit.WLS').css({"fill" : "#FFFF99"});

		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#country-nir').mouseenter(function() {
		$('.subunit.NIR').css({"fill" : "#FFFF99"});

		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.IMN').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#cd-imn').mouseenter(function() {
		$('.subunit.IMN').css({'fill' : "#9999FF"});

		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IRL').css({"fill" : "#CCCCCC"});
		$('.subunit.GGA').css({"fill" : "#CCCCCC"});
		$('.subunit.GGG').css({"fill" : "#CCCCCC"});
		$('.subunit.GGS').css({"fill" : "#CCCCCC"});
		$('.subunit.JEY').css({"fill" : "#CCCCCC"});

		return false;
	});

	$('#cd-chl').mouseenter(function() {
		$('.subunit.GGA').css({"fill" : "#9999FF"});
		$('.subunit.GGG').css({"fill" : "#9999FF"});
		$('.subunit.GGS').css({"fill" : "#9999FF"});
		$('.subunit.JEY').css({"fill" : "#9999FF"});

		$('.subunit.IMN').css({'fill' : "#CCCCCC"});
		$('.subunit.ENG').css({"fill" : "#CCCCCC"});
		$('.subunit.SCT').css({"fill" : "#CCCCCC"});
		$('.subunit.WLS').css({"fill" : "#CCCCCC"});
		$('.subunit.NIR').css({"fill" : "#CCCCCC"});
		$('.subunit.IRL').css({"fill" : "#CCCCCC"});

		return false;
	});
});
<|endoftext|>