<commit_before>const SpotNotification = require("../index");

let spot = SpotNotification.SpotNotifier;

spot.on("termination", date => {
    console.log("termination", date);
});
spot.on("termination-cancelled", date => {
    console.log("termination-cancelled", date);
});
spot.on("termination-not-detected", error => {
    console.log("termination-not-detected", error);
});

spot.instanceId()
    .then((id) => {
        console.log("instanceId", id);
        process.exit(0);
    })
    .catch((err) => {
        console.error("instanceId", err);
    });

setTimeout(function () {
    process.exit(1);
}, 20000);<commit_msg>old version<commit_after>var SpotNotification = require("../index");

var spot = SpotNotification.SpotNotifier;

spot.on("termination", date => {
    console.log("termination", date);
});
spot.on("termination-cancelled", date => {
    console.log("termination-cancelled", date);
});
spot.on("termination-not-detected", error => {
    console.log("termination-not-detected", error);
});

spot.instanceId()
    .then((id) => {
        console.log("instanceId", id);
        process.exit(0);
    })
    .catch((err) => {
        console.error("instanceId", err);
    });

setTimeout(function () {
    process.exit(1);
}, 20000);<|endoftext|>


<commit_before>module("WCAG 2.0 Compliance");

(function(){

var checkElementText = function(element){
    var hasText = false;
    for (var i = 0; i < element.childNodes.length; i++) {
        if ($(element.childNodes[i]).clone().find("*").remove().end().text()) {
            return true;
        } else if (element.childNodes[i].firstChild) {
            if (checkElementText()){
                hasText = true;
            }
        }
    }
    return hasText;
}

var checkChildElements = function(element, page, template){
    if (element.firstChild) { // check for children elements
        var child = element.firstChild;

        while (child) { // check child elements
            if (child.nodeType === 8 && child.parentNode.nodeName.toLowerCase() === "div") { // if comment node is in a div its probably a javascript template
                var trimPathTemplate = document.createElement('div');
                trimPathTemplate.innerHTML = child.data;
                checkChildElements(trimPathTemplate, page, true);
            }
            if (child.nodeType === 1) { // if html element
                var previousImg = false;
                if (child.previousSibling && $(child).prev().context.nodeName.toLowerCase() === "img") {
                    previousImg = true;
                }

                var errorString = "";
                var pass = true;
                var testNodeName = child.nodeName.toLowerCase();

                var hasAlt = false;
                var hasTitle = false;
                var hasText = false;
                var hasChild = false;
                var hasElements = false;

                if ($(child).attr("alt"))
                    hasAlt = true;
                if ($(child).attr("title"))
                    hasTitle = true;
                if ($(child).clone().find("*").remove().end().text())
                    hasText = true;
                if (child.firstChild)
                    hasChild = true;

                if (testNodeName === "img"){
                    errorString = "IMG tag missing ";
                    if (!hasAlt && !previousImg) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "applet"){
                    errorString = "APPLET tag missing ";
                    if (!hasAlt) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "object"){
                    errorString = "OBJECT tag missing ";
                    if (!hasChild) {
                        errorString = errorString + "body, ";
                        pass = false;
                    }
                } else if (testNodeName === "area"){
                    errorString = "AREA tag missing ";
                    if (!hasAlt) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "abbr"){
                    errorString = "ABBR tag missing ";
                    if (!hasTitle) {
                        errorString = errorString + "TITLE attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "a"){
                    var hasChildText = false;
                    for (var i = 0; i < child.childNodes.length; i++) {
                        if (child.childNodes[i].nodeName.toLowerCase() === "img" && $(child.childNodes[i]).attr("alt")) {
                            hasChildText = true;
                        } else if (checkElementText(child.childNodes[i])) {
                            hasChildText = true;
                        }
                    }
                    errorString = "A tag missing ";
                    if (!hasText && !hasChildText) {
                        errorString = errorString + "link text or IMG ALT attribute, ";
                        pass = false;
                    }
                }

                if (!pass) {
                    errorString = errorString + " String: " + $(child).clone().wrapAll("<div/>").parent().html();
                    ok(false, "Page: " + page + ", Error: " + errorString);
                }

                checkChildElements(child, page, template);
            }
        child = child.nextSibling;
        }
    }
};

/**
 * Check HTML pages and test for WCAG compliance
 */
var testInternationalisation = function(){
    var pageArray = ["/dev/403.html",
        "/dev/404.html",
        "/dev/500.html",
        "/dev/account_preferences.html",
        "/dev/acknowledgements.html",
        "/dev/content_profile.html",
        "/dev/create_new_account.html",
        "/dev/directory.html",
        "/dev/group_edit.html",
        "/dev/inbox.html",
        "/dev/index.html",
        "/dev/logout.html",
        "/dev/my_sakai.html",
        "/dev/people.html",
        "/dev/profile_edit.html",
        "/dev/search.html",
        "/dev/search_content.html",
        "/dev/search_groups.html",
        "/dev/search_people.html",
        "/dev/show.html",
        "/dev/s23/s23_site.html"
    ];

    for (var i in Widgets.widgets) {
        if (Widgets.widgets.hasOwnProperty(i) && Widgets.widgets[i].url) {
            pageArray.push(Widgets.widgets[i].url);
        }
    }

    for (var i = 0; i < pageArray.length; i++) {
        var url = pageArray[i];
        $.ajax({
            url: url,
            async: false,
            success: function(data){
                var div = document.createElement('div');
                div.innerHTML = data;
                checkChildElements(div, url, false);
            }
        });
    }
};

/**
 * Run a test
 */
test("Test for WCAG 2.0 Compliance - 1.1.1 Non-text Content / Text Alternatives", function(){
    testInternationalisation();
});

})();<commit_msg>SAKIII-279 fixing img tag check in unit test<commit_after>module("WCAG 2.0 Compliance");

(function(){

var checkElementText = function(element){
    var hasText = false;
    for (var i = 0; i < element.childNodes.length; i++) {
        if ($(element.childNodes[i]).clone().find("*").remove().end().text()) {
            return true;
        } else if (element.childNodes[i].firstChild) {
            if (checkElementText()){
                hasText = true;
            }
        }
    }
    return hasText;
}

var checkChildElements = function(element, page, template){
    if (element.firstChild) { // check for children elements
        var child = element.firstChild;

        while (child) { // check child elements
            if (child.nodeType === 8 && child.parentNode.nodeName.toLowerCase() === "div") { // if comment node is in a div its probably a javascript template
                var trimPathTemplate = document.createElement('div');
                trimPathTemplate.innerHTML = child.data;
                checkChildElements(trimPathTemplate, page, true);
            }
            if (child.nodeType === 1) { // if html element
                var previousImg = false;
                if (child.previousElementSibling && child.previousElementSibling.nodeName.toLowerCase() === "img") {
                    previousImg = true;
                }

                var errorString = "";
                var pass = true;
                var testNodeName = child.nodeName.toLowerCase();

                var hasAlt = false;
                var hasTitle = false;
                var hasText = false;
                var hasChild = false;
                var hasElements = false;

                if ($(child).attr("alt"))
                    hasAlt = true;
                if ($(child).attr("title"))
                    hasTitle = true;
                if ($(child).clone().find("*").remove().end().text())
                    hasText = true;
                if (child.firstChild)
                    hasChild = true;

                if (testNodeName === "img"){
                    errorString = "IMG tag missing ";
                    if (!hasAlt && !previousImg) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "applet"){
                    errorString = "APPLET tag missing ";
                    if (!hasAlt) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "object"){
                    errorString = "OBJECT tag missing ";
                    if (!hasChild) {
                        errorString = errorString + "body, ";
                        pass = false;
                    }
                } else if (testNodeName === "area"){
                    errorString = "AREA tag missing ";
                    if (!hasAlt) {
                        errorString = errorString + "ALT attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "abbr"){
                    errorString = "ABBR tag missing ";
                    if (!hasTitle) {
                        errorString = errorString + "TITLE attribute, ";
                        pass = false;
                    }
                } else if (testNodeName === "a"){
                    var hasChildText = false;
                    for (var i = 0; i < child.childNodes.length; i++) {
                        if (child.childNodes[i].nodeName.toLowerCase() === "img" && $(child.childNodes[i]).attr("alt")) {
                            hasChildText = true;
                        } else if (checkElementText(child.childNodes[i])) {
                            hasChildText = true;
                        }
                    }
                    errorString = "A tag missing ";
                    if (!hasText && !hasChildText) {
                        errorString = errorString + "link text or IMG ALT attribute, ";
                        pass = false;
                    }
                }

                if (!pass) {
                    errorString = errorString + " String: " + $(child).clone().wrapAll("<div/>").parent().html();
                    ok(false, "Page: " + page + ", Error: " + errorString);
                }

                checkChildElements(child, page, template);
            }
        child = child.nextSibling;
        }
    }
};

/**
 * Check HTML pages and test for WCAG compliance
 */
var testInternationalisation = function(){
    var pageArray = ["/dev/403.html",
        "/dev/404.html",
        "/dev/500.html",
        "/dev/account_preferences.html",
        "/dev/acknowledgements.html",
        "/dev/content_profile.html",
        "/dev/create_new_account.html",
        "/dev/directory.html",
        "/dev/group_edit.html",
        "/dev/inbox.html",
        "/dev/index.html",
        "/dev/logout.html",
        "/dev/my_sakai.html",
        "/dev/people.html",
        "/dev/profile_edit.html",
        "/dev/search.html",
        "/dev/search_content.html",
        "/dev/search_groups.html",
        "/dev/search_people.html",
        "/dev/show.html",
        "/dev/s23/s23_site.html"
    ];

    for (var i in Widgets.widgets) {
        if (Widgets.widgets.hasOwnProperty(i) && Widgets.widgets[i].url) {
            pageArray.push(Widgets.widgets[i].url);
        }
    }

    for (var i = 0; i < pageArray.length; i++) {
        var url = pageArray[i];
        $.ajax({
            url: url,
            async: false,
            success: function(data){
                var div = document.createElement('div');
                div.innerHTML = data;
                checkChildElements(div, url, false);
            }
        });
    }
};

/**
 * Run a test
 */
test("Test for WCAG 2.0 Compliance - 1.1.1 Non-text Content / Text Alternatives", function(){
    testInternationalisation();
});

})();<|endoftext|>


<commit_before>var expect = require("chai").use(require('chai-fs')).expect

var path = require('path')
var _ = require('lodash')
var rimraf = require('rimraf')
var bowman = require('../')

var SRC = path.resolve(__dirname, './src');
var DEST = path.join(SRC, '.bowman.json');

describe("test", function(){
  before(function(done){
    rimraf(DEST,done)
  })

  it("should not have a bowman file", function(){
    expect(DEST).to.not.be.a.path();
  })

  it("should automatically create a bowman file", function(){
    return bowman({update: false, cwd: SRC})
      .then(function(bow){
        return expect(DEST).to.be.a.file();
      })
  })

  it("should read a bower file", function(){
    return bowman({update: false, cwd: SRC})
  })

  it("should update a bowman file", function(){
    return bowman({update: true, cwd: SRC})
      .then(function(bow){
        return expect(DEST).to.be.a.file();
      })
  })
})<commit_msg>test timeout<commit_after>var expect = require("chai").use(require('chai-fs')).expect

var path = require('path')
var _ = require('lodash')
var rimraf = require('rimraf')
var bowman = require('../')

var SRC = path.resolve(__dirname, './src');
var DEST = path.join(SRC, '.bowman.json');

describe("test", function(){
  before(function(done){
    rimraf(DEST,done)
  })

  it("should not have a bowman file", function(){
    expect(DEST).to.not.be.a.path();
  })

  it("should automatically create a bowman file", function(){
    this.timeout(4000);
    return bowman({update: false, cwd: SRC})
      .then(function(bow){
        return expect(DEST).to.be.a.file();
      })
  })

  it("should read a bower file", function(){
    return bowman({update: false, cwd: SRC})
  })

  it("should update a bowman file", function(){
    return bowman({update: true, cwd: SRC})
      .then(function(bow){
        return expect(DEST).to.be.a.file();
      })
  })

  it("should fail if plugins are missing")
})<|endoftext|>


<commit_before>var newBlock = require('./new-block.js');

/**
 * lost-masonry-wrap: Creates a wrapping element for working with JS Masonry
 * libraries like Isotope. Assigns a negative margin on each side of this
 * wrapping element.
 *
 * @param {string} [flex|no-flex] - Determines whether this element should
 *   use Flexbox or not.
 *
 * @param {length} [gutter] - How large the gutter involved is, typically
 *   this won't be adjusted and will inherit settings.gutter, but it's made
 *   available if you want your masonry grid to have a special gutter, it
 *   should match your masonry-column's gutter.
 *
 * @example
 *   section {
 *     lost-masonry-wrap: no-flex;
 *   }
 *   div {
 *     lost-masonry-column: 1/3;
 *   }
 */
module.exports = function lostMasonryWrapDecl(css, settings) {
  css.walkDecls('lost-masonry-wrap', function(decl) {
    var declArr = [],
        lostMasonryWrap,
        lostMasonryWrapFlexbox = settings.flexbox,
        lostMasonryWrapGutter = settings.gutter,
        lostMasonryWrapGutterUnit;

    function cloneAllBefore(props) {
      Object.keys(props).forEach(function traverseProps(prop) {
        decl.cloneBefore({
          prop: prop,
          value: props[prop]
        });
      });
    }

    declArr = decl.value.split(' ');

    if (declArr[0] !== undefined && declArr[0] == 'flex' || declArr[0] == 'no-flex') {
      lostMasonryWrapFlexbox = declArr[0];
    }

    if (declArr.indexOf('flex') !== -1) {
      lostMasonryWrapFlexbox = 'flex';
    }

    if (declArr.indexOf('no-flex') !== -1) {
      lostMasonryWrapFlexbox = 'no-flex';
    }

    if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) {
      lostMasonryWrapGutter = declArr[1];
    }

    decl.parent.nodes.forEach(function (decl) {
      if (decl.prop == 'lost-masonry-wrap-flexbox') {
        if (decl.value == 'flex') {
          lostMasonryWrapFlexbox = 'flex';
        }

        decl.remove();
      }
    });

    decl.parent.nodes.forEach(function (decl) {
      if (decl.prop == 'lost-masonry-wrap-gutter') {
        lostMasonryWrap = decl.value;

        decl.remove();
      }
    });

    if (lostMasonryWrapFlexbox !== 'flex') {
      newBlock(
        decl,
        ':after',
        ['content', 'display', 'clear'],
        ['\'\'', 'table', 'both']
      );

      newBlock(
        decl,
        ':before',
        ['content', 'display'],
        ['\'\'', 'table']
      );
    } else {
      decl.cloneBefore({
        prop: 'display',
        value: 'flex'
      });

      decl.cloneBefore({
        prop: 'flex-flow',
        value: 'row wrap'
      });
    }

    lostMasonryWrapGutterUnit = lostMasonryWrapGutter.match(/\D/g).join('');

    cloneAllBefore({
      'margin-left': (parseInt(lostMasonryWrapGutter) / -2) + lostMasonryWrapGutterUnit,
      'margin-right': (parseInt(lostMasonryWrapGutter) / -2) + lostMasonryWrapGutterUnit
    });

    decl.remove();
  });
};
<commit_msg>Updates lostMasonryWrap for ESLint<commit_after>var newBlock = require('./new-block.js');

/**
 * lost-masonry-wrap: Creates a wrapping element for working with JS Masonry
 * libraries like Isotope. Assigns a negative margin on each side of this
 * wrapping element.
 *
 * @param {string} [flex|no-flex] - Determines whether this element should
 *   use Flexbox or not.
 *
 * @param {length} [gutter] - How large the gutter involved is, typically
 *   this won't be adjusted and will inherit settings.gutter, but it's made
 *   available if you want your masonry grid to have a special gutter, it
 *   should match your masonry-column's gutter.
 *
 * @example
 *   section {
 *     lost-masonry-wrap: no-flex;
 *   }
 *   div {
 *     lost-masonry-column: 1/3;
 *   }
 */
module.exports = function lostMasonryWrapDecl(css, settings) {
  css.walkDecls('lost-masonry-wrap', function lostMasonryWrapDeclFunction(decl) {
    var declArr = [];
    var lostMasonryWrap;
    var lostMasonryWrapFlexbox = settings.flexbox;
    var lostMasonryWrapGutter = settings.gutter;
    var lostMasonryWrapGutterUnit;

    function cloneAllBefore(props) {
      Object.keys(props).forEach(function traverseProps(prop) {
        decl.cloneBefore({
          prop: prop,
          value: props[prop]
        });
      });
    }

    declArr = decl.value.split(' ');

    if ((declArr[0] !== undefined && declArr[0] === 'flex') || declArr[0] === 'no-flex') {
      lostMasonryWrapFlexbox = declArr[0];
    }

    if (declArr.indexOf('flex') !== -1) {
      lostMasonryWrapFlexbox = 'flex';
    }

    if (declArr.indexOf('no-flex') !== -1) {
      lostMasonryWrapFlexbox = 'no-flex';
    }

    if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) {
      lostMasonryWrapGutter = declArr[1];
    }

    decl.parent.nodes.forEach(function lostMasonryWrapFlexboxFunction(declaration) {
      if (declaration.prop === 'lost-masonry-wrap-flexbox') {
        if (declaration.value === 'flex') {
          lostMasonryWrapFlexbox = 'flex';
        }

        declaration.remove();
      }
    });

    decl.parent.nodes.forEach(function lostMasonryWrapFunction(declaration) {
      if (declaration.prop === 'lost-masonry-wrap-gutter') {
        lostMasonryWrap = declaration.value;

        declaration.remove();
      }
    });

    if (lostMasonryWrapFlexbox !== 'flex') {
      newBlock(
        decl,
        ':after',
        ['content', 'display', 'clear'],
        ['\'\'', 'table', 'both']
      );

      newBlock(
        decl,
        ':before',
        ['content', 'display'],
        ['\'\'', 'table']
      );
    } else {
      decl.cloneBefore({
        prop: 'display',
        value: 'flex'
      });

      decl.cloneBefore({
        prop: 'flex-flow',
        value: 'row wrap'
      });
    }

    lostMasonryWrapGutterUnit = lostMasonryWrapGutter.match(/\D/g).join('');

    cloneAllBefore({
      'margin-left': (parseInt(lostMasonryWrapGutter, 10) / -2) + lostMasonryWrapGutterUnit,
      'margin-right': (parseInt(lostMasonryWrapGutter, 10) / -2) + lostMasonryWrapGutterUnit
    });

    decl.remove();
  });
};
<|endoftext|>


<commit_before>var expect = chai.expect;
var debug = false;

function MockPort() {
  this.postMessage = sinon.spy();
}

MockPort.prototype.recvmock = function(data) {
  this.onmessage({ data: promiseConnection.extend({ _pc: true } , data) });
};

MockPort.prototype.onmessage = function() {};

describe('promiseConnection', function() {
  beforeEach(function() {
    expect(window.Promise).to.be.a('function');
    promiseConnection.Promise = window.Promise;
  });

  it('should define promiseConnection', function() {
    expect(promiseConnection).to.be.ok;
  });

  describe(".Connection()", function() {
    var Connection = promiseConnection.Connection;

    it('is a function', function() {
      expect(Connection).to.be.a('function');
    });

    it('throws an error when Promise is not defined', function() {
      expect(function() {
        delete promiseConnection.Promise;
        new Connection(new MockPort(), {})
      }).to.throw('promiseConnection.Promise must be defined');
    });

    describe('opts: { autoConnect: false }', function() {
      var port, local, options, connection;
      beforeEach(function() {
        port = new MockPort();
        local = {
        };
        options = {
          autoConnect: false
        };
        connection = new Connection(port, local, options)
      });

      it('does not send any message on creation with autoConnect: false', function() {
        expect(port.postMessage.called).to.be.false;
      });

      describe('.connect()', function() {
        beforeEach(function() {
          // the promise returned by connect should always equal "connected"
          expect(connection.connect()).to.equal(connection.connected);
        });

        it('sends a connect message when you call .connect()', function() {
          expect(port.postMessage.callCount).to.equal(1);
          var messageArgs = port.postMessage.args[0];
          expect(messageArgs[0]._id).to.equal('connect');
          expect(messageArgs[0]._type).to.equal('connect');
        });

        it('resolves connection when remote responds', function() {
          expect(connection._connecting).to.be.ok;
          expect(connection._connected).to.not.exist;
          port.recvmock({ _type: 'resolve', _id: 'connect', value: true })
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;
          });
        });

        it('resends connection packet when you call .connect() a second time', function() {
          // the promise returned by connect should always equal "connected"
          var originalArgs = port.postMessage.args[0];
          port.postMessage.reset();

          expect(connection.connect()).to.equal(connection.connected);
          expect(port.postMessage.callCount).to.equal(1);
          expect(port.postMessage.args[0]).to.deep.equal(originalArgs);
        });
      });

      describe('incoming connect', function() {
        beforeEach(function() {
          expect(connection._connecting).to.be.not.ok
          port.recvmock({ _type: 'connect', _id: 'connect' });
          // let promise resolvers tick before moving on to tests
          return Promise.resolve();
        });

        it('sends its own connection', function() {
          expect(port.postMessage.callCount).to.equal(1);
          var data = port.postMessage.args[0][0];
          expect(data._type).to.equal('connect');
        });

        it('becomes connected when remote replies', function() {
          expect(connection._connecting).to.be.ok;
          expect(connection._connected).to.not.exist;
          port.postMessage.reset();
          port.recvmock({ _type: 'resolve', _id: 'connect', value: true })
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;

            return Promise.resolve();
          }).then(function() {
            // and make sure it tells the other side it's connected
            expect(port.postMessage.callCount).to.equal(1);
            var data = port.postMessage.args[0][0];
            expect(data._type).to.equal('resolve');
            expect(data._id).to.equal('connect');

          });
        });
      });

    });

    describe('opts: {}', function() {
      var port, local, options, connection;
      beforeEach(function() {
        port = new MockPort();
        local = {};
        options = {};
        connection = new Connection(port, local, options)
      });

      it('sends a connect message immediately', function() {
        expect(port.postMessage.callCount).to.equal(1);
        var messageArgs = port.postMessage.args[0];
        expect(messageArgs[0]._id).to.equal('connect');
        expect(messageArgs[0]._type).to.equal('connect');
      });

      describe('incoming connect', function() {
        beforeEach(function() {
          port.postMessage.reset();
          expect(connection._connecting).to.be.ok;
          port.recvmock({ _type: 'connect', _id: 'connect' });
          // let promise resolvers tick before moving on to tests
          return Promise.resolve();
        });

        it('does not resend its own connection', function() {
          expect(port.postMessage.callCount).to.equal(0);
        });

        it('became connected', function() {
          // this became connected because it had already sent a "connect"
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;
            return Promise.resolve();
          }).then(function() {
            // and make sure it tells the other side it's connected
            expect(port.postMessage.callCount).to.equal(1);
            var data = port.postMessage.args[0][0];
            expect(data._type).to.equal('resolve');
            expect(data._id).to.equal('connect');
          });
        });
      });
    });

    describe('on a MessageChannel', function() {
      var ports, local, remote;
      beforeEach(function() {
        ports = new MessageChannel();
        options = {};
        local = new Connection(ports.port1, {}, { debug: debug });
        remote = new Connection(ports.port2, {}, { debug: debug });

        return local.connected;
      });
      it('conneted', function() {
        expect(remote._connected).to.be.ok;
        expect(local._connected).to.be.ok;
      });

      it('rejects an undefined method invoke', function() {
        return local.invoke('noMethod').then(function() {
          throw new Error('unexpected success');
        }, function(e) {
          expect(e.message).to.equal('PromiseConnection: Unknown method noMethod');
          expect(e.number).to.equal(undefined);
        });
      });

      it('calls remote method', function() {
        remote.local.method = sinon.spy(function() {
          return Math.random();
        });
        var args = [1, 2, 3];
        return local.invoke('method', args)
          .then(function(result) {
            expect(remote.local.method.callCount).to.equal(1);
            expect(result).to.equal(remote.local.method.returnValues[0]);
            expect(remote.local.method.args[0]).to.deep.equal(args);
          });
      });

      describe('remote promises', function() {
        var promise, resolve, reject, result;
        beforeEach(function() {
          promise = new Promise(function(res, rej) {
            resolve = res;
            reject = rej;
          });
          var remoteCalled;
          var gotRemote = new Promise(function(resolve) {
            remoteCalled = resolve
          });
          remote.local.promise = sinon.spy(function() {
            remoteCalled();
            return promise;
          });
          result = local.invoke('promise');

          return gotRemote;
        });

        it('does not resolve or reject', function() {
          var invalid = false;
          function invalidate() { invalid = true; }
          // should not reply yet
          result.then(invalidate, invalidate);
          expect(remote.local.promise.callCount).to.equal(1);
          return Promise.resolve()
            .then(function() {
              expect(invalid).to.be.false;
            });
        });
        it('resolves on resolve', function() {
          var obj = { test: true };
          resolve(obj);
          return result.then(function(result) {
            expect(result).to.deep.equal(obj)
          });
        });
        it('rejects on reject', function() {
          var obj = { test: true };
          reject(obj);
          return result.then(function() {
            throw new Error('unexpected resolve')
          }, function(result) {
            expect(result).to.deep.equal(obj)
          });
        });
      });

    });
  });

  describe('.extend()', function() {
    var fix1 = { fix1: true, fix2: false };
    var fix2 = { fix2: true };
    var expected = { fix1: true, fix2: true };

    it('copies keys from multiple objects into one', function() {
      var dest = {};
      var result = promiseConnection.extend(dest, fix1, fix2);
      expect(result).to.deep.equal(expected);
      expect(result).to.equal(dest);
    });
  });

});
<commit_msg>add silly MessageChannel mock for non supported browsers<commit_after>var expect = chai.expect;
var debug = false;

// fake MessageChannel for firefox or other non-chromy tests
if (!window.MessageChannel) {
  window.MessageChannel = function() {
    var port1 = new MockPort();
    var port2 = new MockPort();
    port1.postMessage = function(data) {
      setTimeout(function() {
        port2.onmessage({ data: data });
      });
    };
    port2.postMessage = function(data) {
      setTimeout(function() {
        port1.onmessage({ data: data });
      });
    };
    return {
      port1: port1,
      port2: port2
    };
  }
}

function MockPort() {
  this.postMessage = sinon.spy();
}

MockPort.prototype.recvmock = function(data) {
  this.onmessage({ data: promiseConnection.extend({ _pc: true } , data) });
};

MockPort.prototype.onmessage = function() {};

describe('promiseConnection', function() {
  beforeEach(function() {
    expect(window.Promise).to.be.a('function');
    promiseConnection.Promise = window.Promise;
  });

  it('should define promiseConnection', function() {
    expect(promiseConnection).to.be.ok;
  });

  describe(".Connection()", function() {
    var Connection = promiseConnection.Connection;

    it('is a function', function() {
      expect(Connection).to.be.a('function');
    });

    it('throws an error when Promise is not defined', function() {
      expect(function() {
        delete promiseConnection.Promise;
        new Connection(new MockPort(), {})
      }).to.throw('promiseConnection.Promise must be defined');
    });

    describe('opts: { autoConnect: false }', function() {
      var port, local, options, connection;
      beforeEach(function() {
        port = new MockPort();
        local = {
        };
        options = {
          autoConnect: false
        };
        connection = new Connection(port, local, options)
      });

      it('does not send any message on creation with autoConnect: false', function() {
        expect(port.postMessage.called).to.be.false;
      });

      describe('.connect()', function() {
        beforeEach(function() {
          // the promise returned by connect should always equal "connected"
          expect(connection.connect()).to.equal(connection.connected);
        });

        it('sends a connect message when you call .connect()', function() {
          expect(port.postMessage.callCount).to.equal(1);
          var messageArgs = port.postMessage.args[0];
          expect(messageArgs[0]._id).to.equal('connect');
          expect(messageArgs[0]._type).to.equal('connect');
        });

        it('resolves connection when remote responds', function() {
          expect(connection._connecting).to.be.ok;
          expect(connection._connected).to.not.exist;
          port.recvmock({ _type: 'resolve', _id: 'connect', value: true })
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;
          });
        });

        it('resends connection packet when you call .connect() a second time', function() {
          // the promise returned by connect should always equal "connected"
          var originalArgs = port.postMessage.args[0];
          port.postMessage.reset();

          expect(connection.connect()).to.equal(connection.connected);
          expect(port.postMessage.callCount).to.equal(1);
          expect(port.postMessage.args[0]).to.deep.equal(originalArgs);
        });
      });

      describe('incoming connect', function() {
        beforeEach(function() {
          expect(connection._connecting).to.be.not.ok
          port.recvmock({ _type: 'connect', _id: 'connect' });
          // let promise resolvers tick before moving on to tests
          return Promise.resolve();
        });

        it('sends its own connection', function() {
          expect(port.postMessage.callCount).to.equal(1);
          var data = port.postMessage.args[0][0];
          expect(data._type).to.equal('connect');
        });

        it('becomes connected when remote replies', function() {
          expect(connection._connecting).to.be.ok;
          expect(connection._connected).to.not.exist;
          port.postMessage.reset();
          port.recvmock({ _type: 'resolve', _id: 'connect', value: true })
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;

            return Promise.resolve();
          }).then(function() {
            // and make sure it tells the other side it's connected
            expect(port.postMessage.callCount).to.equal(1);
            var data = port.postMessage.args[0][0];
            expect(data._type).to.equal('resolve');
            expect(data._id).to.equal('connect');

          });
        });
      });

    });

    describe('opts: {}', function() {
      var port, local, options, connection;
      beforeEach(function() {
        port = new MockPort();
        local = {};
        options = {};
        connection = new Connection(port, local, options)
      });

      it('sends a connect message immediately', function() {
        expect(port.postMessage.callCount).to.equal(1);
        var messageArgs = port.postMessage.args[0];
        expect(messageArgs[0]._id).to.equal('connect');
        expect(messageArgs[0]._type).to.equal('connect');
      });

      describe('incoming connect', function() {
        beforeEach(function() {
          port.postMessage.reset();
          expect(connection._connecting).to.be.ok;
          port.recvmock({ _type: 'connect', _id: 'connect' });
          // let promise resolvers tick before moving on to tests
          return Promise.resolve();
        });

        it('does not resend its own connection', function() {
          expect(port.postMessage.callCount).to.equal(0);
        });

        it('became connected', function() {
          // this became connected because it had already sent a "connect"
          return connection.connected.then(function() {
            expect(connection._connecting).to.not.exist;
            expect(connection._connected).to.be.ok;
            return Promise.resolve();
          }).then(function() {
            // and make sure it tells the other side it's connected
            expect(port.postMessage.callCount).to.equal(1);
            var data = port.postMessage.args[0][0];
            expect(data._type).to.equal('resolve');
            expect(data._id).to.equal('connect');
          });
        });
      });
    });

    describe('on a MessageChannel', function() {
      var ports, local, remote;
      beforeEach(function() {
        ports = new MessageChannel();
        options = {};
        local = new Connection(ports.port1, {}, { debug: debug });
        remote = new Connection(ports.port2, {}, { debug: debug });

        return local.connected;
      });
      it('conneted', function() {
        expect(remote._connected).to.be.ok;
        expect(local._connected).to.be.ok;
      });

      it('rejects an undefined method invoke', function() {
        return local.invoke('noMethod').then(function() {
          throw new Error('unexpected success');
        }, function(e) {
          expect(e.message).to.equal('PromiseConnection: Unknown method noMethod');
          expect(e.number).to.equal(undefined);
        });
      });

      it('calls remote method', function() {
        remote.local.method = sinon.spy(function() {
          return Math.random();
        });
        var args = [1, 2, 3];
        return local.invoke('method', args)
          .then(function(result) {
            expect(remote.local.method.callCount).to.equal(1);
            expect(result).to.equal(remote.local.method.returnValues[0]);
            expect(remote.local.method.args[0]).to.deep.equal(args);
          });
      });

      describe('remote promises', function() {
        var promise, resolve, reject, result;
        beforeEach(function() {
          promise = new Promise(function(res, rej) {
            resolve = res;
            reject = rej;
          });
          var remoteCalled;
          var gotRemote = new Promise(function(resolve) {
            remoteCalled = resolve
          });
          remote.local.promise = sinon.spy(function() {
            remoteCalled();
            return promise;
          });
          result = local.invoke('promise');

          return gotRemote;
        });

        it('does not resolve or reject', function() {
          var invalid = false;
          function invalidate() { invalid = true; }
          // should not reply yet
          result.then(invalidate, invalidate);
          expect(remote.local.promise.callCount).to.equal(1);
          return Promise.resolve()
            .then(function() {
              expect(invalid).to.be.false;
            });
        });
        it('resolves on resolve', function() {
          var obj = { test: true };
          resolve(obj);
          return result.then(function(result) {
            expect(result).to.deep.equal(obj)
          });
        });
        it('rejects on reject', function() {
          var obj = { test: true };
          reject(obj);
          return result.then(function() {
            throw new Error('unexpected resolve')
          }, function(result) {
            expect(result).to.deep.equal(obj)
          });
        });
      });

    });
  });

  describe('.extend()', function() {
    var fix1 = { fix1: true, fix2: false };
    var fix2 = { fix2: true };
    var expected = { fix1: true, fix2: true };

    it('copies keys from multiple objects into one', function() {
      var dest = {};
      var result = promiseConnection.extend(dest, fix1, fix2);
      expect(result).to.deep.equal(expected);
      expect(result).to.equal(dest);
    });
  });

});
<|endoftext|>


<commit_before>(function(){

    xtag.register('widget-DAQ', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString, option, title, deckWrap;

                this.width = this.offsetWidth;
                this.height = window.innerHeight*0.6;
                this.showing = 0;

                //get the DAQ structure
                XHR('http://' + this.MIDAS + '/?cmd=jcopy&odb=/DAQ&encoding=json-nokeys',
                    function(res){
                        this.buildDAQ(res);
                    }.bind(this),
                    'application/json');

                //build DOM
                this.navBlock = document.createElement('div');
                this.navBlock.setAttribute('class', 'DAQnav');
                this.appendChild(this.navBlock);

                title = document.createElement('h1');
                title.innerHTML = 'DAQ';
                this.navBlock.appendChild(title);

                this.cardNav = document.createElement('select');
                this.cardNav.setAttribute('id', 'DAQnav')
                this.cardNav.setAttribute('class', 'stdin');
                this.cardNav.onchange = function(){
                    var targetIndex = parseInt(selected('DAQnav'), 10);
                    document.getElementById('DAQdeck').shuffleTo(targetIndex);
                    this.writeCollectorTooltip(-1);
                    this.showing = targetIndex;
                }.bind(this)
                this.navBlock.appendChild(this.cardNav);

                option = document.createElement('option');
                option.value = 0;
                option.innerHTML = 'Master'
                this.cardNav.appendChild(option);

                deckWrap = document.createElement('div');
                this.appendChild(deckWrap);

                xString = '<x-deck id="DAQdeck" selected-index=0>';
                xString += '<x-card id="DAQmasterCard"></x-card></x-deck>';
                xtag.innerHTML(deckWrap, xString);
                this.nCards = 1

                this.masterBlock = document.createElement('div');
                this.masterBlock.setAttribute('class', 'DAQheadNode');
                document.getElementById('DAQmasterCard').appendChild(this.masterBlock);

                this.collectorBlock = document.createElement('div');
                this.collectorBlock.setAttribute('id', 'collectorBlock');
                document.getElementById('DAQmasterCard').appendChild(this.collectorBlock);

                ////////////////////////////
                //Kinetic.js setup
                ////////////////////////////

                //indices for these arrays correspond to the x-card index on display
                this.stage = [];
                this.mainLayer = [];
                this.scaleLayer = [];
                this.tooltipLayer = [];
                this.TTbkg = [];
                this.text = [];
            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'buildDAQ' : function(response){
                var data = JSON.parse(response),
                    i, j, k, option,
                    collectorGutter = this.width*0.02,
                    collectorWidth = (this.width - collectorGutter*16) / 16,
                    xLength = collectorGutter/2,
                    xLeft, xRight, M, S, C;

                this.collectors = [];
                this.digitizers = [];
                this.collectorCells = [];
                this.localMSC = [];

                //determine what collectors are present and instantiate x-cards for each one
                for(i=0; i<16; i++){
                    this.collectors[i] = data.hosts['collector0x' + i.toString(16)];

                    if(this.collectors[i]){
                        document.getElementById('DAQdeck').innerHTML += '<x-card id="collector'+i+'">

</x-card>';
                        option = document.createElement('option');
                        option.value = this.nCards;
                        option.innerHTML = 'Collector 0x' + i.toString(16).toUpperCase();
                        this.cardNav.appendChild(option);
                        this.nCards++;

                    }
                }

                //now that the xdeck is built, paint master canvas:
                //collectors:
                this.setupKinetic('collectorBlock');
                for(i=0; i<16; i++){
                    if(this.collectors[i]){
                        this.collectorCells[i] = new Kinetic.Rect({
                            x:collectorGutter/2 + i*this.width/16,
                            y:this.height*0.6,
                            width: collectorWidth,
                            height:this.height*0.2,
                            fill:'#555555',
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.collectorCells[i].on('click', this.clickCollector.bind(this, i));
                        this.collectorCells[i].on('mousemove', this.moveTooltip.bind(this) );
                        this.collectorCells[i].on('mouseover', this.writeCollectorTooltip.bind(this, i) );
                        this.collectorCells[i].on('mouseout', this.writeCollectorTooltip.bind(this, -1));
                        this.mainLayer[0].add(this.collectorCells[i]);

                        this.localMSC[i] = []
                    } else{
                        //terminate loose cord with red x
                        xLeft = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        xRight = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        this.mainLayer[0].add(xLeft);
                        this.mainLayer[0].add(xRight);
                    }
                }

                //cabling:
                this.masterCables = [[],[],[],[]]; //1-to-4 cables: outer index counts master port, inner index counts collector
                for(i=0; i<4; i++){
                    this.masterCables[i][0] = new Kinetic.Line({
                        points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                        stroke: '#000000',
                        strokeWidth: 4
                    });
                    this.mainLayer[0].add(this.masterCables[i][0]);
                    this.masterCables[i][0].moveToBottom();
                    for(j=1; j<5; j++){
                        this.masterCables[i][j] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*i+j-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[0].add(this.masterCables[i][j]);
                        this.masterCables[i][j].moveToBottom();
                    }
                }
                this.mainLayer[0].draw();

                //and again for each collector card
                this.digitizerCells = [];
                this.collectorCables = [];
                for(i=0; i<16; i++){
                    this.digitizerCells[i] = [];

                    if(!this.collectors[i]) continue;

                    this.setupKinetic('digitizerBlock'+i);
                    for(j=0; j<16; j++){
                        if(data.hosts['collector0x' + i.toString(16)].digitizers[j]){
                            this.digitizerCells[i][j] = new Kinetic.Rect({
                                x:collectorGutter/2 + j*this.width/16,
                                y:this.height*0.6,
                                width: collectorWidth,
                                height:this.height*0.2,
                                fill:'#555555',
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.digitizerCells[i][j].on('mousemove', this.moveTooltip.bind(this) );
                            this.digitizerCells[i][j].on('mouseover', this.writeDigitizerTooltip.bind(this, j) );
                            this.digitizerCells[i][j].on('mouseout', this.writeDigitizerTooltip.bind(this, -1));
                            this.mainLayer[i+1].add(this.digitizerCells[i][j]);

                            this.localMSC[i][j] = [];
                        } else{
                            //terminate loose cord with red x
                            xLeft = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            xRight = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            this.mainLayer[i+1].add(xLeft);
                            this.mainLayer[i+1].add(xRight);
                        }

                    }

                    //cabling:
                    this.collectorCables[i] = [];
                    for(j=0; j<4; j++){
                        this.collectorCables[i][j] = [];
                        this.collectorCables[i][j][0] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[i+1].add(this.collectorCables[i][j][0]);
                        this.collectorCables[i][j][0].moveToBottom();
                        for(k=1; k<5; k++){
                            this.collectorCables[i][j][k] = new Kinetic.Line({
                                points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*j+k-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.collectorCables[i][j][k]);
                            this.collectorCables[i][j][k].moveToBottom();
                        }
                    }
                    this.mainLayer[i+1].draw();

                }

                //build the MSC table in per-digitizer chunks
                //this.localMSC[collector index][digitizer index][ADC index] = channel name
                for(i=0; i<data.MSC.MSC.length; i++){
                    M = (parseInt(data.MSC.MSC[i],10) & 0xF000) >> 12;
                    S = (parseInt(data.MSC.MSC[i],10) & 0x0F00) >> 8;
                    C = parseInt(data.MSC.MSC[i],10) & 0x00FF;

                    this.localMSC[M][S][data.MSC.chan[i]] = data.MSC.MSC[i];
                }

            },

            'setupKinetic' : function(targetID){
                var i = this.stage.length;
                //point kinetic at the div and set up the staging and layers:
                this.stage[i] = new Kinetic.Stage({
                    container: targetID,
                    width: this.width,
                    height: this.height
                });
                this.mainLayer[i] = new Kinetic.Layer();       //main rendering layer
                this.scaleLayer[i] = new Kinetic.Layer();      //layer for scales / legends
                this.tooltipLayer[i] = new Kinetic.Layer();    //layer for tooltip info

                //tooltip background:
                this.TTbkg[i] = new Kinetic.Rect({
                    x:-1000,
                    y:-1000,
                    width:100,
                    height:100,
                    fill:'rgba(0,0,0,0.8)',
                    stroke: 'rgba(0,0,0,0)',
                    listening: false
                });
                this.tooltipLayer[i].add(this.TTbkg[i]);

                //tooltip text:
                this.text[i] = new Kinetic.Text({
                    x: -1000,
                    y: -1000,
                    fontFamily: 'Arial',
                    fontSize: 16,
                    text: '',
                    lineHeight: 1.2,
                    fill: '#EEEEEE',
                    listening: false
                });
                this.tooltipLayer[i].add(this.text[i]);

                this.stage[i].add(this.mainLayer[i]);
                this.stage[i].add(this.scaleLayer[i]);
                this.stage[i].add(this.tooltipLayer[i]);
            },

            'clickCollector' : function(index){
                //document.getElementById('DAQdeck').shuffleTo(index+1);
                document.getElementById('DAQnav').value = index+1;
                document.getElementById('DAQnav').onchange();
            },

            'moveTooltip': function(){
                var mousePos = this.stage[this.showing].getPointerPosition(),
                    TTwidth = this.TTbkg[this.showing].getAttr('width'),
                    TTheight = this.TTbkg[this.showing].getAttr('height');

                //adjust the background size & position
                this.TTbkg[this.showing].setAttr( 'x', Math.min(mousePos.x + 10, this.width - TTwidth) );
                this.TTbkg[this.showing].setAttr( 'y', Math.min(mousePos.y + 10, this.height - TTheight) );
                //make text follow the mouse too
                this.text[this.showing].setAttr( 'x', Math.min(mousePos.x + 20, this.width - TTwidth + 10) );
                this.text[this.showing].setAttr( 'y', Math.min(mousePos.y + 20, this.height - TTheight) );

                this.tooltipLayer[this.showing].draw();
            },

            'writeCollectorTooltip' : function(i){
                var text;

                if(i!=-1){
                    text = 'Collector 0x' + i.toString(16);
                } else {
                    text = '';
                }
                this.text[this.showing].setText(text);
                if(text != ''){
                    //adjust the background size
                    this.TTbkg[this.showing].setAttr( 'width', this.text[this.showing].getAttr('width') + 20 );
                    this.TTbkg[this.showing].setAttr( 'height', this.text[this.showing].getAttr('height') + 20 );
                } else {
                    this.TTbkg[this.showing].setAttr('width', 0);
                    this.TTbkg[this.showing].setAttr('height', 0);
                }
                this.tooltipLayer[this.showing].draw();
            },

            'writeDigitizerTooltip' : function(i){
                var text, key;

                if(i!=-1){
                    text = 'Digitizer 0x' + i.toString(16);
                    for(key in this.localMSC[this.showing-1][i]){
                        text += '\n' + key + ' 0x' + (this.showing-1).toString(16).toUpperCase() + i.toString(16).toUpperCase() + this.localMSC[this.showing-1][i][key].toString(16).toUpperCase();
                    }
                } else {
                    text = '';
                }
                this.text[this.showing].setText(text);
                if(text != ''){
                    //adjust the background size
                    this.TTbkg[this.showing].setAttr( 'width', this.text[this.showing].getAttr('width') + 20 );
                    this.TTbkg[this.showing].setAttr( 'height', this.text[this.showing].getAttr('height') + 20 );
                } else {
                    this.TTbkg[this.showing].setAttr('width', 0);
                    this.TTbkg[this.showing].setAttr('height', 0);
                }
                this.tooltipLayer[this.showing].draw();
            }
        }
    });

})();<commit_msg>setting up tooltip for DAQ<commit_after>(function(){

    xtag.register('widget-DAQ', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString, option, title, deckWrap;

                this.width = this.offsetWidth;
                this.height = window.innerHeight*0.6;
                this.showing = 0;

                //get the DAQ structure
                XHR('http://' + this.MIDAS + '/?cmd=jcopy&odb=/DAQ&encoding=json-nokeys',
                    function(res){
                        this.buildDAQ(res);
                    }.bind(this),
                    'application/json');

                //build DOM
                this.navBlock = document.createElement('div');
                this.navBlock.setAttribute('class', 'DAQnav');
                this.appendChild(this.navBlock);

                title = document.createElement('h1');
                title.innerHTML = 'DAQ';
                this.navBlock.appendChild(title);

                this.cardNav = document.createElement('select');
                this.cardNav.setAttribute('id', 'DAQnav')
                this.cardNav.setAttribute('class', 'stdin');
                this.cardNav.onchange = function(){
                    var targetIndex = parseInt(selected('DAQnav'), 10);
                    document.getElementById('DAQdeck').shuffleTo(targetIndex);
                    this.writeCollectorTooltip(-1);
                    this.showing = targetIndex;
                }.bind(this)
                this.navBlock.appendChild(this.cardNav);

                option = document.createElement('option');
                option.value = 0;
                option.innerHTML = 'Master'
                this.cardNav.appendChild(option);

                deckWrap = document.createElement('div');
                this.appendChild(deckWrap);

                xString = '<x-deck id="DAQdeck" selected-index=0>';
                xString += '<x-card id="DAQmasterCard"></x-card></x-deck>';
                xtag.innerHTML(deckWrap, xString);
                this.nCards = 1

                this.masterBlock = document.createElement('div');
                this.masterBlock.setAttribute('class', 'DAQheadNode');
                document.getElementById('DAQmasterCard').appendChild(this.masterBlock);

                this.collectorBlock = document.createElement('div');
                this.collectorBlock.setAttribute('id', 'collectorBlock');
                document.getElementById('DAQmasterCard').appendChild(this.collectorBlock);

                ////////////////////////////
                //Kinetic.js setup
                ////////////////////////////

                //indices for these arrays correspond to the x-card index on display
                this.stage = [];
                this.mainLayer = [];
                this.scaleLayer = [];
                this.tooltipLayer = [];
                this.TTbkg = [];
                this.text = [];
            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'buildDAQ' : function(response){
                var data = JSON.parse(response),
                    i, j, k, option,
                    collectorGutter = this.width*0.02,
                    collectorWidth = (this.width - collectorGutter*16) / 16,
                    xLength = collectorGutter/2,
                    xLeft, xRight, M, S, C;

                this.collectors = [];
                this.digitizers = [];
                this.collectorCells = [];
                this.localMSC = [];

                //determine what collectors are present and instantiate x-cards for each one
                for(i=0; i<16; i++){
                    this.collectors[i] = data.hosts['collector0x' + i.toString(16)];

                    if(this.collectors[i]){
                        document.getElementById('DAQdeck').innerHTML += '<x-card id="collector'+i+'">

</x-card>';
                        option = document.createElement('option');
                        option.value = this.nCards;
                        option.innerHTML = 'Collector 0x' + i.toString(16).toUpperCase();
                        this.cardNav.appendChild(option);
                        this.nCards++;

                    }
                }

                //now that the xdeck is built, paint master canvas:
                //collectors:
                this.setupKinetic('collectorBlock');
                for(i=0; i<16; i++){
                    if(this.collectors[i]){
                        this.collectorCells[i] = new Kinetic.Rect({
                            x:collectorGutter/2 + i*this.width/16,
                            y:this.height*0.6,
                            width: collectorWidth,
                            height:this.height*0.2,
                            fill:'#555555',
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.collectorCells[i].on('click', this.clickCollector.bind(this, i));
                        this.collectorCells[i].on('mousemove', this.moveTooltip.bind(this) );
                        this.collectorCells[i].on('mouseover', this.writeCollectorTooltip.bind(this, i) );
                        this.collectorCells[i].on('mouseout', this.writeCollectorTooltip.bind(this, -1));
                        this.mainLayer[0].add(this.collectorCells[i]);

                        this.localMSC[i] = []
                    } else{
                        //terminate loose cord with red x
                        xLeft = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        xRight = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        this.mainLayer[0].add(xLeft);
                        this.mainLayer[0].add(xRight);
                    }
                }

                //cabling:
                this.masterCables = [[],[],[],[]]; //1-to-4 cables: outer index counts master port, inner index counts collector
                for(i=0; i<4; i++){
                    this.masterCables[i][0] = new Kinetic.Line({
                        points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                        stroke: '#000000',
                        strokeWidth: 4
                    });
                    this.mainLayer[0].add(this.masterCables[i][0]);
                    this.masterCables[i][0].moveToBottom();
                    for(j=1; j<5; j++){
                        this.masterCables[i][j] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*i+j-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[0].add(this.masterCables[i][j]);
                        this.masterCables[i][j].moveToBottom();
                    }
                }
                this.mainLayer[0].draw();

                //and again for each collector card
                this.digitizerCells = [];
                this.collectorCables = [];
                for(i=0; i<16; i++){
                    this.digitizerCells[i] = [];

                    if(!this.collectors[i]) continue;

                    this.setupKinetic('digitizerBlock'+i);
                    for(j=0; j<16; j++){
                        if(data.hosts['collector0x' + i.toString(16)].digitizers[j]){
                            this.digitizerCells[i][j] = new Kinetic.Rect({
                                x:collectorGutter/2 + j*this.width/16,
                                y:this.height*0.6,
                                width: collectorWidth,
                                height:this.height*0.2,
                                fill:'#555555',
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.digitizerCells[i][j].on('mousemove', this.moveTooltip.bind(this) );
                            this.digitizerCells[i][j].on('mouseover', this.writeDigitizerTooltip.bind(this, j) );
                            this.digitizerCells[i][j].on('mouseout', this.writeDigitizerTooltip.bind(this, -1));
                            this.mainLayer[i+1].add(this.digitizerCells[i][j]);

                            this.localMSC[i][j] = [];
                        } else{
                            //terminate loose cord with red x
                            xLeft = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            xRight = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            this.mainLayer[i+1].add(xLeft);
                            this.mainLayer[i+1].add(xRight);
                        }

                    }

                    //cabling:
                    this.collectorCables[i] = [];
                    for(j=0; j<4; j++){
                        this.collectorCables[i][j] = [];
                        this.collectorCables[i][j][0] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[i+1].add(this.collectorCables[i][j][0]);
                        this.collectorCables[i][j][0].moveToBottom();
                        for(k=1; k<5; k++){
                            this.collectorCables[i][j][k] = new Kinetic.Line({
                                points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*j+k-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.collectorCables[i][j][k]);
                            this.collectorCables[i][j][k].moveToBottom();
                        }
                    }
                    this.mainLayer[i+1].draw();

                }

                //build the MSC table in per-digitizer chunks
                //this.localMSC[collector index][digitizer index][ADC index] = channel name
                for(i=0; i<data.MSC.MSC.length; i++){
                    M = (parseInt(data.MSC.MSC[i],10) & 0xF000) >> 12;
                    S = (parseInt(data.MSC.MSC[i],10) & 0x0F00) >> 8;
                    C = parseInt(data.MSC.MSC[i],10) & 0x00FF;

                    this.localMSC[M][S][data.MSC.chan[i]] = data.MSC.MSC[i];
                }

            },

            'setupKinetic' : function(targetID){
                var i = this.stage.length;
                //point kinetic at the div and set up the staging and layers:
                this.stage[i] = new Kinetic.Stage({
                    container: targetID,
                    width: this.width,
                    height: this.height
                });
                this.mainLayer[i] = new Kinetic.Layer();       //main rendering layer
                this.scaleLayer[i] = new Kinetic.Layer();      //layer for scales / legends
                this.tooltipLayer[i] = new Kinetic.Layer();    //layer for tooltip info

                //tooltip background:
                this.TTbkg[i] = new Kinetic.Rect({
                    x:-1000,
                    y:-1000,
                    width:100,
                    height:100,
                    fill:'rgba(0,0,0,0.8)',
                    stroke: 'rgba(0,0,0,0)',
                    listening: false
                });
                this.tooltipLayer[i].add(this.TTbkg[i]);

                //tooltip text:
                this.text[i] = new Kinetic.Text({
                    x: -1000,
                    y: -1000,
                    fontFamily: 'Arial',
                    fontSize: 16,
                    text: '',
                    lineHeight: 1.2,
                    fill: '#EEEEEE',
                    listening: false
                });
                this.tooltipLayer[i].add(this.text[i]);

                this.stage[i].add(this.mainLayer[i]);
                this.stage[i].add(this.scaleLayer[i]);
                this.stage[i].add(this.tooltipLayer[i]);
            },

            'clickCollector' : function(index){
                //document.getElementById('DAQdeck').shuffleTo(index+1);
                document.getElementById('DAQnav').value = index+1;
                document.getElementById('DAQnav').onchange();
            },

            'moveTooltip': function(){
                var mousePos = this.stage[this.showing].getPointerPosition(),
                    TTwidth = this.TTbkg[this.showing].getAttr('width'),
                    TTheight = this.TTbkg[this.showing].getAttr('height');

                //adjust the background size & position
                this.TTbkg[this.showing].setAttr( 'x', Math.min(mousePos.x + 10, this.width - TTwidth) );
                this.TTbkg[this.showing].setAttr( 'y', Math.min(mousePos.y + 10, this.height - TTheight) );
                //make text follow the mouse too
                this.text[this.showing].setAttr( 'x', Math.min(mousePos.x + 20, this.width - TTwidth + 10) );
                this.text[this.showing].setAttr( 'y', Math.min(mousePos.y + 20, this.height - TTheight) );

                this.tooltipLayer[this.showing].draw();
            },

            'writeCollectorTooltip' : function(i){
                var text;

                if(i!=-1){
                    text = 'Collector 0x' + i.toString(16);
                } else {
                    text = '';
                }
                this.text[this.showing].setText(text);
                if(text != ''){
                    //adjust the background size
                    this.TTbkg[this.showing].setAttr( 'width', this.text[this.showing].getAttr('width') + 20 );
                    this.TTbkg[this.showing].setAttr( 'height', this.text[this.showing].getAttr('height') + 20 );
                } else {
                    this.TTbkg[this.showing].setAttr('width', 0);
                    this.TTbkg[this.showing].setAttr('height', 0);
                }
                this.tooltipLayer[this.showing].draw();
            },

            'writeDigitizerTooltip' : function(i){
                var text, key,
                    M = (this.showing-1).toString(16).toUpperCase(),
                    S = i.toString(16).toUpperCase(),
                    C;

                if(i!=-1){
                    text = 'Digitizer 0x' + i.toString(16);
                    for(key in this.localMSC[this.showing-1][i]){
                        C = this.localMSC[this.showing-1][i][key].toString(16).toUpperCase();
                        if(C.length == 1)
                            C == '0' + C
                        text += '\n' + key + ' 0x' + M + S + C;
                    }
                } else {
                    text = '';
                }
                this.text[this.showing].setText(text);
                if(text != ''){
                    //adjust the background size
                    this.TTbkg[this.showing].setAttr( 'width', this.text[this.showing].getAttr('width') + 20 );
                    this.TTbkg[this.showing].setAttr( 'height', this.text[this.showing].getAttr('height') + 20 );
                } else {
                    this.TTbkg[this.showing].setAttr('width', 0);
                    this.TTbkg[this.showing].setAttr('height', 0);
                }
                this.tooltipLayer[this.showing].draw();
            }
        }
    });

})();<|endoftext|>


<commit_before>/*global describe,it,before,after*/
'use strict';

var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var assert = require('assert');
var streamAssert = require('stream-assert');
var cheerio = require('cheerio');
var plugin = require('../');

var fixtures = function (glob) {
  return path.join(__dirname, 'fixtures', glob);
};

var assertCount = function(buffer, selector, num) {
  var $ = cheerio.load(buffer);
  var count = $(selector).length;
  assert.equal(count, num);
};

describe('gulp-sri-hash', function () {

  describe('plugin', function () {
    it('should know it\'s name', function () {
      assert.strictEqual(plugin.PLUGIN_NAME, 'gulp-sri-hash');
    });

    it('should be callable', function () {
      assert.strictEqual(typeof plugin, 'function');
    });
  });

  describe('plugin()', function () {

    it('should pass through null files', function (done) {
      gulp.src(fixtures('doesnotexist'))
        .pipe(streamAssert.length(0))
        .pipe(plugin())
        .pipe(streamAssert.length(0))
        .pipe(streamAssert.end(done));
    });

    it('should throw on streams', function (done) {
        gulp.src(fixtures('flat/*.html'), {buffer: false})
          .pipe(streamAssert.length(3))
          .pipe(plugin())
          .on('error', function (err) {
            assert.equal(err.message, 'Streams are not supported!');
            done();
          });
    });

    it('should bail on unsupported hashing algorithm', function () {
      assert.throws(function() {
        return gulp.src(fixtures('**/*'))
          .pipe(plugin({algo: 'invalid'}))
        ;
      }, /Hashing algorithm is unsupported/);
    });

    it('should ignore missing external files', function (done) {
      var noopFile = fixtures('flat/noop.html');
      var expectedContent = fs.readFileSync(noopFile).toString();

      gulp.src(noopFile)
        .pipe(plugin())
        .pipe(streamAssert.length(1))
        .pipe(streamAssert.first(function (file) {
          assert.strictEqual(file.contents.toString(), expectedContent);
        }))
        .pipe(streamAssert.end(done))
      ;
    });

    it('should ignore existing `integrity` attribute', function (done) {
      var ignoreFile = fixtures('flat/ignore.html');
      var expectedContent = fs.readFileSync(ignoreFile).toString();

      gulp.src(ignoreFile)
        .pipe(plugin())
        .pipe(streamAssert.length(1))
        .pipe(streamAssert.first(function (file) {
          assert.strictEqual(file.contents.toString(), expectedContent);
        }))
        .pipe(streamAssert.end(done));
    });

    describe('with absolute path resolution', function() {

      ['sha256', 'sha384', 'sha512'].forEach(function (algo) {

        it('should apply integrity hash ' + algo, function (done) {

          gulp.src([fixtures('flat/**/*.html')], {base: __dirname + '/fixtures/flat'})
            .pipe(plugin({algo: algo}))
            .pipe(streamAssert.length(3))
            .pipe(streamAssert.first(function (vinyl) {
              assertCount(vinyl.contents, '[integrity]', 2);
              assertCount(vinyl.contents, '[integrity="incorrect-but-must-not-be-altered"]', 2);
            }))
            .pipe(streamAssert.second(function (vinyl) {
              assertCount(vinyl.contents, '[integrity]', 0);
            }))
            .pipe(streamAssert.last(function (vinyl) {
              var checksum = require(fixtures('flat/checksum.json'))[algo];
              var hash = [algo, checksum].join('-');
              assert.ok(vinyl.path.match(/transform\.html$/));
              assertCount(vinyl.contents, '[integrity]', 3);
              assertCount(vinyl.contents, '[integrity="'+hash+'"]', 3);
            }))
            .pipe(streamAssert.end(done))
          ;
        });

      });

      it('should apply custom selectors', function (done) {

        gulp.src(fixtures('flat/transform.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity]', 0);
          }))
          .pipe(plugin({selector: 'script'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity]', 1);
            assertCount(vinyl.contents, 'script[integrity]', 1);
          }))
          .pipe(streamAssert.end(done))
        ;
      });

      it('should apply hashing to whitelisted prefixes', function (done) {
        gulp.src(fixtures('flat/transform.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, 'link[href^="https://secure"][integrity]', 0);
          }))
          .pipe(plugin({prefix: 'https://secure.com'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, 'link[href^="https://secure"][integrity]', 1);
          }))
          .pipe(streamAssert.end(done));
      });

    });

    describe('with relative path resolution', function() {

      ['sha256', 'sha384', 'sha512'].forEach(function (algo) {

        it('should apply integrity hash ' + algo, function (done) {

          var checksums = require(fixtures('nested/checksum.json'));
          var styleHash = checksums['style'][algo];
          var scriptHash = checksums['script'][algo];

          gulp.src(fixtures('nested/**/*.html'))
            .pipe(streamAssert.length(2))
            .pipe(plugin({algo: algo, relative: true}))
            .pipe(streamAssert.length(2))
            .pipe(streamAssert.first(function (vinyl) {
              assertCount(vinyl.contents, 'link[integrity="' + styleHash +'"]', 3);
              assertCount(vinyl.contents, 'script[integrity="' + scriptHash + '"]', 3);
              assert.ok(vinyl.path.match(/nested\/folder\/index\.html$/))
            }))
            .pipe(streamAssert.second(function (vinyl) {
              assertCount(vinyl.contents, 'link[integrity="' + styleHash + '"]', 1);
              assertCount(vinyl.contents, 'script[integrity="' + scriptHash + '"]', 1);
              assert.ok(vinyl.path.match(/nested\/folder\/html\/index\.html$/))
            }))
            .pipe(streamAssert.end(done));
        });

      });

      it('should apply custom selectors', function (done) {

        var checksum = require(fixtures('nested/checksum.json'))['script']['sha384'];

        gulp.src(fixtures('nested/folder/html/*.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity]', 0);
          }))
          .pipe(plugin({selector: 'script[data-sri-hash=1]'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity="' + checksum + '"]', 1);
          }))
          .pipe(streamAssert.end(done));
      });

    });

  });

});
<commit_msg>Test: Verify 'crossorigin' attribute is added<commit_after>/*global describe,it,before,after*/
'use strict';

var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var assert = require('assert');
var streamAssert = require('stream-assert');
var cheerio = require('cheerio');
var plugin = require('../');

var fixtures = function (glob) {
  return path.join(__dirname, 'fixtures', glob);
};

var assertCount = function(buffer, selector, num) {
  var $ = cheerio.load(buffer);
  var count = $(selector).length;
  assert.equal(count, num);
};

describe('gulp-sri-hash', function () {

  describe('plugin', function () {
    it('should know it\'s name', function () {
      assert.strictEqual(plugin.PLUGIN_NAME, 'gulp-sri-hash');
    });

    it('should be callable', function () {
      assert.strictEqual(typeof plugin, 'function');
    });
  });

  describe('plugin()', function () {

    it('should pass through null files', function (done) {
      gulp.src(fixtures('doesnotexist'))
        .pipe(streamAssert.length(0))
        .pipe(plugin())
        .pipe(streamAssert.length(0))
        .pipe(streamAssert.end(done));
    });

    it('should throw on streams', function (done) {
        gulp.src(fixtures('flat/*.html'), {buffer: false})
          .pipe(streamAssert.length(3))
          .pipe(plugin())
          .on('error', function (err) {
            assert.equal(err.message, 'Streams are not supported!');
            done();
          });
    });

    it('should bail on unsupported hashing algorithm', function () {
      assert.throws(function() {
        return gulp.src(fixtures('**/*'))
          .pipe(plugin({algo: 'invalid'}))
        ;
      }, /Hashing algorithm is unsupported/);
    });

    it('should ignore missing external files', function (done) {
      var noopFile = fixtures('flat/noop.html');
      var expectedContent = fs.readFileSync(noopFile).toString();

      gulp.src(noopFile)
        .pipe(plugin())
        .pipe(streamAssert.length(1))
        .pipe(streamAssert.first(function (file) {
          assert.strictEqual(file.contents.toString(), expectedContent);
        }))
        .pipe(streamAssert.end(done))
      ;
    });

    it('should ignore existing `integrity` attribute', function (done) {
      var ignoreFile = fixtures('flat/ignore.html');
      var expectedContent = fs.readFileSync(ignoreFile).toString();

      gulp.src(ignoreFile)
        .pipe(plugin())
        .pipe(streamAssert.length(1))
        .pipe(streamAssert.first(function (file) {
          assert.strictEqual(file.contents.toString(), expectedContent);
        }))
        .pipe(streamAssert.end(done));
    });

    describe('with absolute path resolution', function() {

      ['sha256', 'sha384', 'sha512'].forEach(function (algo) {

        it('should apply integrity hash ' + algo, function (done) {

          gulp.src([fixtures('flat/**/*.html')], {base: __dirname + '/fixtures/flat'})
            .pipe(plugin({algo: algo}))
            .pipe(streamAssert.length(3))
            .pipe(streamAssert.first(function (vinyl) {
              assertCount(vinyl.contents, '[integrity][crossorigin=anonymous]', 0);
              assertCount(vinyl.contents, '[integrity="incorrect-but-must-not-be-altered"]', 2);
            }))
            .pipe(streamAssert.second(function (vinyl) {
              assertCount(vinyl.contents, '[integrity]', 0);
            }))
            .pipe(streamAssert.last(function (vinyl) {
              var checksum = require(fixtures('flat/checksum.json'))[algo];
              var hash = [algo, checksum].join('-');
              assert.ok(vinyl.path.match(/transform\.html$/));
              assertCount(vinyl.contents, '[integrity][crossorigin=anonymous]', 3);
              assertCount(vinyl.contents, '[integrity="'+hash+'"][crossorigin=anonymous]', 3);
            }))
            .pipe(streamAssert.end(done))
          ;
        });

      });

      it('should apply custom selectors', function (done) {

        gulp.src(fixtures('flat/transform.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity]', 0);
          }))
          .pipe(plugin({selector: 'script'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity][crossorigin=anonymous]', 1);
            assertCount(vinyl.contents, 'script[integrity][crossorigin=anonymous]', 1);
          }))
          .pipe(streamAssert.end(done))
        ;
      });

      it('should apply hashing to whitelisted prefixes', function (done) {
        gulp.src(fixtures('flat/transform.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, 'link[href^="https://secure"][integrity]', 0);
          }))
          .pipe(plugin({prefix: 'https://secure.com'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, 'link[href^="https://secure"][integrity][crossorigin=anonymous]', 1);
          }))
          .pipe(streamAssert.end(done));
      });

    });

    describe('with relative path resolution', function() {

      ['sha256', 'sha384', 'sha512'].forEach(function (algo) {

        it('should apply integrity hash ' + algo, function (done) {

          var checksums = require(fixtures('nested/checksum.json'));
          var styleHash = checksums['style'][algo];
          var scriptHash = checksums['script'][algo];

          gulp.src(fixtures('nested/**/*.html'))
            .pipe(streamAssert.length(2))
            .pipe(plugin({algo: algo, relative: true}))
            .pipe(streamAssert.length(2))
            .pipe(streamAssert.first(function (vinyl) {
              assertCount(vinyl.contents, 'link[integrity="' + styleHash +'"][crossorigin=anonymous]', 3);
              assertCount(vinyl.contents, 'script[integrity="' + scriptHash + '"][crossorigin=anonymous]', 3);
              assert.ok(vinyl.path.match(/nested\/folder\/index\.html$/))
            }))
            .pipe(streamAssert.second(function (vinyl) {
              assertCount(vinyl.contents, 'link[integrity="' + styleHash + '"][crossorigin=anonymous]', 1);
              assertCount(vinyl.contents, 'script[integrity="' + scriptHash + '"][crossorigin=anonymous]', 1);
              assert.ok(vinyl.path.match(/nested\/folder\/html\/index\.html$/))
            }))
            .pipe(streamAssert.end(done));
        });

      });

      it('should apply custom selectors', function (done) {

        var checksum = require(fixtures('nested/checksum.json'))['script']['sha384'];

        gulp.src(fixtures('nested/folder/html/*.html'))
          .pipe(streamAssert.length(1))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity]', 0);
          }))
          .pipe(plugin({selector: 'script[data-sri-hash=1]'}))
          .pipe(streamAssert.first(function (vinyl) {
            assertCount(vinyl.contents, '[integrity="' + checksum + '"][crossorigin=anonymous]', 1);
          }))
          .pipe(streamAssert.end(done));
      });

    });

  });

});
<|endoftext|>


<commit_before>var helper = require('./helper');
var Queue  = require('../');
var db     = helper.knex;
var expect = helper.expect;

describe('Queue', function() {
  it('can be instantiated', function() {
    var queue = new Queue(db);
  });

  describe('#enqueue', function() {
    var queue;

    beforeEach(function() {
      queue = new Queue(db);
    });

    it('records the job in the DB', function(done) {
      var job_data = {
        example: 'job metadata'
      };

      queue
        .enqueue('job type here', job_data)
        .asCallback(function(err) {
          expect(err).to.not.exist();

          db
            .select()
            .from('jobs')
            .asCallback(function(err, jobs) {
              expect(err).to.not.exist();

              expect(jobs).to.have.length(1);

              expect(jobs).to.deep.equal([
                {
                  id:       jobs[0].id,
                  job_type: 'job type here',
                  data:     '{"example":"job metadata"}'
                }
              ]);

              expect(jobs[0].id).to.be.a('number');

              done();
            });
      });
    });

    context('when the job type does not exist', function() {
    });

    context('when the job type already exists', function() {
    });

    context.skip('when provided a transaction', function() {
      it('uses the transaction to insert the row', function(done) {
      });
    });
  });

  describe('#dequeue', function() {
    // pull a job off the queue
    // mark it as taken by a worker
    context('when a job type is provided', function() {
    });
  });

  describe('#requeue', function() {
    // if a worker chooses to stop working on a job
    // surrender it back to the queue
  });
});
<commit_msg>Attempting to focus<commit_after>var helper = require('./helper');
var Queue  = require('../');
var db     = helper.knex;
var expect = helper.expect;

describe('Queue', function() {
  it('can be instantiated', function() {
    var queue = new Queue(db);
  });

  describe('#enqueue', function() {
    var queue;

    beforeEach(function() {
      queue = new Queue(db);
    });

    it('records the job in the DB', function(done) {
      var job_data = {
        example: 'job metadata'
      };

      queue
        .enqueue('job type here', job_data)
        .asCallback(function(err) {
          expect(err).to.not.exist();

          db
            .select()
            .from('jobs')
            .asCallback(function(err, jobs) {
              expect(err).to.not.exist();

              expect(jobs).to.have.length(1);

              expect(jobs).to.deep.equal([
                {
                  id:       jobs[0].id,
                  job_type: 'job type here',
                  data:     '{"example":"job metadata"}'
                }
              ]);

              expect(jobs[0].id).to.be.a('number');

              done();
            });
      });
    });

    context.skip('when provided a transaction', function() {
      it('uses the transaction to insert the row', function(done) {
      });
    });
  });
});
<|endoftext|>